10 ms·
Aspect-Oriented Programming
- kgeist 3y agoI've seen the classic examples of AOP being used to log or authorize, but you can easily do that without "cluttering your code" by using the decorator pattern? Decorators are also nestable (when you want to both log and authorize).
- rjbwork 3y agoDecorators are one implementation of how to do some kinds of AOP afaik? If you look at a system like PostSharp or AspectJ, they do it via attributes which modify the way in which a method is invoked, or even if it is invoked by the system. There are other ways to use those systems, by programmatically targeting parts of code to modify via reflection, but that is the simplest and most common.
- toolslive 3y agoYou start with reification of some part of your system/codebase. Once you have that, it's easy to adapt things. For example, in an OO context, once you've objectified your method call instance into an object that has reference to the caller, callee, parameters and the code to execute it's easy to log it, decide if the caller needs to be authorized aso... The are some other considerations like when (compilation time, run time, ...) It's a really interesting code organization strategy and the only problem I've experienced with it is that (for example decorators) introduce a static layering (the order of the decorators) that works against the inter-aspect dynamics. For example, a call only needs to be logged if there is a necessity of authentication in a distributed context. In essence, you might not be able to have a static ordering that works for use cases. (security on top, or on the bottom ?)
- jillesvangurp 3y agoWhich would be a form of AOP that mostly emerged after the AOP hype of the late nineties. I was looking at things like aspect oriented programming and subject oriented programming around 1999-2000 time frame as part of my phh d thesis work. There were a few interesting derivatives. The main aspectj work sort of folded into the spring framework which still uses some parts of that as part of the annotation processing in e.g. hibernate. That's the main reason, it bundles byte code manipulation libraries. So it can weave in some aspects. But most of the aspectj language level features never really became a mainstream thing. Decorators, annotations, and similar language constructs emerged as a good enough thing that did most of what AOP was trying to accomplish. Python added those around 2003. Java gained annotations with Java 1.5 which was a few years after that. Other languages use macros or similar features to achieve the same thing. Mostly good enough though IMHO people over use them. BTW. if you are into functional programming, this should feel really wrong. Basically you are deliberately adding side effects to your code by saying around or before/after a call to this, also do that. Of course the goto functional programming solution of monads has its own issues in terms of complexity, philosophical debates, and people having a hard time understanding them. The researchers in Utrecht where I studied in the mid nineties were into monads big time. My compiler course was basically about the compiler generator technology they were working on. Monads top to bottom. I liked aspectj a lot better after that. Easier to grasp for my primitive brain.
- asplake 3y ago> BTW. if you are into functional programming, this should feel really wrong. Basically you are deliberately adding side effects to your code by saying around or before/after a call to this, also do that. A decorator in Python (and I guess other languages) is a nothing but a function of a function. And you’re taking those side effects out of your function. What’s not to like?
- jillesvangurp 3y agoYou are confusing the implementation and the syntax. It's a special syntactical construct (an annotation) that gets translated into function calls that amount to doing AOP type things around the call to the original function. That's more or less how annotations work in other languages too. Some do it with reflection, some do it at compile time, etc. The goal is the same: get rid of the drudgery of spelling out the function call in order to introduce the side effect in the form of a thing that gets called before/after/around another thing. Not against that btw. and I always appreciated how pragmatic python can be with a lot of things.
- deleted 3y ago[deleted]
- lmm 3y ago> A decorator in Python (and I guess other languages) is a nothing but a function of a function. And you’re taking those side effects out of your function. What’s not to like? A Python decorator may be "just a function", but in order to do anything useful it generally has to do some kind of nasty hack - mutable state, global state, monkeypatching or the like - because the meat of what a decorator does usually lies in what happens when you call a decorated function, not in when you define it.
- snarfy 3y agoI created an AOP library for .net core. It uses the decorator pattern. Aspects are attributes you apply to classes and methods. It was fun to implement. It was all the rage in game programming. I never used it myself. As all of the other comments have mentioned, it ends up being a kind of anti-pattern. Nobody wants logic strewn about your code base. It might as well be called side-effect based programming.
- lastangryman 3y agoAh this takes me back to my first job. Medical start up, working on a very long term project that the company was completely unequipped to deliver. I was young and keen so didn't appreciate the context, I just did stuff. For some reason, we hired an "architect" from a large Bank that used Java. He used to make proclamations like "we should write tests", but never actually got into more detail than that. One of his preachings was about aspect oriented programming and how it was going to be future. He did a talk on it, and I remember someone asking "what else does it apply to apart from logging and Auth?"...no answer. Not long after, I left. 2 years there, probably over 15 engineers, I don't think we built anything close to a functioning software product.
- rjbwork 3y agoCaching, managing object life times in IOC containers, input validation, are some common uses I've seen.
- lastangryman 3y agoThanks - I'm sure there are other uses cases, I didn't mean to imply there weren't, just for me I always associate AOP with a time in my career where nothing useful was ever shipped, but there was lots of pontificating and philosophising about rather abstract things like this.
- retrocryptid 3y agoLol. I associate C++ with that. Turns out the first big C++ project I was involved with had a lot of research types. To their credit, when they did something it was almost always the best thing to do. But there was A LOT of thought and discussion put into each line of code. For a decade I thought about C++ as being "the language for people who are forced to think long and hard about every line of code." And then I saw "normal" C++ code everyone else was writing... I now sort of like it (C++), especially after recent language additions.
- speed_spread 3y agoTransaction coordination, Error management (retry, backoff, fallback). In the end, aspects were always used for the same transversal concerns, which any serious framework would provide explicit support for anyway. Going beyond these to use aspects for application domain modeling is popping open an immense can of carnivorous worms on the dev team.
- barbariangrunge 3y agoQuestion: how do you think the binding of isaac lets you mix and match so many abilities? The number of item/effect synergies is really striking in that game. Is it a series of decorators, or something AOP like? My personal theory is it's something decorator like that involves modifying something like a struct which gets converted into game effects after all the modifiers run This article just made me wonder about this again
- Traubenfuchs 3y agoI'd expect any non trivial (like changing color/size) interaction involves custom coding of a wholly new, invisible item as in "if player has item 300 and item 278, make them inactive and give him secret item 1200".
- barbariangrunge 3y agoBased on a link somebody else posted, that may be right. The number of combinations is so large though. It must have been exhausting
- Traubenfuchs 3y agoAs Binding of Isaac is a money printing machine, it was definitely worth it.
- DaiPlusPlus 3y agoThis dev-blog article from 2015 pretty-much admits that it's all done manually: https://web.archive.org/web/20151108110741/http://bindingofisaac.com/post/130107389809/32-days-to-go https://web.archive.org/web/20151108110741/http://bindingofi... > now as some of you know, item combos have to be hard coded at this point due to how nutty some of the tears are in rebirth. the most requested update you guys wanted in afterbirth was item combos, so the team has been hard at work the past few weeks mostly focusing on said combos.
- barbariangrunge 3y ago
- invalidname 3y agoA more practical explanation of stuff you can do with AOP that would be challenging otherwise: https://debugagent.com/spring-boot-debugging-with-aspect-oriented-programming-aop https://debugagent.com/spring-boot-debugging-with-aspect-ori...
- unscaled 3y agoLooking at what AOP is still used for nowadays, it's pretty clear that the killer application for AOP was always logging (and nowadays that would also include tracing). There were many other suggested use cases of course: transactions, caching, application-level security, dependency injection, retries, refactoring a legacy app... The problem with all of the other suggested use cases is that AOP was never a great fit for them. AOP is always casting a wide net, which has the following two properties: 1. False positives: It's very easy to wrap all methods in the com.myapp.* package which fit the pattern "interact*()" with some transaction manager, or to cache their result. But a few years later a hapless developer adds another "interact" method which suddenly starts to misbehave. Logging has very little impact on behavior, but most of the other use cases (even caching and retries) can greatly impact behavior, so you'd usually want more control on them. Of course, you could define a very narrow pointcut which doesn't risk a false positive — but in that case, why shouldn't you just use an annotation? 2. Large amount of join points: AOP works great to save you writing a lot of boilerplate code when you need to modify a large number of functions in a similar way. In modern programming languages you'd often use annotations (which postdate AOP, especially within Java), but even adding a single annotation on thousands of methods is tedious and error-prone. But again, out of all these use-cases, only logging really often needs to do the exact same thing for thousands of methods. Caching, Retries and Dependency Injection require more in-site knowledge that is easier to achieve and more readable with annotations: which values you want to cache, what dependencies to inject and what would be their life time and source, which retry strategy should you use, etc.
- tjansen 3y agoI am happy that AOP never really caught on. The idea of modifying the behaviour of a class in a completely different place of the source tree has always horrified me. Makes it pretty much impossible to understand code by just looking at a single file. Admittedly, IDEs were pretty rudimentary when AOP was first introduced, and today's IDEs can display aspects right where they are applied. But I still think that annotations/decorators are a far better solution for the problem that AOP tried to solve.
- pjmlp 3y agoAnyone using Python, Ruby, Java and .NET frameworks is using AOP, how much of it depends on the framework.
- whstl 3y agoYeah, I feel the same. I think that in the surface the idea was interesting, but the final implementation, with the "weaving" involving code transformation, and also the fact that there was some "inversion" of control flow (where the COMEFROM comparison comes from) weren't really good. All that flexibility was probably a good selling point, but it just wasn't necessary IMO. I think in the end things like Python decorators follow similar ideas without the problems associated. No magic, just functions. I do like that AOP helped "Cross Cutting Concern" become a common thing in development vocabulary, though.
- marcosdumay 3y ago> but it just wasn't necessary IMO AOP makes Java style logging incredibly convenient. That was not only its main selling point, but also it's one single benefit that people managed to identify during the few years it was hyped. IMO, Java style logging is bad by itself. But surely, AOP does make Java style logging much more convenient.
- TeMPOraL 3y agoI have the opposite view. AOP didn't go far enough. At this point we're reaching limits of IDE support[0] and language design. New languages have been piling up increasingly arcane mathematical abstractions to try and squeeze in a lil' bit more stuff in the same number of characters, but they too can't get past the fundamental problem: there is only so much you can fit in a piece of plaintext. You can't cover every cross-cutting concern at the same time in the same piece of code, and keep all of them easy to understand and work with. That is, we are being limited by insisting on directly authoring and manipulating source code that's plaintext and a "single source of truth". AOP solved a lot of these issues, but it was hamstrung by being deeply embedded in that "plaintext single source of truth" code workflow. It was confusing to have "spooky action at a distance" that's invisible unless you're using a properly configured IDE, but the real problem here is that we expect everything to be local in the same piece of text. If we drop that expectation - learn to work on higher-level representations of the underlying source code - then none of it is a problem anymore. AOP becomes a subset of more general techniques of authoring software systems. -- [0] - Perhaps with exception of LLMs, which promise to be able to both write heaps of code and explain what all that code does. We can probably ride quite far in that direction, but it'll also eventually hit the same wall: no more progress until we abandon the idea of working with the plaintext source code directly.
- seanparsons 3y agoI remember writing a state machine system for a project to replace Windows Workflow Foundation (shudders) using Aspect.Net (IIRC) many years ago and it working but being a faff. But then I think to something like the bracket function from Haskell: https://hackage.haskell.org/package/base-4.18.0.0/docs/Control-Exception.html#v:bracket https://hackage.haskell.org/package/base-4.18.0.0/docs/Contr... That's 2 orders of magnitude simpler and doesn't need arbitrary function definitions so a pointcut can be defined against a block of code.
- culturedsystems 3y agoThe paper linked to in the Criticism section of the article [1] is well with reading, IMO. It points out that AOP only works when there is "obliviousness of application", i.e the code to which the aspect is applied doesn't need to know about the aspect, and argues that this kind of obliviousness is pretty rare. 1: http://onward-conferences.org/2009/files/steimannessay.pdf http://onward-conferences.org/2009/files/steimannessay.pdf
- shanghaikid 3y agoDojo's aspect feature is one of my favorite feature in the framework. https://dojotoolkit.org/reference-guide/1.9/dojo/aspect.html https://dojotoolkit.org/reference-guide/1.9/dojo/aspect.html Now dojo is gone. But sometimes I still will port this feature into react/vue project.
- aspyct 3y agoOh, I made an AOP library for python when I started uni back in 2008. That's actually where my nickname comes from: aspyct (a concatenation of aspect, python and aspyc). Sadly I lost the contents of the old wiki. I did pour a lot of energy into that :) But I still have a page on my old blog: https://www.aspyct.org/aspyct/ https://www.aspyct.org/aspyct/ (funny URL though \o/) It's never been a huge hit, but from time to time I would get emails from students who were investigating it for a university project. That was fun :) Is was adding some interesting features (notably pointcuts), but ultimately it didn't bring enough added value compared to a simple decorator in python, and I ceased development. It's still available on SourceForge, for those interested: https://sourceforge.net/projects/aspyct/files/aspyct/ https://sourceforge.net/projects/aspyct/files/aspyct/ EDIT: wow that was 15 years ago. I'm not getting younger :p
- liampulles 3y agoIn my experience, it's best to keep AOP usage limited to very well defined areas. Logging is fine, making your own AOP stuff is often a recipe for overly clever code.
- voz_ 3y agoGreat way to get mired down in bullshit.
- brokenkebaby 3y agoSince I learned what is it it's been my strong feeling that AOP is a very big (and somewhat misleading) name for such a small thing
- Omroth 3y agoI was already dubious of the concept, but the account example in the page makes me even more so. "Transactions, security, and logging all exemplify cross-cutting concerns." Logging, maybe. Transactions and security? Hard disagree. And then in the example it checks for enough funds to make the withdrawal, and then makes the withdrawal, not as an atomic ation. I don't think that's just nit-picking on a simple example - how AOP interacts with atomic actions is fundamental to the use-case.
- SCdF 3y agoI did an AOP project back in ~2007, where we used crosscutting to separate the frontend from the backend, due to the belief that in the future we would swap out the thick client frontend for a web client. It was kind of a nightmare (to put it kindly). This was an insurance app where updates in the frontend would automagically be pushed into the backend algorithm, which would automagically push changes to the frontend, which would automagically push changes to the backend... The client also didn't pay for regression tests (2007 was a long time ago!) so basically every week it infinite loop locked in some new and undebuggable way.
- Simon_O_Rourke 3y agoI dabbled a bit using AOP in college, mostly trying to get software to do new things via dynamic updates. It was the most awful paradigm to use, had to develop a test harness just to figure out the configuration and control flow for experiments. For it's very niche use cases I'm sure it's interesting, for anything else it's just too difficult.
- mbork_pl 3y agoEmacs Lisp has AOP built in [0], and in this context it is extremely useful. The common use case is advising functions of a third-party library without modifying the library itself (which wouldn't survive e.g. an upgrade). This is a bit atypical, though, in that the end user is a programmer here. A blog post I wrote last year [1] is one example of advising functions sitting pretty deep in the chain of function calls to achieve something useful. That said, even the manual says [2]: > advice-add can be useful for altering the behavior of existing calls to an existing function without having to redefine the whole function. However, it can be a source of bugs, since existing callers to the function may assume the old behavior, and work incorrectly when the behavior is changed by advice. Advice can also cause confusion in debugging, if the person doing the debugging does not notice or remember that the function has been modified by advice. > For these reasons, advice should be reserved for the cases where you cannot modify a function’s behavior in any other way. [0] https://www.gnu.org/software/emacs/manual/html_node/elisp/Advising-Functions.html https://www.gnu.org/software/emacs/manual/html_node/elisp/Ad... [1] https://mbork.pl/2022-09-17_Safe_killing_with_Emacs https://mbork.pl/2022-09-17_Safe_killing_with_Emacs [2] https://www.gnu.org/software/emacs/manual/html_node/elisp/Advising-Named-Functions.html https://www.gnu.org/software/emacs/manual/html_node/elisp/Ad...
- kqr 3y agoI've always put advice (and Perl's Hook::LexWrap and other implementations) in a different bucket to aspect-oriented programming, with the idea that AOP is used to build an application and advice is used to monkey-patch around a bug that isn't yet fixed upstream. But you're right, they're similar to some degree.
- gorjusborg 3y agoAOP creates 'hidden coupling', something I found extremely common while working in java. The logic seems to be that loose coupling is better than tight coupling, and what's looser than zero coupling? It's perfect! The trouble is that zero coupling is not really possible in a working system. Instead what you've done is introduce 'hidden coupling', where one can't see the connections between components in the system from the code. Hidden coupling makes understanding and maintaining a software system much harder than it would be otherwise.
- IggleSniggle 3y agoThis is such a fantastic way to put this! Coupling is extremely important: if these two things GO together, why not make that as clear as possible? The reason we avoid tight coupling is so that our software can remain “soft.” We can continue to mould and manipulate it even as out requirements or understandings change. But software with hidden coupling might as well be the Internet. Sure, Google might crawl Wikipedia, and it provides some information as a result, and your software might rely on the result of some query. But then when your query breaks do you need to make a change to Wikipedia? That’s probably a pretty bad analogy, but it’s the way I routinely felt when I was a junior working in a “hidden coupling” software system where even knowing what queries were being made was a challenge.
- oh_sigh 3y agoIt's hidden from the perspective of code represented as individual byte stream files, but that doesn't need to be the only representation, though obviously it is the most common form. Or, your IDE could surface this information.
- gorjusborg 3y ago> It's hidden from the perspective of code represented as individual byte stream files, but that doesn't need to be the only representation This is unarguably true. However, it seems that the tooling often doesn't offer that support, or it isn't broadly known that it does. You are also marrying the tool as well as the language at that point, which might be deemed acceptable by some, but probably not all (I am not a fan of Lombok for similar reasons to why I would not be a fan of this). To me, you are better off with simpler abstractions and practices than amping up the base requirements of your developers and tooling.
- w10-1 3y agoAs others have noted, AspectJ was/is used in Spring, so it had a long, useful life. IBM also used it to layer in closed-source enterprise features on their open-source web server, particularly for error-handling. AOP/AspectJ won the space, beating out the more analytical program-slicing approaches which were incomprehensible to most. Pointcuts were more understandable than slices. It's best not to reduce AOP to interception or weaving. While "crosscutting concerns" was the animating motivation, Kiczales regretted giving any toe-hold for mechanistic ideas of AOP and removed the notion of "crosscut" or "weaving" from the language and messaging (even though load-time binary weaving was the driving feature for adoption). There were (toy) implementations in C++ et al. The core idea is that a program has well-understood places and times - where's and when's - that a language should capture as one when they have integrity while preserving language semantics. So the join point model targets programmer-understandable things (like method call or exception handling), not just anything (like loops), and preserves type-safety and access control. Similarly, type-extensions ("inter-type declarations") were binary-compatible with the original code. Unlike extensions in Swift or Objective-C, these extensions could add state to an object, which could be published or just used privately by the aspect (traits or mixin's anyone?). Aspect instances could be created staticly, one-per-instance of an object, and even once per control-flow/thread, esp. to tunnel information from high in the call stack down below (i.e., through library call-backs, if in thread). Tooling support was always a strong concern. It started with its own debugger and IDE, but was really a perfect match for Eclipse (and Java's then-new support for debug context for any language in bytecode). The Eclipse compiler beat javac by focusing on incremental builds, making Eclipse the best place to code. The compiler has always had to be forked and extended to support AspectJ, which is something of a black art. But it did mean you could browse any pointcuts in a code base, leaving some to use it for its program-slicing abilities :) Obliviousness (like private static) is the safe default, but AspectJ also supported aspect-aware code with public extensions. So there were a range of aspects, from benign observers, through essential but still oblivious security/audits, to public aspects forming feature layers in a product-family scheme. Today, Swift has many AOP-like features, and Python context managers transformed the language (so yeah, loops are sensible join points). But AspectJ was tied to Java, and all the enterprise programming-container models were careful to keep programs dependent on the containers (read: oracle databases with in-memory VM's and IBM JVMs). There's no after advice for handler join points because Java bytecode doesn't have determinate points for that. Generics and method and field handles strained the language when there has been just a few heroic maintainers. There was lots of discussion for extending the notion of control flow across threads and machines (like tracing now), but no real support in bytecode (and not enough consistency in thread models or package loading conventions to make any implementation broadly available). And there were hard problems: can you weave an already-woven class? After much analysis and discussion, the simple answer won: The original class was preserved in the woven class as an annotation (bloating the disk size, but not the size as loaded), and that was used instead of trying to unweave the woven bytecode. AspectJ survived for a long time both through careful semantics and by making a lot of pragmatic engineering decisions, in both cases stretching to make it usable for ordinary programmers. But it was always a derivative of Java, and was embraced/extended (and monetized and contained) by Spring. (Adrian Colyer was handed the project as it moved to Eclipse, and was the CTO of Spring.) https://www.eclipse.org/aspectj/doc/next/progguide/index.html https://www.eclipse.org/aspectj/doc/next/progguide/index.htm...
- larsrc 3y agoI worked on AspectJ during a summer internship at Xerox PARC i n 2000. Very interesting, but did not convince me that AOP was a good thing. They had a few good examples (logging was the big one), but added so many advanced features to support other use cases that the code ended up being very hard to understand. Same problem I have with Guice.
- yodon 3y agoIt's odd to see posts saying "Aspect-Oriented Programming never caught on." All game developers know Aspect-Oriented Programming, just not by that name, because it's at the core of one of the most successful platforms in the industry. Unity3d is a $14B company built in large part on Aspect-Oriented Programming and Aspect-Oriented Design. Every time you implement a Unity Behavior in C#, you're doing Aspect-Oriented Programming in a text editor. Every time you drag a Behavior onto a Game Object in the Unity Editor, you're doing Aspect-Oriented Programming in a graphical programming environment.
- incrudible 3y agoI have never heard of anyone referring to the Unity way of doing things as AOP, and the docs do not call it AOP. In my view, if it was AOP, you could change the behavior of all Foo instances without dragging anything on them, and without changing the definition of Foo. If anything, Unity follows the composition-over-inheritance principle.
- jonnycomputer 3y agoThe article says implemented in Python, but doesn't say how or where. Anyone know? Decorators?
- hejcloud 3y agoI think AOP is a fair tool.. for maybe 1% of of your day to day problems. I'd say it's okay to use in combination with OOP when you (and your team) manage to strictly keep the Domain/Business stuff in OOP world and the infrastructural stuff (logging) in AOP. Whenever you start mixing any of these together or have overlapping concerns, then things will quickly get very messy. While logging is fine with AOP e.g. with Access control things easily get mixed up over time. When I look back the last 1-2 decades, the pattern that I see is that one principle always won: Simplicity. I'd like to end up with a little war story: In 2017 I happened to work at a startup (~60 engineers) that started with a gazillion of Microservices in dozens of different languages and ecosystems. Then there was this Clojure guy that didn't even do that much of missionary work. When people started reading each others codebases they realized the simplicity of Clojure and later started porting/rewriting their things to it. At the same time, everything Scala was frowned upon; I vividly remember trying to understand the request a supposedly simple CRUD service was making to another service and I couldn't understand the program flow for like 2h. Needless to say that probably like 80% of the services ended up being rewritten in Clojure and the Clojure guy got called the Johnny Appleseed of the company.
- zoogeny 3y agoI recall learning about aspect-oriented programming (AOP) waaaaay back in the day. This was before inversion of control patterns and dependency injection frameworks mostly solved that problem space in the OOP languages I was dealing with. Even before that, most people just used singletons or some kind of service locater pattern. Now that I spend a lot of time using Typescript, I find I rarely have the same issues that required those solutions. I believe that is due to the module system but I'm not entirely sure. I'm trying to think of the classic AOP problems, like structured log providers. Maybe it is the standardization of logging interfaces and the fact that I can trivially write adapters that makes this a non-issue for me these days? I suppose, things like context managers [1] in React solve a similar problem space. That is probably the closest modern equivalent annoyance I can think of to the kind of problem that AOP was designed to solve. To be honest, the tools I've had available were always able to solve the problem well enough. Every AOP solution I have seen is an order of magnitude more complicated than the problem it was trying to solve. 1. https://react.dev/reference/react/useContext https://react.dev/reference/react/useContext
- thom 3y agoThere is no level of abstraction at which you can write code that won't simultaneously be too obstruse for some, and an impossible maintenance burden to others. There is no programming paradigm, language, framework or tool that is going to fix this. Fun to argue though.
- CyberDildonics 3y agowon't simultaneously be too obstruse for some, and an impossible maintenance burden to others I think you mean either abstruse or obtuse. Wouldn't something too difficult to comprehend be an impossible maintenance burden? Why would these be too different things? There is no programming paradigm, language, framework or tool that is going to fix this. Seatbelts and backup cameras in cars don't solve car accidents, but refinements are still steps forward, because systemic problems are not all or nothing.
- thom 3y agoYou are correct about my spelling, apologies and shame! Things that make low level code easier to understand and manipulate make whole systems harder to understand and manipulate. More abstractions make larger systems easier to reason about in the whole, but harder to debug at a low level. Each programmer gets angry at a different place in this spectrum. There is no refinement that helps here because every step you take is further towards one person’s taste and away from someone else’s.
- gloryjulio 3y agoThe reason react hooks get so much hate it's because that it's basically Aspect-Oriented Programming. If ur project scope is small and u don't get why you need it in the first place, then it looks weird and unintuitive. But when u work on bigger projects and u have some many shared HOCs which are stacked, they become callback hells to manage and debug. But hooks solve this cross cutting problem. It's like going from promise callback hells to async await.
- kazinator 3y agoThe joke language INTERCAL incorporated AOP. In INTERCAL, the GOTO statement is replaceed by COMEFROM. If you write a COME FROM 20 anywhere in the program, then when line 20 executes, control will invisibly pass to your COMEFROM statement. https://en.wikipedia.org/wiki/INTERCAL https://en.wikipedia.org/wiki/INTERCAL https://en.wikipedia.org/wiki/COMEFROM https://en.wikipedia.org/wiki/COMEFROM
- rektide 3y agoJavascript annotations are finally landing & they are very much enabling aop like concerns. Alas none of thr original greatness of javascript has been allowed. The new language features are all 100% special snowflake things, miles apart from the everything-is-an-object world we had. So these annotations/transforms are load-time only. They make a bunch of changes to your classes or whatever as the class loads then they are erased, invisible, totally unable to be seen unless explicitly coded. Dripping disdain for this weak ass shitty path JS has started following. We keep making invisible unreflective shit & it's all super shit. Private fields can't be reflected on at all. ESM took over half a decade to get any kind of module metadata like import.meta and there is absolutely positively none of the module registry notions we were talking up as ESM was being crafted. Everything is a huge downgrade for a runtime where you can look around & see what you have. To me, the neat spirit of AOP is when you not just attach some static annotations & compile it away, but when the runtime can keep growing new ways to be self aware. When you can keep compounding & meta-mutating. But the language design keeps shoving us down narrower more limited paths where the runtime actively tries to blind itself. There's such a huge massive narrative here on language design, & it should be in textbooks & screamed out loud, but it's invisible & unseen & the forces of conservative secure encapsulation & hiding are the only ones with any power or say & everyone else is losing. We have AOP about to happen but it's sad AOP, ignorant AOP, blind AOP. Dynamic runtime AOP is just one of many capabilities - like DI/dependency Injection - where really what we are doing is creating a powerful metaplatform for resources, for object instances (and factories). Having management over objects is intensely interesting & empowering. Declarative code is just a cheap way to explicitly wire up resources/instances, with no management layer. I loved & hope we get back to more interesting & ambitious times when object repositories become powerful interesting object generating & manipulating entities.