AOP is a paradigm, not a library

There are many articles about AOP. Developers have discussed whether or not Python needs an AOP library.

Note

Aspect oriented programming is not just a library. It's a paradigm, just like object oriented programming and functional programming.

The key goal that AOP strives to solve is writing crosscutting solutions in places where OOP can't. OOP solves problems where the solution can be inherited. AOP is transversal whilst OOP is vertical. Either way, the goals are the same: "DRY (Don't Repeat Yourself)" and "obey the SRP". This also is described by the 1:1 Principle, which states that one requirement has one and only one manifestation in the implemented code. This is a combination of the DRY and SRP principles.

Developers resort to copy-and-paste style coding when it comes to adding logging, caching, transactions, etc. This code which spans across multiple service classes is repetitive and represents a single strategy. Whenever there is a change the change must be repeated everywhere, and this is risky and costly.

In our example, we used Spring Python to code an interceptor and applied it using pointcuts. This allowed us to avoid repetitive code while still keeping things simple and nicely encapsulated. This has the following benefits.

  • Any time a new method is added to WikiService, we can check the IoC configuration to see if the CachingInterceptor applies. There is only one place to check, meaning it is easy to check the pointcuts
  • We can easily tune the pointcuts without touching CachingInterceptor. This demonstrates how the advice is cleanly decoupled from the pointcuts
  • In our more complex configuration we introduced PerformanceInterceptor, where we observed which methods are taking the longest and evaluate them for caching. This was relatively easy to add, because it required no interference with the other interceptors or their pointcuts. This suggests that future updates should be relatively easy to make

With advice decoupled from pointcuts, it is easy to add new pointcuts and new advice, thereby updating our crosscutting behavior. And all of this can be done without impacting the core API we are enhancing.

We have shown that AOP supports loosely coupling solutions. We have also looked at how it is easy to easily apply advice with precision, offering high cohesion. These factors will help us by making it easy to respond to changes we know are coming.

The following diagram shows a high-level view of how the components are wired together.

AOP is a paradigm, not a library

Each interceptor has its code is cleanly wrapped by an advisor with its pointcuts, forming well defined aspects. Each aspect is also separated from the business logic of the WikiService. With this separation of concerns, it is easy to make changes with minimal risk. It is also easy to add new advisors and change the order of execution.

Distinct features of Spring Python's AOP module

Spring Python isn't the only means to code an AOP solution. There are other libraries available, such as Aspyct and aspects.py. Python's rich feature set also provides the ability to code in an AOP-like fashion, using things like meta-class programming and decorators.

It is important to note what makes Spring Python's AOP solution distinct. While I have tried to include some high-level comparison with Aspyct and aspects.py, the reader is encouraged to visit these projects and compare the features in more detail.

Difference

Description

Advice applicable to instances of objects.

Spring Python gives the developer the option of applying advice to individual instances of objects, without requiring all instances to adopt the behavior. This gives the developer maximum flexibility. The tradeoff is that if this behavior is desired for all instances, then the developer is responsible to apply it to all instances.

Aspyct allows you to define aspects and apply them to functions. The behavior permanently modifies the function, and this impacts all instances.

The ability to wrap functions around methods is offered by aspects.py. This would apply to all instances. It also supports wrapping a subset of instances in this fashion.

No metaclass programming.

For certain problems, metaclass programming may be the easiest solution. For other problems, metaclass programming isn't what is needed. It is an alternative paradigm from standard OOP and procedural development practices. In OOP, classes are templates for creating objects. Metaclasses are templates for creating classes. This means that some crosscutting problems may easily fit metaclasses programming, while other problems do not.

Spring Python's AOP solution doesn't require learning a complex concept. Instead, it is based on creating classes and using IoC to define pointcuts that apply the advice.

Don't need access to source code.

Metaclass programming requires access to the source code. So does applying decorators defined in an AOP library. Both of these options make it harder to apply advice to a 3rd party library, since developers are less likely to take on maintaining patches.

Aspyct and aspects.py don't require altering the source code. However, Aspyct's primary means of application involves using decorators, which would require access to the source code.

Considering how Spring Python leverages its IoC container to apply advice, it is easy to utilize classes from any library and apply independent advisors.

No monkey patching.

Monkey patching is where an object's functions are added, removed, or replaced at runtime. While some people consider monkey patching a valuable tool, it must be used with care. There is a certain level of associated risk with altering the class definitions of libraries, which may result in unpredictable bugs.

Spring Python utilizes proxies to merge target objects with interceptors. This makes it easy to add and remove advice, while maintaining a nice separation between services and target APIs. Later on in this chapter, automated testing of aspects will be discussed.

The risks of AOP

AOP carries its own risks. When some of the functionality (in our case, caching), is moved out of our core code and into an interceptor, it may not be apparent when the caching logic is active. We may not even be aware that there is caching in the system. But the same could be said about OOP practices, where commonly used functionality is moved to other classes up or down the inheritance hierarchy. All of these coding styles are better served by the right set of tools, developer training, documentation, automated test suites, and communication amongst the development team. Since AOP is relatively new compared to OOP, the tool sets aren't as mature and developers are not as familiar with the concepts.

But this doesn't mean AOP should be abandoned. Instead, it should be evaluated just like any other technology, language, and tool suite used by the team.

AOP is part of the Spring triangle

The following diagram—known as the Spring triangle—encompasses the key principles used by Spring Python:

AOP is part of the Spring triangle

Using Spring Python's IoC container we have been able to take a simple WikiService object and layer on a CachingService through AOP. By using Dependency Injection, we have kept WikiService clear of any Spring Python dependencies. To read the details of this, we just look up the blue prints of our IoC container in WikiProductionAppConfig. Spring also utilized Portable Service Abstractions, such as DatabaseTemplate, to reduce the need to work with low level APIs. Later on in this book, we will revisit the Spring triangle to discuss this in more detail.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.189.23