Patterns and Anti-patterns
How to learn design patterns?
Categories of GoF patterns
The Fundamental theorem of software engineering
Real-world problems and how design patterns solve them with GoF structural patterns
Sameh DeabesSoftware Architect em Ministry Of Justice
2. AGENDA
Patterns and Anti-patterns
How to learn design patterns?
Categories of GoF patterns
The Fundamental theorem of software engineering
Real-world problems and how design patterns solve them
Uncovered Structural Patterns
Summary
3. PATTERNS AND ANTI-PATTERNS
What is a design pattern?
Well-known good high-level abstract solution templates for common problems
Blueprints not actual solutions
No pre-baked solution, you will implement it yourself
Built on concepts of OOP notice the wide usage of polymorphism
Caution: don’t try to apply design patterns on every problem you face, rather
“refactor to patterns” better!
What is an anti-pattern?
Well-known quick high-level abstract solution templates for common problems that
prove to have extensibility/flexibility limitations.
Quick not correct solutions
Don’t be afraid to use them given that you justify their usage, and you consider refactoring to patterns.
[KISS, YAGNI]
It’s a matter of right vs quick solution.
4. HOW TO LEARN DESIGN
PATTERNS?
Problem with GoF book
The original text groups patterns in three categories, and then alphabetically within
each. All good for reference purposes, but lousy for learning. -- Michael Mahemoff
Solution: use other learning path
GoF Design Patterns: Rapid Learning Tips, Michael Mahemoff [Article, 2 pages]
http://cs.millersville.edu/~ekatz/cs420/designPatterns/MamehoffRapidLearning.pdf
Head First Design patterns, Freeman [book]
Professional ASP.NET design patterns, Scott Millet [book]
My own learning path
GoF categories
Problem-Solving approach
Similarity/differences
5. LEVELS OF DESIGN PATTERNS
I: Design Patterns: Elements of Reusable Object-Oriented Software,
GoF [23 patterns]
II: Patterns of Enterprise Application Architecture, Martin Fowler
III: Enterprise Integration Patterns, Gregor Hohpe
Problem specific patterns
SOA patterns
Concurrency patterns
…etc.
6. CATEGORIES OF GOF PATTERNS
Creational patterns
Objects construction and decoupling
Structural patterns
How to shape objects to build more complex objects?
Behavioral patterns
Communication between objects, SoC, and algorithms.
7. THE FUNDAMENTAL THEOREM OF
SOFTWARE ENGINEERING
We can solve any problem by introducing an extra level of indirection
– David Wheeler
…except for the problem of too many levels of indirection – Kevlin
Henney
8. THE IDEA OF “WRAPPING”
We will depend on this idea a lot here, then it worth have an example:
12. WCF CLIENT AUTO-GENERATED
CODE• The remote object is wrapped by a local object!
• The web service proxies generated by svcutil.exe and deriving
from System.ServiceModel.ClientBase<TChannel>
13. NOTES
A layer of indirection/wrapper was created to solve the problem.
The interface was adhered.
The wrapper located at my system to wrap remote object
Congrats! This is the first design pattern, Proxy Pattern (typically,
remote proxy)
More examples:
When you consume a WebApi service that has no wsdl, you create your own proxy
When you create a SignalR windows client and you create your own proxy
Another flavor = Reverse Proxy: proxy for external systems to use my
services
The wrapper located at the remote system to control access to its internal objects
15. NAVIGATION PROPERTIES IN
ENTITY FRAMEWORK.
EF inherits the class at runtime and adds its implementation to
support lazy loading of navigation properties
16. NOTES
A layer of indirection was created to solve the problem.
The interface was adhered.
Congrats! This is another flavor of Proxy Pattern (typically, virtual
proxy)
More examples:
Mocking frameworks @ unit tests makes intensive use of this idea.
17. WHAT IF WE WANT TO
CHANGE/EXTEND OBJECT BEHAVIOR
AT RUNTIME?
18. INHERITANCE AND COMPOSITION
Basic OOP solution: derive a sub-class and override methods
implementation you want to change.
One step forward solution (better for most cases):
Favor composition over inheritance
Composition = wrap the object by another object
Composition is superior to inheritance not because of the sake of itself, but because it allows to handle
orthogonal concerns separately will be obvious in Bridge pattern in a following session.
Or, in S.O.L.I.D. principles: Open/Closed Principle = Classes should be open to
extension, but closed to changes
Implement a shared interface + inject an instance of the class that we want to
change its behavior
20. NOTES
A layer of indirection was created to solve the problem.
The interface was adhered.
Congrats! This is the Decorator Pattern
Decorator is a special case of proxy (also known as Smart Proxy)
More real-world examples:
ASP.NET MVC has only one resolver, to support more than one: create a single class
that wraps many resolvers, and forward calls to appropriate resolvers among them.
@ WPF: System.Windows.Controls.Decorator uses the same idea.
21. WHAT IF MY CODE DEPENDS ON
OTHER SYSTEM THAT DOESN’T EXIST
YET?!
22. DON’T STUCK!
Before the dependent system exists:
Create an interface that spells the behavior you need.
Create a dummy implementation that adheres this interface and returns dummy
data to be able to test your system
Use the dummy object in your system
Once the dependent system exists:
Create a new class that adheres the interface you created before
Wraps the object that do the actual business, and forward calls to it
Replace the dummy object by this object in your system.
23. WHAT IF I NEED TO USE OBJECTS
WITH DIFFERENT INTERFACES
INTERCHANGEABLY?!
24. AGAIN…DON’T STUCK!
Create an interface that matches the behavior you need.
Wrap every incompatible object with a new class that adheres the
interface and forward calls to the underlying object.
Use the desired wrapper in your system (DI/IoC will be useful here!)
Real-world examples:
GIS application that needs to use Google maps and MS Virtual Maps
interchangeably!
Creating an anti-corruption layer for a third-party to enable replacing it in future
OOD principle: design for replacement not for reusability!
E.g. Create an ILog interface, and an adapter for Log4Net, Nlog, ..etc.
26. NOTES
Congrats! This is the Adapter Pattern (also known as
wrapper)
This is one of the most useful patterns!
The interface was NOT adhered
actually the adapter pattern enables classes of incompatible interfaces to be used
together by converting the interface of a class into another interface that my system
expects.
Usually used to avoid changing existing classes by – again - adding a
layer of indirection!
Optimum when this class is a third-party that you have no control over its code
Examples from .NET world:
ADO.NET providers, e.g. System.Data.SqlClient.SqlConnection,
System.Data.OleDb.OleDbConnection etc. Each provider is an adapter for its
specific database.
27. WHAT IF WE NEED TO SIMPLIFY THE
INTERFACE OF A
COMPLEX SUBSYSTEM OR GROUP OF
SUBSYSTEMS?
28. ADAPTER++
• Do as you did in Adapter BUT wrap multiple objects:
• Create a class that wraps all objects you need to expose
• Define your simple interface
• Forward calls to underlying objects.
31. NOTES
Congrats! This is the Façade Pattern
This is one of the most useful patterns!
A layer of indirection was created to solve the problem.
The interface was NOT adhered
Similar enterprise pattern: Transaction Script
Used in service layer
= Façade + Transaction (atomic/all or none)
More real-world examples:
Login to windows with fingerprint and AD
A single method that calls each pre-existing service successively and return a single result!
32. YOU HAVE A TREE/HIERARCHY OF
ITEMS/PEOPLE AND YOU NEED TO DO
OPERATIONS ON ALL OF THEM, AT ALL
LEVELS.
THINK OF ORGANIZATION CHART AND
ATTENDANCE CALCULATIONS.
33. POSSIBLE SOLUTIONS
Wrong solution:
nested for-loops and lengthy code
Perfect solution:
Group objects into tree-like or hierarchical collection
Each node in the tree is responsible of its own operations
Call the root node, which calls the nested nodes recursively to complete the
operation.
The important point is that each node is responsible of its own calculations
36. NOTES
Congrats! This is the Composite pattern!
More examples from .NET framework:
System.Windows.Forms.Control
System.Web.UI.Control
System.Xml.XmlNode
37. UNCOVERED STRUCTURAL
PATTERNS
Bridge pattern
It is a mix of Template and Strategy Behavioral patterns, thus postponed till we
learn these patterns.
Flyweight
Depends on Factory Creational pattern, thus postponed till we learn this pattern.
38. SUMMARY
Right vs Quick solutions = Patterns vs Anti-patterns
Important OOD principles
We can solve any problem by introducing an extra level of indirection except for the problem of too many
levels of indirection
Favor composition over inheritance
Open/Closed Principle = Classes should be open to extension, but closed to changes
Design for replacement not for reusability!
Covered GoF Structural Patterns
Proxy
Decorator
Adapter
Façade
Composite
Uncovered GoF Structural Patterns
Bridge
Flyweight