Design patterns and emergent architecture
A pattern is a design fragment that helps to solve a commonly encountered “problem” in a standard manner. A proper pattern description starts with the “intent”: a short description of the problem and the manner in which the pattern forms a solution. The addressed problems are often related to unwanted dependencies between code modules. Thus, application of design patterns can help to make software more modular and thereby realize its non-functional properties. The emphasis in pattern application is on the software structure rather than the implemented functionality. There is a well-known quotation from Grady Booch, a person who was very instrumental in popularising object-oriented techniques: “All well structured object-oriented architectures are full of patterns.” It expresses the link between design patterns and software architecture. That is exactly what the 4-day training is about.
The course covers the patterns laid out by the “Gang of Four”, the fathers of the design pattern approach in software engineering. It might seem superfluous to discuss all their 23 patterns, but they form a concise toolbox from which the proper mix can be obtained to fulfil the non-functional properties of the software.
The course will illustrate the approach using non-trivial case studies and hands-on exercises. For example: the composite pattern will be applied for extensibility and reuse, the observer for scalability, and the decorator for extensibility and flexibility. Finally the combination of composite and observer can implement cash coherence with a background.
Prerequisites
This course is the natural sequel of the ‘Object-oriented analysis & design‘ (OOAD) training. It builds further on the ideas presented there, and it is strongly recommended that one attends the OOAD first. A solid background in object-oriented software design through other training courses or through daily practice may also suffice.
Example 1
In one of the case studies a reusable component is obtained that will illustrate a number of issues regarding software evolution. When a software component evolves it is very important that “old” client code written against the component works unaltered. Such evolving component is said to remain backwards compatible. Many people have the impression that one should add functionality to an interface as hooks for later extensions. This is not recommended. In fact one should minimize the functionality that is offered to the bare minimum required. Keeping client code compatible is easy when the interface is extended but sheer impossible if the interface is shrunk. On the other hand compatibility is greatly improved by enforcing some simple syntactical rules involving patterns. Applying such rules one can decouple the evolution of the reusable component from the client code. This is not only important for the delivery of reusable frameworks, rolled out to a large customer base, but also for the construction of new versions of components in a larger dedicated software system. What one sees in practice is, that when functionality of a component is extended, a lot of other components topple over.
Example 2
The observer pattern can play an important role in software architecture. It is the object-oriented variant of the “call-back” mechanism. Like the “call-back” it inverts the dependency from caller to callee. So, if we have two components that make operation invocations to one-another we remove one of the resulting dependencies. Being able to shape the dependencies is great, but mutual operation invocations can result in another problem: deadlock. If the objects performing the calls are lockable there is a chance of cyclic waiting and deadlock may occur. This issue will be discussed in detail in relation to the observer pattern. Some concretely specified rules will be presented that can prevent deadlock by design. For anybody who develops concurrent OO programs this is a must.