Abandoning traditional constructors and all their strange special-cased rules in favor of regular old class methods that return Self was one of Rust’s best design decisions, I think. Super easy to reason about. Glad to see similar techniques being advocated for other languages.
I appreciate the motivation of the author but the examples of this blog do not convince me at all. For every situation, there would be an alternative (with init or not) that addresses the design issues. The first example is solved with namedtuple[1] which is not a recent feature. Then the rest of article is about IO. Although, the special methods for the context managment interface and the std lib for context managment (which do a great job at async btw) are not mentioned.
__init__ in Python already has a lot of alternatives. IMO a situation encountered similar to the example is when you do not take advantages of the alternatives or your code design is bad.
Also, specifically for this case, if I need an object for this IO operation, I __would not__ uses dataclass. The first solution would be to create a context manager[2] and a NamedTuple (or dataclass if needs some mutations).
If it's not a fit, the classmethod and the dunders __enter__, __exit __ are good if this fd implementation is important for the design of my object. Alternatively, I would just make a builder function outside my object if the implementation of the fd capability should be considered as extra and not a builtin for the object.
The dataclass decorator could be added to save 1 line of code but would confuse the intent of the object which is a content manager with some state management.
A side geniune question, why not a type[3] statement to alias the int as a fd? What is the difference with using NewType[3]? In which situation creating a NewType from a base type - here int - is useful?
Abandoning traditional constructors and all their strange special-cased rules in favor of regular old class methods that return Self was one of Rust’s best design decisions, I think. Super easy to reason about. Glad to see similar techniques being advocated for other languages.
The recommendations in this article can be summarized as "gawdy makeup on a pig".
Using @classmethod to create functions that return class instances honestly feels too much like Java and the class factory method pattern.
I don't agree with the blanket policy of banning __init__ methods
I appreciate the motivation of the author but the examples of this blog do not convince me at all. For every situation, there would be an alternative (with init or not) that addresses the design issues. The first example is solved with namedtuple[1] which is not a recent feature. Then the rest of article is about IO. Although, the special methods for the context managment interface and the std lib for context managment (which do a great job at async btw) are not mentioned.
__init__ in Python already has a lot of alternatives. IMO a situation encountered similar to the example is when you do not take advantages of the alternatives or your code design is bad.
Also, specifically for this case, if I need an object for this IO operation, I __would not__ uses dataclass. The first solution would be to create a context manager[2] and a NamedTuple (or dataclass if needs some mutations). If it's not a fit, the classmethod and the dunders __enter__, __exit __ are good if this fd implementation is important for the design of my object. Alternatively, I would just make a builder function outside my object if the implementation of the fd capability should be considered as extra and not a builtin for the object. The dataclass decorator could be added to save 1 line of code but would confuse the intent of the object which is a content manager with some state management.
A side geniune question, why not a type[3] statement to alias the int as a fd? What is the difference with using NewType[3]? In which situation creating a NewType from a base type - here int - is useful?
[1]: https://docs.python.org/3/library/collections.html#collectio... [2]: https://docs.python.org/3/library/contextlib.html#contextlib... [3]: https://docs.python.org/3/reference/simple_stmts.html#type [4]: https://docs.python.org/3/library/typing.html#typing.NewType
I don’t get it. His final solution doesn’t read from integers, which was the whole reason to go on the journey to look for an alternative to init.