Solid Design Patterns
This course will introduce delegates to the wonderful world of Object Orientated Design Patterns. Once understood design patterns allow the leveraging of proven solutions to common re-occurring problems. Probably the most important aspect to design patterns is that it provides a common vocabulary to describe a system. No longer will teams of developers need to discuss lines of code but instead describe the system as a series of patterns, leading to accurate and efficient communication. As part of this process delegates will obtain key insights in how to design good object orientated systems. The original Gang of Four Design Patterns were documented prior to .NET, in this course the implementation of these patterns is bought up to date using the latest versions of C# and the .NET framework.
Modules in Solid Design Patterns:
Why Design Patterns
This module discusses the reasons why you should study design patterns. Design patterns offer the ability to reuse solutions not just code. By reusing already established designs, you get a head start on problems and avoid gotchas; you benefit by learning from the experience of others; you do not have to reinvent solutions for commonly recurring problems.
Design patterns establish a common terminology allowing developers to use a common vocabulary and share a common viewpoint of the problem. Design patterns provide a common point of reference during the analysis and design phase of a project.
The course will use UML as a means to communicate pattern intent, and this chapter will introduce key UML concepts.
Some solutions require the use of a single object instance across the whole solution, for example naming services, cached objects. This chapter will introduce the singleton pattern as a solution, along with variations for thread safety, and other varieties of single instance based on thread affinity.
Strategy and Template Patterns
What we can be 100% sure of with software is that constantly needs to evolve. What we also know is every time we change existing working code there is a risk that we will break it. What we need is an approach that will allow the software to evolve without having to modify existing working code. The strategy and template patterns allow us to build solutions that can evolve without the risk of effecting existing well tested code.
There are occasions when you want to decouple the knowledge of which type to create from the client code. This is essential for effective unit testing. There are a variety of creation pattern that will allow you do this by encapsulating the necessary knowledge of how to create the object thus allowing the actual implementation used to vary. In this chapter we will look at the Factory, Builder and Prototype patterns.
The ability to notify interested entities of changes to an object state is a fundamental requirement of most Object oriented solutions. There are many ways to do this but there is a danger that we will build a tightly coupled system, we prefer to build a loosely coupled system. The typical way of implementing the observer pattern is to use interfaces, but we will show that delegates and events are a far more flexible and efficient way of implementing the pattern on the .NET framework
Iterator, Composite and Visitor Patterns
There is often a need to access every object inside an object hierarchy, user interface control objects, documents , business entities , file systems.....The iterator pattern provides a standard means to achieve this, .NET provides a standard implementation of this, further the C# language simplifies the implementation further through language extensions. The visitor pattern gives us the ability to layer behaviour onto the hierarchy without the need to change the underlying implementation of the hierarchy. Continuing the theme closed for modification open for extension.
One of the key design pattern goals is to write code that is closed for modification and open to extension, this pattern will show that an objects behaviour and responsibilities can be extended at runtime, as opposed to design time using inheritance. This will allow us to combine a variety of behaviours far more efficiently that normal inheritance. Examples of decorators in the framework are BufferedStream , SynchronizationWrappers and XmlValidatingReaders.
The command pattern allows us to encapsulate invocation, allowing the invoker to be decoupled from the client and the recipient, this enables us to build a variety of different invokers to deliver custom thread pooling, and invocation logging to build fault tolerant solutions. We continue to extend the command pattern to not only encapsulate forward invocation but also undo invocation, allowing us to build a complex undo sequence through a series of simple undo commands.
In many cases object behaviour will depend on the state an object is in, we typically model the internals of objects through the use of finite state machine. This pattern provides a means to map a finite state machine into a series of classes where each class represents a different state, and thus providing different behaviours. This approach allows us to add new states and transitions without effecting existing code, continuing the theme closed for modification, open for extension.
Proxy and Interceptor Patterns
The proxy pattern manages the invocation of an object, by hiding the true nature of the location and invocation mechanism of the object, typically used to make remote method calls. Proxies have a host of uses from the conventional RPC style to more elaborate uses such as virtual proxies, security proxies and caching proxies. Proxies can be built manually, using the CLR or using third party libraries often taking advantage of the interceptor pattern. In this module we will look at all three approaches to build effective proxies.
Effective Unit testing with patterns
Design patterns allow us to build loosely coupled systems, allowing your software to be flexible and easily respond to change. The flexibility offered by patterns are essential for effective unit testing. In this module we will use TDD to build a solution utilising many patterns along the way to allow each unit to be tested in isolation. At the end of this module you will have seen how to practically apply many patterns to deliver effective unit testing