Introduction to Aspect-Oriented Analysis and Design
- Software Development and the Object-Oriented Paradigm
- The Case for Aspects
- What Is an Aspect?
- Why Consider Aspects in Analysis and Design?
- Aspects and Other Concerns
- The Theme Approach
- Applying the Theme Approach
- Theme: Symmetric or Asymmetric?
- Fitting Theme into Your Existing Development Process
- What About Implementation?
- Summary
You've probably picked up this book because you've heard that aspects will solve difficulties you're having with writing your object-oriented software. You've heard that aspects offer a new way to modularize your code, but you're here because you have questions like, What are aspects? Why do I need them? Are objects obsolete? Or perhaps you've picked up this book because you've tried programming with an aspect-oriented language and are interested in delving more deeply into the paradigm. You may have questions like, How do I plan for aspects before design and implementation? and How do I design aspects so that I can better plan for implementation? This book answers these questions and also guides you through the process of identifying and designing your aspects.
Software Development and the Object-Oriented Paradigm
Few would disagree that the object-oriented paradigm is one of the most important contributions to software development in its history. Those of us who remember developing software without objects most keenly appreciate their value. Everything to do with a "thing" is all in one place! When we want a "thing" we already have in one application to be used in another application, we can just pick it up and use it! And there are many more benefits besides.
To this day, we both remain big fans of objects. But of all the benefits associated with object-oriented development, the two of encapsulation and reuse that we hinted at above were not selected lightly. Can we really always put everything to do with a thing all in one place? Have you ever found that there was some piece of processing that did not seem to fit in any one particular class, and yet it did not feel as if it belonged in a class in its own right either? This is probably because it was too tightly coupled to behaviors in many other classes.
Think about, for example, objects that require some transaction management. It is difficult, if not impossible, to modularize all setup, communication with a transaction manager, and rolling back that may be needed to handle transactions. This is because all objects (or methods in objects) that require transaction management need to be aware that their operation is impacted by a transaction context and must behave accordingly. In other words, transaction-handling code must be placed in every object that needs it. Take a look at the code you’ve written in the past, and you will probably find many examples of similar (if not the same) pieces of code repeated in different places. The common, though compromised, solution to a problem like transaction management is to copy the code into the different places that need it. Code copying then results in poor modularization for much of your code and leaves you with considerable maintenance and evolution headaches. This phenomenon is also known as scattering, as code for a concern is scattered across multiple parts of the system.
In addition, from a reuse perspective, modules that contain code relating to many concerns are likely to be less generally useful in different situations. The phenomenon where multiple concerns are intermixed in the code is known as tangling.
Of course, good use of design patterns will help you encapsulate in many situations, but you will find the repetition and concern-mixing phenomena even where design patterns are well used. Ultimately, you will always encounter processing that relates to and impacts upon many portions of a system.