What Is Aspect Oriented Programming?

Aspect Oriented Programming (AOP) provides the ability to intercept code execution with the purpose of inserting a process before, in place of, or after the code that would normally execute. When you consider that everything, calling a method, returning from a method, retrieving or assigning a value, handling exceptions, switching context, etc., consists of code execution, you can begin to think about how such a capability would be used. If that satisfies your curiosity, then read no further. However, this definition is so simple that the reasons behind why one would use AOP are completely lost. Be warned also that this definition speaks only to a particular implementation which, in the opinion of this author, has actually nothing to do with Aspect Oriented Software Design (or Development, the terms seem to be interchangeable even if the acronym is the same) – AOSD. Furthermore, AOSD is itself a subset of post-object programming (POP) technologies. Unfortunately, pursuing AOP and AOSD gets us quickly lost in a quagmire of bizarre terminology and custom languages and extensions. This article is intended to provide a concise understanding of not only AOP but the more general issues of AOSD. Like many of the recent paradigms intended to solve some of the problems arising with complex software development, AOSD contains gems of wisdom within the effluence of actual implementations.

Why Aspect Oriented Software Design?

The predominant reason for AOSD is to help solve the issue of messy object architectures. The proponents of AOSD claim that object oriented programming has difficulty dealing with global information. Also, functionality that requires the involvement of several different objects (possibly collected into a component) results in interdependency between those objects/components. This makes the application susceptible to the implementation changes of a dependent object/component. Maintenance and enhancement are also problems, as the interaction between these objects/components (regardless of whether the rules of interaction are coded formally or informally) are typically hard coded within the containing object. If this is confusing in itself, consider that in these statements, the terminology of AOSD to explain the reason for AOSD is specifically avoided. This is intentional so as to avoid putting the cart before the horse. Attempting to understand AOSD can be very confusing when immediately immersed in the terminology of AOSD, with no glossary in sight.

Messy object architectures occur when something that the application needs to do requires the involvement of many different objects. Given a requirement specification, Object Oriented Design (OOD) often proceeds by determining the objects that are necessary to support the requirements. The goal is to compartmentalize functionality as determined by an analysis of the requirements until sufficient abstraction occurs (among other goals of OOD). Throughout this process, the designer often loses sight of the fact that ultimately these objects are going to need to interact with each other in order to meet the requirements with actual functionality. This happens easily and subconsciously because the way requirements interact is often fundamentally different from the way objects interact. The concepts described in Design Patterns are an attempt to formally understand the issues of object interaction and to provide the designer with some well understood and supported means for solving this object interdependency problem. In fact, the primary implementation of an AOP language, that being AspectJ, relies heavily on the Observer design pattern. However, one of the criticisms made by AOSD proponents is that, beside there being too many design patterns (and ever growing), these patterns are often “designed in” too early in the design process. As a result, designs must be redone, or even worse, implementation must be reworked when a different design pattern is required. Another criticism is the interaction between design patterns and system structure. A design pattern not only influences system architecture, but is itself influenced by system architecture. As a result, the design pattern loses its modularity as it disappears in the implementation. This often affects re-usability, as the design pattern (a reusable component) and the object model (another reusable component) become integrated into a more rigid, less re-usable, component.

Personally, while I agree with the reality of this observation, I disagree that this indicates some flaw with the concept of design patterns. Rather, I feel it is indicative of incomplete requirements and analysis, a lack of education and training on the part of the designer/developer, and a poor project leadership (someone should be smarter than everyone else!). If you accept this counter argument, then it also deflates the premise that AOSD is the cure to bad object architectures. Another consideration is that none of these paradigms give any indication as to when they should be used. Many useful applications, including web-based applications (where complex object interdependencies are difficult to maintain between page refreshes), do not encounter the problems that AOSD attempts to address. AOSD (and similar paradigms) begin to be useful only when an application crosses the boundary between automating simple tasks (like a simple text editor with cut and paste and print capability) and automating complex processes made of up multiple tasks (like a word processor that provides embedded graphics, line drawing, spell checking, layout and formatting tools, collaboration, security, and integration with other applications). Where this boundary is, and when to make the shift in the design paradigm, is still an art. My experiences have taught me that the vague requirements, ill-defined use cases, and potentially limitless enhancement are indicators that I should consider these issues at the very beginning of the project and design accordingly.