Question, is there anything decorators can do that higher order functions and higher order classes cannot already accomplish?
I typically dislike decorators because they are spooky action at a distance, and whenever I look at code in a language that has decorators, the code almost becomes a DSL of sorts.
Not that HoF and HoC don't tend towards the same problems, React used to be famous for how often HoC got used in the ecosystem and the confusion that caused!
Functions can return new class definitions- the "class" keyword represents an expression, not a statement.
As such, you could write a function that takes in as an argument a class, and return a new class definition that extends the argument you provided... Or any number of other dubious practices.
Can't fathom why annotation are used for this, except maybe as a holdover from years ago when Java didn't have certain language features. Other approaches in Java are much nicer and involve zero annotations. Example (from the Spark Java microframework documentation):
All your endpoints concisely and composibly mapped out in code, and not smeared across dozens or hundreds of methods and classes. Not an annotation in sight; just plain old Java.
The code I posted above is used for client side apps, not server side. Client code typically has to accommodate calling different systems that use different patterns so having more flexibility in mapping endpoints to results is more important.
I think some people want things to be DSL-like. However, I don’t think, long-term, using a DSL-like syntax wins. Ruby was famous for abusing Ruby’s unique syntax to make everything into a DSL and it turned off newcomers. Similarly, Java’s DI frameworks meet a lot of resistance because of their heavy use of annotations. Ultimately, DSLs are separate languages. Most people don’t want to learn a new language.
In my experience as someone who has worked with dozens of new Ruby developers, I think the ability to create expressive DSLs was a significant net positive. It was much more likely to be a source of excitement than something that turned newcomers off. I don't think DSLs are or were a problem for Ruby (nor do I think they count as "abusing syntax").
The countless users of popular third-party frameworks are the opposite of a “experienced, cohesive team” so I agree with you that it can and has caused problems there.
The EcmaScript implementation of decorators is quite nice—it’s just syntactic sugar for a higher-order function call. Much better than the spooky reflection-based approach you see in some other languages.
> I typically dislike decorators because they are spooky action at a distance, and whenever I look at code in a language that has decorators, the code almost becomes a DSL of sorts.
Yes, decorators are not evil by themselves, but they allow people to make poor choices easier. Having to debug decorators, fiddling with order of execution + scope binding/closures when setting multiple decorators, can (not sure!) become a nightmare; depending on the code base. Or we just go straight to the hibernate spaghetti. Imagining having to use three decorators with the same name, but different functions, makes me not to want to work with this.
Having worked with (old) Java EE and Jakarta code bases, I've seen decorators being abused in 300 ways and breaking ABI in 600 ways, so let's hope we stay sane this time.
They're the same, but decorators encourage a programming style that is much easier to follow than HOF do. This way of using them is pretty standard in Python and it works well, imo.
I typically dislike decorators because they are spooky action at a distance, and whenever I look at code in a language that has decorators, the code almost becomes a DSL of sorts.
Not that HoF and HoC don't tend towards the same problems, React used to be famous for how often HoC got used in the ecosystem and the confusion that caused!