Principles to get acquainted with
SOLID principles were introduced by Robert C. Martin (a.k.a Uncle Bob) in
2000. The intention of these principles is to make software designs more
understandable, easier to maintain and extend. These principles are
essential for every developer to know, because it will help them in
writing better code an better understanding other code that was written
with these principles in mind.
- S - Single Responsibility
- O - Open/Closed
- L - Liskov Substitution
- I - Interface Segregation
- D - Dependency Inversion
Introduction to Patterns
One might not believe it, but design patterns do not find their origin in
software architecture. Patterns were first described in the 1970s by a
real "Bricks and Stones" architect. A pattern is defined as a re-usable
solution to a common type of problem, without ever repeating the actual
way the solution is implemented. This means that patterns are an ideal
learning tool and also ideal for communicating design ideas. Of course
there are also anti-patterns, things often used, but actually better
- What is a Pattern?
The Gang of Four: Erich Gamma, Ralph Johnson, Richard Helm and John
Different kinds of design patterns: creational, structural and
Patterns everywhere: the difference between implementation, design and
- When to apply patterns, and when not to.
- Some anti-patterns such as Loosy-Goosy.
When creating software, you feel yourself continuously creating new
objects. Although the basic form of creating new objects is not bad, it
can result in design problems or added complexity to the design.
Creational patterns will help you deal with object creation that is
suitable to the situation.
Singleton - a.k.a. The Pluto Pattern and how to implement it in .NET
- LAB: Building a Singleton in .NET
Factory Method - delegating/hiding the creation of objects to a factory
Abstract Factory - abstracting the factory to create families of objects
- LAB: Implementing an Abstract Factory
Once your objects are created, they start interacting. When you're not
careful, these interactions can quickly start leading into code that is
tightly coupled. Behavioral design patterns help with identifying common
communication patterns between objects and realize these patterns. By
correctly applying these patterns, you can increase flexibility in
carrying out the interaction between objects.
Template Method - defer exact parts of an algorithm to inheriting
classes, delegates, ...
- LAB: Building a Template Method for a board game
- Strategy - template method without the annoying inheritance
- LAB: Implementing a Builder as a Strategy
Chain of Responsibility - strategy to go through a chain of strategies
- LAB: Using a Chain of Responsibility to implement a Builder
State - defer state dependending logic to state classes, state machines,
- Using the Stateless library
LAB: Implementing a VCR with the State patterns using the Stateless
Iterator - providing a generic way of navigating through collections,
yield is your friend, asynchronously iterating a collection
Observer - notifying whoever is interested in what you have to say,
events vs. delegates
Mediator - providing two-way communication between objects unaware of
one another, correcly implementing INotifyPropertyChanged
- LAB: Avoiding the String-based programming anti-pattern
Created objects do not tend to stand on their own. No, they start
encapsulating other objects trying to create structure in, what otherwise
would be a chaotic software environment. Structural patterns help at
identifying and setting up relationships between objects.
Adapter - plugging in different objects into your code that do not fit
- LAB: Building INotifyPropertyChanged as a generic Adapter
Decorator - altering the behavior of an object without the caller
- LAB: Changing IComparable<T> with a Decorator
Composite - tree structures are here to help you, working with Linq
- Facade - hiding the complexity of subsystems from the caller
Flyweight - reduce memory consumption by preventing unnecessary creation
Proxy - proxying requests made to the subject without changing the
Building your own little programming language with some patterns - Fun!
Programming languages also use a bunch of patterns in their
implementation. In this chapter you will build your own little programming
language, which is extensible by the way. While doing so you will discover
and apply some very important patterns which are perfectly useable outside
of the scope of building programming languages!
Interpreter: Build your own expressive language-grammar and execute it.
How LINQ uses Interpreter - and how you can take advantage of it
Builder: Hide how complex hierarchies of objects get built - and allow
- XAML as the ultimate builder.
- Reflection: the ideal .NET way for implementing your own builder.
- How NOT to use reflection.
- LAB: Building your own calculator with Interpreter and Builder
Visitor: When you need a lot of different operations on the same object
- Building a pretty-printer using Visitor.
- Implementing Visitor the dynamic way.
LAB: Implementing a Visitor to walk over a complex hierarchy of objects
- Automating tedious code with Source Generators
Most developers make lousy graphic designers. That is why we see the
emergence of patterns that allow developers to focus on writing code to
implement the behavior of the application, while allowing graphics
designers to build kick-ass user interfaces. The main pattern is called
Model-View-*Whatever*, with *Whatever* replaced depending on the
technology you are using. Understanding the MVW pattern is important as it
is used to develop both windows and web applications.
- Model-View-Controller: An ancient pattern back in fashion.
- ASP.NET MVC - an introduction.
MVVM in WPF - MVC taking advantage of powerful databinding capabilities.
- Command: Encapsulate behavior in objects.
- Implementing commands using closures.
- LAB: Using MVVM in a WPF application
Have you ever heard of Reactive Programming? This is an important new
development where you learn to program using Observables. You
will learn to apply this technique to solve some common, hard-to-solve
problems with classic Object-Oriented Programming, and we will also
explore the Fluxor/Redux pattern.
- What are Observables?
- Using Reactive Extensions.
- Applying the Redux pattern so simplify complex applications.
- LAB: Implementing a search system with Observables
Design Patterns Applied: Developing your own reusable library.
When do you need patterns the most?! When you are building a framework
yourself. Building a framework means handling new features while keeping
backward compatibility. This very hard task can be make easier with the
proper use of patterns. So in this last part of the training we will build
a reusable library, and while doing so encounter some problems and then
solve these problems by applying the right pattern.
- Adding the GoF Command pattern to MVVM.
- Using interfaces for flexibility.
- Building Command Objects - extending WPF's ICommand interface.
- Adding Undo and Redo functionality to the command pattern.
- Using a CommandManager class.
Challenge: retro-fitting our commands into MVVM without lots of changes.
- Implementing Undo-Redo using the Memento pattern.
- Choosing whether or not to add the Prototype pattern.
- Ideas on how to proceed with the command pattern.
- LAB: Implementing Undo/Redo logic as a reusable library