This article is originally written on here on Mar 20, 2017
You will find a term Cross-cutting Concern every time you search for what is AOP. It means, literally, “I think I should log at here, here and here” or “All these point, values should be validated as those are from user input”.
Let’s look at an example below. I wrote a “hello world” AOP use case example. It is a simple code which gets
book name from
Now I want to log every time the function is called. And It’ll be better if it can handle the request from cache. Oh! and don’t forget to validate the
ISBN as the value is from user input. Our work as a developer won’t finish simply. How will the code change if we add codes for caching, validating and so on?
I think some
then().then().then() will be added and the code will be getting uglier and uglier and I won’t write an example for this :(. I am disappointed with my code, sitting in front of my laptop watching the code gets longer and uglier. I just wanted to get a book name. How come the work so complicate? Is the
BookCollection class name right one? How can I fix this?
Find one reason to change and take everything else out of the class.
Reminding what uncle bob said, Let’s try to separate it into several classes.
Hm… It’s better. But is this really the best? Sure we can make it better with the power of OOP. But eventually, we will end up with creating long class names and complex inheritances.
It looks cleaner! The
BookCollection focus on getting data. And logging resides on separated class. This time let’s add
Yey! The irrelevant code in
BookCollection has been reduced and its role looks obvious. In this way, you can gradually increase Aspect. And no matter how much Aspect is added,
BookCollection will only have code for its role. In addition, note that the name pattern above can be applied to various classes and methods, given the expression
/^get.*/. Even if more classes need to perform common operations, they can be applied to all of them without increasing the number of lines of code.
To explain again, we have separated logging, caching, etc. that correspond to Cross-cutting Concern of Collection classes. At this point, if you are wondering if this code is really working this way, go to aspect.js and follow the example. And don’t forget Babel and Decorator plugin.
The above code creates a Proxy of the
BookCollection prototype and executes the log only when a function of the given pattern is executed. If you are not familiar with Proxy, I recommend that you read the article “ES6 Features — 10 Use Cases for Proxy”. Now, let’s change the code by using Decorators to bind the Logger and BookClass.
Don’t panic about
@wove above is exactly the same code as the code below.
If you want to understand a little more about Descriptors, let’s read Decorators, Decorators, and functions. Decorators are on the Stage2 Draft, and there are many discussions in the current standard. So, please consider that there is room for future changes. Back in the code above, this is to show how it works and is different from the code provided by aspect.js. If you understand how it works so far, I think it would be enough to imagine how the code I introduced with AOP would work.
- OOP Is Not Your Hammer
- Intro to Aspect Oriented Programming
- TC39 Notes, July 28 2016
- Decorators and functions
- Implement new decorator proposal when finalized
- eWeek — You Down with AOP?
- Suns Gosling — The dangers of aspect-oriented programming
Originally published at medium.com on March 20, 2017.