Aspect Oriented Programming and Cross-cutting concerns
Let’s say I’m working on an application that has “users”. First, I’m trying to design and implement business model, leaving MVC and data storage for later.
When users are registered in the application they are considered inactive until they have verified their email address.
While the DATA team is still picking the most trending data storage for the application, I implement the logging system. Basically, we need to write to log each time a new user is added:
Now, I want the administrator of the site to be able to create activated users, so that email verification is not required. The same log message should be added to the log file:
It’s not too bad now, but the duplication of code has begun. It gets worse when you’re ready to save the users set in a database:
With all the code duplication and mixing of things, I can say good bye to the nice separation of concerns.
Cross Cutting Concerns
Why are they “cross-cutting”? Because they exist in different layers of your application. They cross the boundaries, if you will. In the example above, “adding a user” may refer to three things: busines-wise adding a user, saving a new record to a RDBMS table or adding a line to a log file.
Business rules. MySql table. Log file. They are all different. Yet they are one: “adding a user”.
This is why they are “cross-cutting”. Why is it called a problem of cross-cutting concerns? Because there is no “built-in” way of solving this in classic paradigms and approaches to programming.
OOP abstractions
Having OOP abstractions helps to some degree. For instance, instead of working with database directly we introduce new concepts into the Business area. $users collection may be a “repository” still acting like an array, it may reference the database under the hood. The so-called UnitOfWork pattern helps dealing with things like DB transactions.
In reality, however, it is pretending. You can have a business requirement about users, but not about “units of work”. These are all made-up entities that you have to introduce into your design again and again to justify/hide the presence of infrastructure-related logic (db/log/…) in your Domain Layer.
Aspect Oriented Programming (AOP)
The UsersManager class is responsible not only for the business “aspect” of the application but also deals with database and logging systems. These are the three different aspects of the same activity, that should not be mixed up.
Aspect Oriented Programming is an approach that helps separating these aspects within your application. The idea is that you can store your aspects independently, while they will still be executed “at the same time” (or, you can define a particular order of execution).
As AOP contradicts the OOP in its classic definition, implementing it usually implies relying on “magic” features of a language.
In some languages it is built-in (although still doesn’t feel like it is), but in most cases it’s done by a framework, an extension or a library. In PHP, what’s worth mentioning is the Go framework by lisachenko, AOP extension for PHP and the set of tricks used in Doctrine2.
Implementations may differ depending on which tool you use, but the idea is as follows. I still have the business layer UsersManager as it was in the beginning, independent from Db and Logging:
Then I have the aspect of logging, something like this:
And the aspect of database interaction:
Then there would be some initialization logic, wiring all the aspects together:
Why doesn’t everybody use it?
There is a lack of tools at the moment, and the ones we have are limited, not convenient enough to use and hacky due to the magic features they utilize:
In theory, we may need to have aspects of any random piece of logic. With the tools we have we’re limited to having aspects of a method or a function.
Aspects should be made first-class citizens. I don’t think introducing an alias for “class” is enough.
Understanding what an AOP application does is tricky. You can’t see right away all the aspects of some code you’re looking at.
OOP requires experience, well-thought hierarchy of classes and SOLID design in order to be understood correctly. The situation is the same with AOP, but there’s not much in terms of best practices.
No IDE support. For example, we could have support for swithing between contexts on any given line of code and seeing them in some manner.
I like analogy where OOP/procedural programming is 2-dimensional while adding AOP into the equation makes it 3d. It does require better imagination.
Comments and feedback are much appreciated. See contact details here