4 ms·
I think you are being completely unfair here. AOP in Java (and .NET) is a metaprogramming facility that has few equivalents in other languages. The closest th
by rclayton 6y ago
I think you are being completely unfair here. AOP in Java (and .NET) is a metaprogramming facility that has few equivalents in other languages. The closest thing that comes to it is macros, but those are often compile time modifications.
More importantly, nothing about standard Java development requires The use of AOP.
- lmm 6y ago> AOP in Java (and .NET) is a metaprogramming facility that has few equivalents in other languages. The closest thing that comes to it is macros, but those are often compile time modifications. You don't need macros to achieve what grandparent was talking about - handling cross-cutting concerns like logging or transaction boundaries without being too intrusive. In a language that lets you do a half-decent monad implementation (which is pretty much any language that has higher-kinded types and first-class functions, although do notation can be a useful enhancement), you can comfortably write this kind of thing in plain old code. (I do those very things - transaction boundaries and logging - in Scala all the time). > More importantly, nothing about standard Java development requires The use of AOP. And yet, in real-world Java development, people feel the need to use AOP. In my 10+ years of JVM work in companies large and small, I don't think I saw a single one that didn't use some form of AOP. That should tell you something.
- mping 6y agoIf I give you a jar (or equivalent) of my compiled app, can you still apply cross cutting concerns (over compiled code you may not own)? Because that's what AOP and bytecode transformation can do.
- lmm 6y agoYou can't insert them at completely arbitrary points in third-party code. But libraries can be written generically (in terms of e.g. a general monad) so as to propagate cross cutting concerns from your callbacks to the right place, even when those concerns are implemented later on and the library doesn't know about them. Look at e.g. fs2 and http4s: everything's written generically in terms of some F[_] type which the user supplies when they use the library, and it will all be plumbed through correctly. So if you want logging, you use something like treelog as your F[_] type; if you want transactions, you include a transaction type in there. And so on. In my experience that covers almost all the use cases, while it means that library code can still behave predictably and be understood and tested (e.g. you don't have to worry that a library upgrade is going to break your application, which you do if you've used AOP to define pointcuts deep in its internals).
- mping 6y agoI'm not familiar with scala but will take a look. Completely agree over your last point. I very much prefer libraries over frameworks, and as you said pointcuts are a bit fragile, but my main point is that they behave differently because of bytecode transforms.
- pkphilip 6y agoI have done a LOT of development using Spring and have very rarely used AOP. I don't think it is a complex technology to work with though.
- vidarh 6y agoAOP is doable in most languages that allows very basic levels of runtime instrospection and manipulation of objects and types, and is easy in a large number of them. In Ruby, for example, "alias_method", "define_method" and "send" is sufficient to implement cross-cutting in a handful lines of code, and at least one generic gem exists that provides basic cross-cutting in a generic way. But it's very rarely done because it's generally cleaner to pass down code for the library to explicitly call. I used to be very excited about AOP, but in effect while AOP can be great as a debugging facility (e.g. ability to inject logging at any point for example), when you have control over the design it tends to be better to explicitly build code so that it is designed to accommodate user provided functionality. In Ruby that tends to involve e.g. the ability to pass in blocks a lot of places.