A glimpse of AOP
AOP or Aspect Oriented Programming is just another programming paradigm that you may have heard of but never probably applied it anywhere or found a use for it. AOP is usually present as a small topic in a good deal of basic programming courses with a small theoretical part highlighting it. People skim through the topic and probably never use it again. I personally think AOP is kind of underrated and underutilized concept which could be helpful in different ways and I will hopefully will try to enlighten you with what AOP is and how could it be helpful to you as a programmer.
How can AOP be helpful to me?
Let’s imagine you want to log a message inside your methods :
Example: Logging without AOP:
package aop.forum.model;
.
.
import java.util.logging.Level;
import java.util.logging.Logger;
class Forum {
private final static Logger LOGGER =
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
public void deletePost(Post post) {
LOGGER.log(Level.INFO, "Delete post is going to be implemented");
posts.remove(post);
}
}
If you have to do this in a lot of places, the logging would become a part of your business logic. You would have to inject all the logging dependencies in your methods. Since logging is nothing that a business logic should care about, this is an example of a non-functional requirement
With AOP, the code inside your model would know nothing about logging. It will just concentrate on the business logic.
Example: Logging with AOP (your class):
package aop.forum.model;
Public class Forum {
public void deletePost(Post post) {
posts.remove(post);
}
}
Where did your logging go away then? Well, the logging is now done from an AOP aspect. It’s just a class tagged with @aspect and a method that implements the specific action, before advice. The expression after the @before tag tells the AOP framework to which method calls this action should be applied. It’s called pointcut expression and has many possibilities, even for complex scenarios.
Example: Logging with AOP (aspect):
package aop.forum.logging;
.
.
.
.
import java.util.logging.Level;
import java.util.logging.Logger;
@Aspect
Public class LoggingAspect {
@Before("execution(public void aop.forum.deletepost())
public void logDeletePost() {
LOGGER.log(Level.INFO, "Delete post is going to be implemented");
}
}
This was just a basic Overview of what you can do with AOP but to actually understand the concept let’s start with a cookie cutter definition of Aspect Oriented Programming (that I have to admit I ripped from Wikipedia because it was on point) -“In computing, aspect-oriented programming (AOP) is a programming paradigm that aims to increase modularity by allowing the separation of cross-cutting concerns. It does so by adding additional behavior to existing code (an advice) without modifying the code itself, instead separately specifying which code is modified via a “pointcut” specification. This allows behaviors that are not central to the business logic (such as logging) to be added to a program without cluttering the code, core to the functionality”.
Now this does consist of some terms like – cross-cutting concerns, advice and pointcut which are essential to understanding AOP and applying it. Let’s go through them briefly, and then we can jump back into AOP more equipped than before.
Concerns in programming are the different parts of a system that are differentiated on the basis of functionality. A concern can be as general as “the details of the hardware for an application”, or as specific as “the name of which class to instantiate”. SoC(Separation of concerns) is also a common term that is associated with concerns which promotes modularity by separating these concerns. Layered designs in information systems are embodiment of separation of concerns (e.g., presentation layer, business logic layer, data access layer, persistence layer). The concerns representing single and specific functionality for primary requirements are known as core concerns for example business logic. On the contrary cross-cutting concerns are aspects of a program that affect other concerns. These concerns often cannot be cleanly decomposed from the rest of the system in both the design and implementation, and can result in code duplication, significant dependencies between systems, or both. For example-Caching, Configuration management, Auditing, Security, Exception management, Logging etc. If writing an application for Medical Records, the bookkeeping and indexing of such records is a core concern, while logging a history of changes to the record database or user database, or an authentication system, would be cross-cutting concerns since they touch more parts of the program.
This figure represents a typical application that is broken down into modules. Each module’s main concern is to provide services for its particular domain. However, each of these modules also requires functionalities such as security logging and transaction management. An example of crosscutting concerns is “logging,” which is frequently used in distributed applications to aid debugging by tracing method calls. Suppose we log at both the beginning and the end of each function body. This will result in crosscutting all classes that have at least one function.
Now back to AOP with all the knowledge you gained until now and your power of patience. You probably now have many loose threads in your mind that are in dire need to connect, well let us do that now. When I talked about increasing modularity using AOP, you probably would have thought “Hey! Object-Oriented Programming (OOP) basically does the same” (no! I cannot read your mind). Well, AOP complements OOP by separating of concerns (SoC) making a software easier to maintain by grouping features and behavior into manageable parts which all have a specific purpose and business to take care of. Just like discussed before Caching, Configuration management, Auditing, Security, Exception management, Logging in a software are those features and behavior that are grouped into manageable parts which have a specific purpose and business to take care of.
OOP already allows for modularizing concerns into distinct methods, classes and packages. However, some concerns are difficult to place as they cross the boundaries of classes and even packages. One example for such a cross-cutting concern is security: AOP enables you to move the security (or any other) aspect into its own package and leave the other objects with clear responsibilities, probably not implementing any security themselves. This could imply that you do not need to mix code snippets related to security into the actual business logic of different methods.
The terminologies I am using are general terms used in concern with AOP but some specific terms in relation to the programming are of Java. Aspects are the backbone of AOP which are basically the classes which implement the application’s cross-cutting concerns(transaction, logger etc). In Java these are just normal classes with an annotation @Aspect. Join point, pointcut and advice are three interrelated concepts. Joinpoint is simply a point of execution of the program, such as the execution of a method or the handling of an exception.Pointcut is a predicate or expression that matches join points. Advice is associated with a pointcut expression and runs at any join point matched by the pointcut. Advice is the actual job which is meant to be done by an Aspect or it can be defined as the action taken by the Aspect at a particular point. There are five types of Advice namely: Before, After, Around, AfterThrowing and AfterReturning as understood by the names:
- Before: Runs before the advised method is invoked. It is denoted by @Before annotation.
- After: Runs after the advised method completes regardless of the outcome, whether successful or not. It is denoted by @After annotation.
- AfterReturning: Runs after the advised method successfully completes ie without any runtime exceptions. It is denoted by @AfterReturning annotation.
- Around: This is the strongest advice among all the advice since it wraps around and runs before and after the advised method. This type of advice is used where we need frequent access to a method or database like- caching. It is denoted by @Around annotation.
- AfterThrowing: Runs after the advised method throws a Runtime Exception. It is denoted by @AfterThrowing annotation.
You can use these advices according to different requirements and the respective AOP framework can hijack the executing method, and add extra functionality before or after the method execution.
I fumbled upon AOP due to necessity- we needed an auditing functionality that could record some really specific information like the logged-in user who executed a specific set of methods, the status, responses etc. When the method was called these specific set of parameters could be stored in db using the aspects that intercepted these methods on execution. The data stored in db could be retrieved using Logstash, analysed using Elastic search and visualised using Kibana providing a full fledged auditing functionality. I made aspects in Java which has AOP frameworks like AspectJ, SpringAOP but there are many ways to handle these cross-cutting concerns in different languages- a small research could help you out. AOP seemed something really useful to me and, something I wanted to log and share. Hope you were able to get a glimse of Aspect oriented programming.