Additional Blogs by Members
cancel
Showing results for 
Search instead for 
Did you mean: 
jwood_bowdark
Active Participant

These days, it is getting harder and harder to ignore the object-oriented side of ABAP. If you are one of the many developers who have embraced this change, then perhaps you might be looking for ways to take your skills to the next level. Regardless of the discipline, one of the best ways to master a trade is to look at how senior practitioners go about solving particular problems. However, if you don’t have an OO guru sitting in the cubicle beside you, you might be wondering where you can go to learn these trade secrets. Fortunately, as it turns out, many of these best practices have been documented and left behind by some of the masters of the trade in the form of design patterns. In this blog series, I will introduce you to design patterns and show you how to use them to improve your designs.

What are Design Patterns?

The term “design pattern” was coined by Christopher Alexander, a noted architect whose book A Pattern Language: Towns, Buildings, Construction helped inspire software architects to document design approaches in terms of patterns. In his book, Alexander notes that “Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice”. Whether these solutions are fashioned from brick and mortar or from classes and interfaces doesn’t really matter. The point is that we can use this approach to document a solution to a problem in context.

The design pattern concept was first introduced to the software community in the classic software engineering text Design Patterns: Elements of Reusable Object-Oriented Software (colloquially known as the “Gang of Four Book”). In this book, four leading software engineers attempted to catalog a set of patterns that were informally known throughout the community. In an effort to bring some structure to the text, they documented these patterns in four parts:

  1. Each pattern was assigned an informal name that could be used to identify and discuss the pattern throughout the community.
  2. Next, the problem that the pattern addressed was described in context.
  3. Once the problem was clearly defined, a general solution was described in terms of the classes/interfaces that make up the design, as well as the relationships, responsibilities, and collaborations between those classes. Here, you will not find a solution that can be cut-and-pasted into your program, but rather a design approach that can be adapted to fit the particular problem at hand.
  4. Finally, they documented trade-offs associated with applying the design. This information includes design alternatives, consequences of using the design, etc.

Throughout the course of this blog series, I will introduce you to some of the more common design patterns documented in the Gang of Four book. To illustrate these solutions, I will try to show you how these solutions might be used to solve particular kinds of problems in ABAP. So, without further adieu, let’s begin our journey by looking at the Strategy pattern.

Classifying Behavior

In some respects, the OO analysis and design (OOAD) process bares similarities to the classification process used by biologists to organize plants and animals. Here, we attempt to make sense out of a set of functional requirements by classifying the objects that make up a given problem space. A common tactic used to identify these classes is to read through a functional specification and underline all of the nouns. This approach, though flawed to a certain degree, is useful in taking a first pass through a set of requirements. On the other hand, it is easy to get carried away if you don’t have an open mind.

Technically speaking, a noun is a person, place, thing, or idea. Oftentimes, developers get hung up on those first three definitions, looking only at concrete object types such as business partners, plants, sales transactions, etc. However, this narrowed perspective limits you when modeling real world phenomena. After all, there are a lot of requirements that don’t fit into such neat little packages. For instance, what about algorithms? How do we classify those?

Normally, algorithms are classified as a type of behavior and associated with one or more classes in the form of methods. However, in certain cases, this design approach violates a core OO design principle in that it reduces the cohesiveness of the class(es) in question. Here, the term “cohesiveness” refers to how strongly related and focused the various responsibilities of the class are. In other words, does the algorithm fit within the class? Or should it stand on its own?

To answer these questions, let’s take a look at an example from the sales and distribution domain. Let’s imagine that you want to develop a sales contract application. As you would expect, one of the core classes in this application would be a "Contract" class. Of course, there are many different types of contracts. There are fixed price contracts, cost-plus contracts, basic ordering agreements, etc. At first, you might be inclined to model these differences by developing a class hierarchy like the one depicted in the UML class diagram below.


Looking at the UML class diagram above, you can see some problems with this approach. In this simple diagram, we have only shown a subset of the classes that might be derived. In reality, the class hierarchy might end up extending several levels down depending upon how many different contract types the application needs to support. This kind of fine-grained specialization results in designs that are brittle and hard to maintain.

Deriving the Strategy Pattern

So, you might ask, how should we proceed differently? Well, before we investigate alternative designs, let’s look at a few common themes in the Gang of Four book (I’m paraphrasing here):

  1. Consider what should be variable in your design.
  2. Encapsulate the concept that varies.
  3. Favor composition over inheritance.

Looking back at our sales contracts example, let’s see if these concepts can help guide us towards a better solution:

  1. First of all, we need to figure out what is variable in our design. Now, much of this depends upon our functional requirements. However, for the sake of this discussion, let’s assume that the only difference between these contract types is in how their overall value is calculated.
  2. The next step is to encapsulate the concept that varies. Here, we need to encapsulate the algorithm(s) that calculate a contract’s value.
  3. Finally, once we have properly encapsulated the value calculations, we can graft them back into our Contract class hierarchy using composition. This gives us lots of flexibility as there are many ways we may want to integrate these two concepts. Indeed, we can even swap solutions out at runtime in a plug-and-play fashion.

When you put all this together, you arrive at the Strategy pattern. In the Gang of Four book, the definition of the Strategy pattern is as follows:

   Define a family of algorithms, encapsulate each one, and make them interchangeable.
   Strategy lets the algorithm vary independently from clients that use it.

The UML class diagram below shows a revised design architecture for our contracts example using the Strategy pattern. As you can see, we have factored out the various contract-specific calculations into a separate class hierarchy underneath the abstract base class ContractValuation. Within this hierarchy, we can reuse existing algorithms to derive specialized value calculations such as the one required for a cost-plus incentive contract. In this way, the Contract class can vary independently from the various calculations (which may change more frequently). Also, by splitting the calculations out, we give ourselves more room to maneuver. This makes it possible to mix-and-match valuations at runtime, re-use calculation logic in other areas of our application, etc.

Summary

Hopefully by now you have an appreciation for the Strategy pattern. Generally speaking, you will want to use the Strategy pattern when you come up with a design in which you have many related classes that differ only in their behavior. Other warning signs that might indicate a fit for the Strategy pattern include situations where you find yourself writing a lot of CASE statements or doing a lot of “copy-and-paste” coding. In an upcoming blog entry, I will show you how you can blend the Strategy pattern with another pattern to simplify the integration process

4 Comments