Object Oriented Programming C Sharp Succinctly
Object Oriented Programming C Sharp Succinctly
By
Sander Rossel
2
Copyright © 2016 by Syncfusion, Inc.
If you obtained this book from any other source, please register and download a free copy from
www.syncfusion.com.
The authors and copyright holders provide absolutely no warranty for any information provided.
The authors and copyright holders shall not be liable for any claim, damages, or any other liability arising
Please do not use this book if the listed terms are unacceptable.
SYNCFUSION, SUCCINCTLY, DELIVER INNOVATION WITH EASE, ESSENTIAL, and .NET ESSENTIALS are the
3
The World's Best
UI Component Suite
4.6 out of
5 stars
for Building
Powerful Apps
Laptop: 56%
Orders
Online Orders offline Orders Total users
Analytics
Sales Overview Monthly
S M T W T F S
Message
26 27 28 29 30 31 1
Accessories: 19% Mobile: 25%
2 3 4 5 6 7 8 $51,456
OTHER
9 10 11 12 13 14 15 Laptop Mobile Accessories
16 17 18 19 20 21 22 Users
23 24 25 26 27 28 29
Teams Top Sale Products
Cash
30 31 1 2 3 4 5
Setting Apple iPhone 13 Pro $999.00
$1500
Order Delivery Stats
Mobile +12.8%
100K
Completed
120 Apple Macbook Pro $1299.00 50K
In Progress
Invoices New Invoice Laptop +32.8%
25K
24
Order id Date Client name Amount Status Galaxy S22 Ultra $499.99 0
Mobile +22.8% 10 May 11 May 12 May Today
Log Out #1208 Jan 21, 2022 Olive Yew $1,534.00 Completed
G et our ree
y F .NE T nd a Java c S ript UI Components
syncfusion.com/communitylicense
desktop platforms
20+ years in
Terminology .........................................................................................................................10
Inheritance ...........................................................................................................................12
Encapsulation .......................................................................................................................16
Polymorphism ......................................................................................................................18
Chapter 2 Interfaces...............................................................................................................20
4
Creational Patterns...............................................................................................................36
Abstract Factory...............................................................................................................37
Singleton..........................................................................................................................43
Structural Patterns................................................................................................................45
Adapter ............................................................................................................................46
Composite .......................................................................................................................49
Decorator .........................................................................................................................52
Observer ..........................................................................................................................55
Strategy ...........................................................................................................................60
Repository .......................................................................................................................72
Creator .................................................................................................................................75
5
Packages .............................................................................................................................86
Procedural Programming......................................................................................................92
Conclusion ..............................................................................................................................96
6
The Story behind the Succinctly Series
of Books
S As many of you may know, Syncfusion is a provider of software components for the
Microsoft platform. This puts us in the exciting but challenging position of always
being on the cutting edge.
Whenever platforms or tools are shipping out of Microsoft, which seems to be about
every other week these days, we have to educate ourselves, quickly.
In reality, this translates into a lot of book orders, blog searches, and Twitter scans.
While more information is becoming available on the Internet and more and more books are
being published, even on topics that are relatively new, one aspect that continues to inhibit us is
the inability to find concise technology overview books.
We are usually faced with two options: read several 500+ page books or scour the web for
relevant blog posts and other articles. Just as everyone else who has a job to do and customers
to serve, we find this quite frustrating.
This frustration translated into a deep desire to produce a series of concise technical books that
would be targeted at developers working on the Microsoft platform.
We firmly believe, given the background knowledge such developers have, that most topics can
be translated into books that are between 50 and 100 pages.
This is exactly what we resolved to accomplish with the Succinctly series. Isn’t everything
wonderful born out of a deep desire to change things for the better?
Each author was carefully chosen from a pool of talented experts who shared our vision. The
book you now hold in your hands, and the others available in this series, are a result of the
authors’ tireless work. You will find original content that is guaranteed to get you up and running
in about the time it takes to drink a few cups of coffee.
7
Free forever
Syncfusion will be working to produce books on several topics. The books will always be free.
Any updates we publish will also be free.
As a component vendor, our unique claim has always been that we offer deeper and broader
frameworks than anyone else on the market. Developer education greatly helps us market and
sell against competing vendors who promise to “enable AJAX support with one click,” or “turn
the moon to cheese!”
We sincerely hope you enjoy reading this book and that it helps you better understand the topic
of study. Thank you for reading.
8
About the Author
Sander Rossel is a professional developer with over five years of working experience in .NET
(VB and C#, WinForms, MVC, Entity Framework), JavaScript, and SQL Server.
He has an interest in various technologies including, but not limited to, functional programming,
NoSQL, and software design.
He seeks to educate others on his blog, Sander’s Bits – Writing the code you need, and on his
CodeProject profile.
In his spare time he likes to play games, watch a movie, and listen to music. He currently lives
with his cat, Nika, in the Netherlands.
9
Introduction to OOP
Object-oriented programming, or OOP for short, has been around since the 60’s and is now the
de facto standard programming paradigm. The programming language Simula first adopted
OOP concepts in the 60’s. Later, these concepts were taken further by the first pure OOP
language, Smalltalk. OOP started to really pick up steam in the 90’s with languages such as
Java. C# and .NET came in 2000.
OOP is a powerful concept that solves many problems found in software development. OOP is
not the holy grail of programming, but, as we will see throughout this book, it can help in writing
code that is easy to read, easy to maintain, easy to update, and easy to expand.
The concepts in this book are not unique to C#. Other object-oriented languages, such as Java,
C++ and Python, share principles that are discussed throughout this book.
The included code samples were all tested in the free Community Edition of Visual Studio 2015
and were created in .NET 4.5 (though most will also run in earlier versions of .NET).
Throughout this book I’m assuming basic knowledge of C#. If you know how to write a class and
declare a variable, you’re pretty much good to go.
Why OOP?
OOP is all about architecting your software. Let’s compare software to a house. Would you want
a bunch of builders to just start building your house without predefined rules and agreements? I
bet you wouldn’t! Your house would be a mess. Still, that’s what often happens in software and,
as expected, a lot of software turns out a mess! Returning to our house metaphor, let’s say your
lamps were built right into the ceiling. Whenever a lamp broke you’d need a new ceiling! Luckily,
that’s not the case. Yet in software, when a small detail needs to change, we often find
ourselves rewriting huge pieces of code. And in many cases functionality that had nothing to do
with the change breaks anyway. By abstracting away certain functionality we can just worry
about the detail and we’re sure other parts of the system won’t break. On top of that we can
reuse code so that if functionality needs to change we’re sure it’s changed everywhere where
we use it. How that’s done will become clear throughout the book.
Terminology
Before we dive into OOP it’s important that we get some terminology straight.
Often, I see the terms class and object used interchangeably. Let’s get that out of the way, as
they are two different things. A class is a blueprint for an object. It contains the methods and
properties that will eventually define the behavior of an object. An object is the actual instance of
a class, created at runtime using the new keyword.
10
In the following code listing we’ll see an example of a Person class. It doesn’t do anything, it
just sits there.
In the previous code listing, we can see how an object is instantiated from a class by calling its
constructor (using the new keyword).
Let’s go a bit further. Each object has one or more types. A type is defined by the class that was
used to instantiate an object. For example, our personObject has the type Person. One type
all objects in C# share is the type Object (or, including its namespace, System.Object). This is
possible because C# supports Inheritance, but we’ll get into that later. We have a couple of
ways to check the type of an object, for example, we can use GetType, typeof or the is
operator. For now, let’s move on.
Last I’d like to mention packages. A package is a common name for a set of code that is
compiled together. In Microsoft land a package is often called a DLL. In .NET a DLL is often
known as an Assembly. In Visual Studio each project is compiled into a DLL or an exe
(executable) file.
11
Chapter 1 The Three Pillars of OOP
Object-oriented programming has three characteristics that define the paradigm, the so-called
“three pillars of OOP.” In this chapter, we’ll look at each one of them in detail. They all play an
important role in the design of your applications. That’s not to say that your systems will have a
great design by simply applying these concepts. In fact, there is no single correct way of
applying these concepts, and applying them correctly can be difficult.
Inheritance
Inheritance is an important part of any object-oriented language. Classes can inherit from each
other, which means the inheriting class gets all of the behavior of the inherited class, also
known as the base class. Let’s look at the Person example I used earlier.
The trick is in the Employee : Person part. That part basically says “Employee inherits from
Person”. And remember everything inherits from Object. In this case Employee inherits from
Person and Person (because it’s not explicitly inheriting anything) inherits from Object. Now
let’s look at how we can use Employee.
That’s pretty awesome! We got everything from Person just by inheriting from it! In this case we
can call Person a base class or superclass and Employee a subclass. Another common way of
saying it is that Employee extends Person.
12
There’s a lot more though! Let’s say we’d like to write some common behavior in some base
class, but we’d like subclasses to be able to extend or override that behavior. Let’s say we’d like
subclasses to change the behavior of GetFullName in the previous example. We can do this
using the virtual keyword in the base class and override in the subclass.
As you can see we can override, or re-define, GetFullName because it was marked virtual in
the base class. We can then call the original method using the base keyword (which points to
the implementation of the base class) and work with that, or we can return something
completely different. Calling the original base method is completely optional, but keep in mind
that some classes may break if you don’t.
Now here’s an interesting thought: Employee has the type Employee, but it also has the type
Person. That means that in any code where we need a Person we can actually also use an
Employee. When we do this we can’t, of course, access any Employee specific members, such
as Salary. So here’s a little question: what will the following code print?
If you answered “Rossel, Sander” (rather than "Sander Rossel") you were right!
What else can we do? We can force a subclass to inherit certain members. When we do this we
must mark a method, and with that the entire class, as abstract. An abstract class can’t be
instantiated and must be inherited (with all abstract members overridden).
13
Code Listing 7: An Abstract Class
On the other end of the spectrum, we can explicitly state that a class or method may not be
inherited or overridden. We can do this using the sealed keyword.
Now that Person is sealed no one can inherit from it. That means we can’t create an Employee
class and use Person as a base class.
Methods can only be sealed in subclasses. After all, if you don’t want people to override your
method, simply don’t mark it virtual. However, if you do have a virtual method and a subclass
wants to prevent further overriding behavior it’s possible to mark it as sealed.
14
public class Employee : Person
{
public decimal Salary { get; set; }
public sealed override string GetFullName()
{
return LastName + ", " + FirstName;
}
}
Why would you ever use sealed on your classes or methods? First, there is a small
performance gain because the .NET runtime doesn’t have to take overridden methods into
account. The gain is negligible though, so that’s not really a good reason. A better reason is
perhaps because a class implements some security checks that really shouldn’t be extended in
any way.
Note: Some languages, like C++, know multiple inheritance. That means a
subclass can inherit from more than one base class. In C# this is not possible; each
subclass can inherit from, at most, one base class.
15
}
We could’ve used this approach with Person and Employee as well, but how would we set
FirstName and LastName? We could make Person public, but we are now breaking a principle
called encapsulation (as discussed in the next chapter). We could mimic Person by defining a
FirstName and LastName property, but we now have to change the public interface of
Employee every time the public interface of Person changes. Additionally, Employee will not be
of type Person anymore, so the type of Employee changes and it will not be interchangeable
with Person anymore.
Encapsulation
Encapsulation is the process of hiding the internal workings of our classes. That means we
specify a public specification, used by consumers of our class, while the actual work is hidden
away. The advantage is that a class can change how it works without needing to change its
consumers.
In C# we have four access modifiers keywords which enable five ways of controlling code
visibility:
• public—visible to everyone.
Let’s say we’re building some class that runs queries on a database. Obviously we need some
method of RunQuery that’s visible to every consumer of our class. The method for accessing the
database could be different for every database, so perhaps we’re leaving that open for
inheritors. Additionally, we use some helper class that’s only visible to our project. Last, we
need to store some private state, which may not be altered from outside our class as it could
leave it in an invalid state.
16
Code Listing 12: Access Modifiers
If we were to compile this into an assembly and access it from another project we’d only be able
to see the QueryRunner class. If we’d create an instance of the QueryRunner we could only call
the RunQuery method. If we were to inherit QueryRunner we could also access
OpenConnection and CloseConnection. The Helper class and the connection field will be
forever hidden from us though.
I should mention that classes can contain nested private classes, classes that are only visible to
the containing class. Private classes can access private members of their containing classes.
Likewise, an object can access private members of other objects of the same type.
17
public void SomeMethod(SomeClass otherInstance)
{
otherInstance.someField = "Some value";
}
When omitting an access modifier a default is assigned (internal for classes and private for
everything else). I’m a big fan of explicitly adding access modifiers though.
A last remark, before moving on, is that subclasses cannot have an accessibility greater than
their base class. So if some class has the internal access modifier an inheriting class cannot
be made public (but it could be private).
Polymorphism
We’ve seen inheritance and that we can alter the behavior of a type through inheritance. Our
Person class had a GetFullName method which was altered in the subclass Employee. We’ve
also seen that whenever, at run-time, an object of type Person is expected we can throw in any
subclass of Person, like Employee. This is called polymorphism.
In the following example the PrintFullName method takes an object of type Person, but it
prints “Rossel, Sander” because the parameter that’s passed into the method is actually of
subtype Employee, which overrides the functionality of GetFullName.
class Program
{
static void Main(string[] args)
{
Person p = new Employee();
p.FirstName = "Sander";
p.LastName = "Rossel";
PrintFullName(p);
// Press any key to quit.
Console.ReadKey();
}
18
}
The Takeaway
The Three Pillars of OOP are the foundation of object-oriented programming. They haven’t been
implemented for nothing and they do solve real problems. It’s crucial that you know these
features by heart and practice them in your daily code. Think about encapsulation every time
you create a class or method. Use inheritance when necessary, but don’t forget it brings extra
complexity to the table as well. Be very wary of polymorphism, know which code will run when
you inherit classes and override methods. Even if you don’t practice it you’ll come across code
that does. Throughout this book we’ll see these be used extensively.
19
Chapter 2 Interfaces
In the previous chapter, we saw that the class Employee inherits from Person. Do you see any
potential issues with this approach? What if a person is an employee, but also a stamp
collector? Obviously, a person can also be a stamp collector but not an employee (lots of people
are “between jobs”). If all we had was inheritance we might write the following code:
I don’t know about you, but it just doesn’t feel right to me. The problem we have is that the only
thing the EmployeeStampCollector and the StampCollector have in common is the Person
base class, but they’re still both stamp collectors! Writing a method that takes a stamp collector
as input is now impossible! This problem could be solved using multiple inheritance, but C#
doesn’t have that (and many developers say it is better that way).
20
Notice that none of the fields have an access modifier. If a class implements an interface
everything on that interface is publicly accessible. This is what the actual implementation would
look like:
So here SomeClass has the types object, SomeClass, and ISomeInterface. The “I” prefix on
ISomeInterface, or any interface, is common practice in C#, but not necessary.
When using inheritance and interface implementation on a single class, you first specify the
base class and then use a comma-separated list of interfaces. How would this look for our
Person, Employee and StampCollector example?
21
{
// ...
}
Now both StampCollector and EmployeeStampCollector are of type Person and of type
IStampCollector. EmployeeStampCollector is also of type Employee (and IEmployee)
because it inherits from Employee, which implements IEmployee.
Because a class can implement multiple interfaces it is possible to have an interface inherit from
multiple interfaces. A class must then simply implement all interfaces that are inherited by the
interface. For obvious reasons, an interface can’t inherit a class.
Now that’s a very theoretical example, but let’s consider a real world example. Let’s say our
application needs to log some information. We may want to log to a database in a production
environment, but we’d also like to log to the console for debugging purposes. Additionally, in
case the database isn’t available, we’d like to log to the Windows Event logs.
class Program
{
static void Main(string[] args)
{
List<ILogger> loggers = new List<ILogger>();
loggers.Add(new ConsoleLogger());
loggers.Add(new WindowsLogLogger());
loggers.Add(new DatabaseLogger());
22
public void LogError(string error)
{
Console.WriteLine("Error: " + error);
}
That’s pretty nifty! And as you can imagine, we can add or remove loggers as we please.
By the way, having both an interface and a base class (which implements the interface) is
perfectly fine. Maybe you have an ILogger, a DbLogger (which implements ILogger and
defines some common behavior for logging to a database) and then have a SqlServerLogger,
an OracleLogger, a MySqlLogger, etc. (which all inherit from DbLogger).
23
Code Listing 21: Explicitly Implemented Interface
24
Inheritance vs. Interface
One discussion you will find frequently online, or might get engaged in at work, is that of
inheritance vs. using an interface. Remember that you can only inherit from one class. That
means if you use inheritance, like Person -> Employee, your Employee is stuck with the Person
base class. Alternatively, you could define an IPerson and implement it separately in Person
and Employee. One guideline you’ll often see is that inheritance defines an “is-a” relationship
(an Employee is a Person) while interface implementation defines a “can do” or “has-a”
relationship (a Person has a stamp collection). As you see, it’s not entirely fool proof, as a
stamp collector is also a Person, but still inheritance can lead us into trouble.
I like to use inheritance when I have some functionality that is shared across multiple, if not all,
subtypes of that class, like with the DbLogger example.
The Takeaway
An interface is a means to create additional types without the need for multiple inheritance.
They are extremely useful. I’ve talked to people who say every class needs a matching
interface. It’s such an important feature that Visual Studio even has the option to create an
interface based on a class. When your cursor is in a class, you can find it under Edit -> Refactor
-> Extract Interface in the top menu.
Learn to use them well, as we’ll use them a lot throughout this book.
25
Chapter 3 SOLID
We’ve seen the building blocks that make up an object-oriented language, but how can we write
our classes so that they make sense? When to inherit, what to put inside a class, how many
interfaces do we need? These are questions that can be answered in part by the so-called
SOLID principles. SOLID is an acronym and each letter stands for a principle.
In this chapter we’re going to look at all of them. Knowing these principles can help you write
modular code that is easy to maintain and expand. The principles are described by Robert C.
Martin in his 2006 book Agile Principles, Patterns, and Practices in C#1.
Let’s look at a concrete example. Let’s say you’re building a database module. Now you’ve got
a class that can establish a connection to the database, get and send data, and finally close the
connection. If we defined an interface it could look as follows:
26
So this could really be the interface to your class, right? Unfortunately, this class is doing two
things. The class deals with opening and closing connections and with data communication.
Here comes the tricky part, and this may or may not be a problem. The question you should ask
yourself is this: will the application change in a way that either connections or data
communications will change, but not both? This is important, because when the time comes and
you realize you need to change one of the two functionalities, the functionality that doesn’t need
to change will be in the way. The more functionality that’s in the way, the more chances you
have of breaking those parts of the application.
When applying SRP, your classes will be a lot smaller and more maintainable, but you’ll have
more classes to deal with. Which would you rather change, a class with 200 lines of code that
does multiple things, or a class with 100 lines of code that does only one thing?
As you see, there is no wrong or right in SRP. Unfortunately, it’s a bit of a gut feeling. If you feel
a class is to bloated, try identifying different responsibilities and give each their own class.
Let’s say you’ve built that database class we just talked about. In a sense it’s already extensible,
since everyone can inherit from it and add methods and properties. Doing so will almost
certainly result in breaking SRP though, since the core functionality of the class is already
defined in the base class and we can’t change that. You could make every method in the base
class virtual, and I’ve seen that happen, but that’s not really good practice as consumers may
now break your class. For example, if they override Connect and just leave it empty, no
connection will be made and each subsequent method call to your class will fail. Besides, even
if the method is overridden correctly the base class will now just be sitting there doing nothing,
which doesn’t feel right.
I propose a different solution, one of many. Let’s break up the previously proposed interface into
two separate interfaces. You’ll probably need some more methods now, but let’s stick to
simplicity for now.
27
void SendData(IConnectionManager connManager, object data);
}
Now suppose I’d like to change the way I connect to the database. I can implement my own
IConnectionManager and pass it to my IDataManager. Without touching the original code, I am
now able to extend the functionality of the classes without actually breaking the already existing
class! Likewise, if I’d like to change the way I’m getting or sending data I can simply implement
my own IDataManager and use it with the already existing implementation of
IConnectionManager.
It gets better, though. Every class that depends on IConnectionManager and/or IDataManager
is now extendable in that it can use any database you can ever imagine! Well, theoretically.
Later we’ll look at Design Patterns, which can help you in designing classes that conform to
OCP.
28
A more subtle violation of LSP is when subclasses behave differently than their base classes.
The classic example is that of a Square class that inherits from a Rectangle class. A square is
a rectangle (with equal width and height), so this inheritance looks plausible. Unfortunately, in
some scenarios a square may behave differently than a rectangle and may break users of the
Rectangle class and get a Square instead.
As I mentioned in the bit about SRP, this may or may not be SRP-proof, depending on your
requirements. Let’s say it is okay for our example, but let’s take another approach, that of
inheritance. More specifically, I’m going to create a base class for connection management and
inherit that for our data management.
29
public class DataManager : ConnectionManager
{
public virtual object GetData()
{
// ...
}
Now our FileDataManager has a fat interface. It depends on classes it doesn’t need! Notice
that this would not have happened if we just created two Interfaces and implemented those
instead. We could even use composition to re-use the ConnectionManager in other
Data(base)Managers. The downside to this is that FileDataManager now depends upon
ConnectionManager, even though it doesn’t need it. Any change to ConnectionManager may
now break FileDataManager though! Such couplings between classes should be avoided
where possible.
class Program
{
//...
30
bool TestConnection(SqlConnectionManager connMngr)
{
// ...
}
It should be obvious that TestConnection can now only be used for SqlConnectionManager.
We have created two problems. First, TestConnection, and Program with it, now depend on
SqlConnectionManager. Second, we’ll have to write a TestConnection for each
ConnectionManager we’re going to write. We’re saying that SqlConnectionManager is a
concrete type of the abstract type IConnectionManager. So let’s fix that so that we’re relying
on abstract types compliant to DIP.
You may think that’s a pretty lame solution, and you may even say this will break your existing
code because TestConnection relies on methods that aren’t part of the IConnectionManager
Interface. If that's the case, you should ask yourself three things. Is TestConnection
implemented correctly, and does it really only test connections? Is my SqlConnectionManager
really an IConnectionManager? Finally, is IConnectionManager defined correctly?
Now why is this principle so important? It has everything to do with expanding and changing
existing systems. If you depend on abstractions, it’s easier to switch implementations. In theory
you could switch your database (or at least the connection manager) and TestConnection
would still behave as expected. We’ve seen loggers earlier, depend on ILogger and you can
switch from file logging to database logging without problems!
31
For the next example I’m going to use Unity, a DI library developed by Microsoft and now
maintained by other people. You can get it using the NuGet Package Manager in Visual Studio.
Just go to Tools > NuGet Package Manager > Manage NuGet Packages for Solution and
search for “Unity.” Install it in your (saved) project and you’re good to go.
A “DI Container,” which Unity provides, is a sort of repository where abstract types are mapped
to concrete types. Any code can then ask that repository for an instance of an abstract type and
the repository will return whatever concrete type you’ve mapped to it. Your entire code base,
save for the part(s) where you map your types, can now depend upon abstractions. Sounds
pretty neat, so let’s have a look at some code!
32
return true;
}
class Program
{
static void Main(string[] args)
{
// Create a new DI Container...
IUnityContainer container = new UnityContainer();
// ...And register a type!
container.RegisterType<IConnectionManager, SqlConnectionManager>();
}
}
And elsewhere in the code we can now request an IConnectionManager and call
TestConnection:
You should now see “Connected to SQL Server!” and “Closed SQL Server connection…” in
your console window. Now change the call to RegisterType so it registers as
OracleConnectionManager. The TestConnection will now print Oracle instead of SQL Server.
Imagine: by changing this one line of code you could change an entire application to use Oracle
instead of SQL Server!
Now suppose you have some dynamic user interface and the controls that are shown on screen
depend on some settings and/or configuration. Let’s say we have some HTML form defined in
the database, and we wish to generate the HTML server side. I’m going to let you figure this one
out on yourself, but I’m pretty sure you’ll get it.
class Program
{
static void Main(string[] args)
{
IUnityContainer container = new UnityContainer();
container.RegisterType<IHtmlCreator, HtmlInputTextCreator>("text");
container.RegisterType<IHtmlCreator, HtmlInputCheckboxCreator>("checkbox");
33
Type = "text"
},
new
{
Text = "Do you wish to receive offers?",
Type = "checkbox"
}
};
Console.ReadKey();
}
}
See how that just saved you an unwieldy switch/if statement? And the best part is that you
can add new IHtmlCreators and types without changing the code that generates the HTML!
So you’ve just created OCP and DIP compliant code (except for the <p> tags, but you can figure
that out)!
This isn’t a tutorial on using Unity, but it does show the basic principle of DIP and DI containers.
The sample in this section demonstrated what is called Interface Injection, but it is also possible
to create objects using a specified constructor, called Constructor Injection, and automatically
set objects on properties, called Property, or Setter, Injection. Other DI Frameworks exist, such
as Ninject and Spring.NET. In this example we’ve written code to setup our container, but other
frameworks also work with (XML) config files. All of them work with the same principle though,
and depend upon abstractions.
34
Inversion of Control (IoC)
Often mentioned together with DI is Inversion of Control, or IoC. You may even see the terms
being used interchangeably. The basic principle of IoC is that “higher” code depends upon
abstractions. We have already seen this in action with TestConnection. Here’s another fun
fact: DI is actually a form of IoC (not necessarily the other way around though)!
The Takeaway
Generally speaking, the SOLID Principles can lead to good, maintainable, extensible, and
testable software design at the expense of additional complexity. However, they do not come
naturally to a lot of developers. Let’s be honest, it’s hard to think ahead, so if you need a
SqlConnectionManager now, why bother with some IConnectionManager that may need to be
modified later anyway? It’s a lot easier to simply create a SqlConnectionManager and use it
throughout your code. However, you cannot predict the future and, even though you think you’ll
never switch to something other than SQL Server now, the future may prove otherwise. When
you’ll have to switch to something else, you will wish you had practiced the Dependency
Inversion Principle. Likewise, when your API that had always been internal suddenly has to go
public, you will wish you had practiced the Open Closed Principle. And that stuff does happen.
I’ve heard “that will never happen” a few times too many, so really, think ahead and practice
SOLID!
35
Chapter 4 Design Patterns
Have you ever had that problem that you know you’ve solved before somewhere else? Many
people have. Design Patterns are general solutions to specific problems that many people face.
Design Patterns were first systematically organized for the C++ language in the book Design
Patterns: Elements of Reusable Object-Oriented Software, by Erich Gamma et al. in 19952.
In general there are three kinds of Design Patterns: Creational, Structural, and Behavioral. Not
only do they solve recurring problems, a formalized solution to a problem means that we don’t
re-invent the wheel and that we can communicate more clearly about our code. Any
programmer will (hopefully) recognize your use of pattern X and then know how to change your
code accordingly.
In this chapter, I’m going to discuss a few (of many) Design Patterns. I’ll include a Unified
Modeling Language (UML) class diagram of each pattern. UML is outside the scope of this
book, so I can’t explain how the diagrams should be interpreted. I’ve added them for reference
and they’re the “official” UML diagrams, so the class and method names don’t match those in
the examples. You can use them for visual explanation, but if you don’t get them don’t worry, it’s
all explained in the text.
The patterns I’m discussing are mentioned by the Design Patterns book as good starting
patterns. They’re pretty easy to get into and you’ll probably use them a lot as well.
Creational Patterns
Creational Patterns deal with, as the name implies, the creation of objects. With Creational
Patterns we can abstract away the process of object instantiation. As we’ve seen before, we
can use composition rather than inheritance. Creating a set of objects that work together as a
group can be beneficial, but rather than hard-coding which concrete types to use we can
abstract this process like we’ve seen with DI. In the next section we’re going to look at a few
Creational Patterns. It’s not a full list, but it shows the power they can bring.
2 Gamma, Helm, Johnson, Vlissides - Design Patterns: Elements of Reusable Object-Oriented Software
36
Abstract Factory
One of the easiest, yet most useful, Creational Design Patterns is the Abstract Factory. The
Abstract Factory defines an interface for the creation of closely related objects. Imagine, again,
that we’re building a dynamic user interface. We need textboxes, buttons, checkboxes, radio
buttons, etc. So let’s say we have the following Interface, analogous to the example I’ve used
before, but in WinForms:
And let’s say it’s used as follows (which creates a pretty much unusable user interface):
37
}
Now our application can create either a red or a green GUI using the specified concrete type.
38
Figure 4: Form Using the RedControlFactory
Notice how easy it would be to add a BlueControlFactory without breaking any existing
code? Or even better, we can swap our ugly WinForms controls with custom controls or with
third party controls.
In .NET you can find the Abstract Factory Pattern when working with databases. The
DbProviderFactory base class is such an Abstract Factory, although it’s typically not
necessary to implement it yourself.
39
}
// ...
}
Factory Method
Sometimes it does not make sense to create an Abstract Factory. What if there are no closely
related objects, like TextBox, CheckBox, Button, etc.? Having an Abstract Factory to create a
single object (which may contain other objects, of course), while possible, feels weird (although
can be useful). Suppose we’re building some class that generates our UI. The UIGenerator
could make use of an IControlFactory to construct the UI. Furthermore we may have multiple
UIGenerators to build UIs for different kinds of users.
With the Factory Method Pattern we can delegate the creation of objects to subclasses. This is
especially useful when a base class can’t anticipate which subclass it’ll need to perform its
functionality.
So here is the BaseUIGenerator (which will serve as a base class for all UIGenerators).
40
}
It’s also possible to use something else as a container, for example a Panel.
41
Code Listing 45: Using the Generator with Panels
The result is that each Panel now has the same Controls, but in a different color.
This example also demonstrates the power of the Abstract Factory and Factory Method
patterns.
The .NET Framework uses the Factory Method Pattern too, such as when working with
database connections.
42
Singleton
The Singleton Pattern is pretty fun. It’s easy, but often implemented incorrectly. It’s loved, and
it’s hated. So why do I want to include it here? First, the Singleton limits the amount of created
objects of a specific type to exactly one, which is pretty neat and can be necessary (examples of
Singletons are your print spooler, the file system, etc.). Also, since it’s often used incorrectly, I’d
like to educate a little and hope to clear up when to use this. Last, since it’s so often incorrectly
implemented, we’re going to do it correctly now, once and for all.
At the base of the Singleton is a private constructor. You read that right. When the constructor
of a class is private no other class can create instances of this class. That may come in handy,
as the class can now create instances of itself and keep track of those instances. That’s a bit
counter-intuitive, but with a static field completely possible.
private SomeSingleton()
{ }
}
At this point no other class can create or reach an instance of this class. Next, we’ll need
another static method (or property) to give access to the instance of this class. We’ll also need
to create that instance.
private SomeSingleton()
{ }
43
{
instance = new SomeSingleton();
}
return instance;
}
}
}
And now the Singleton is complete. Indeed, this is the implementation we’ll often find in code
bases (you’ll also often find Singletons with public constructors a.k.a. not Singletons at all).
So what is wrong with this Singleton? Nothing, if your application is completely single-threaded.
When you’re going multi-threaded, this implementation can still result in multiple instances. This
happens when two threads try to get the instance at the same time. Both threads will see that
instance is null because neither thread has actually created the new instance yet, so we’ll need
to lock this code for multiple threads. And as a small optimization, we won’t lock after the
instance is created. Here is the full thread-safe Singleton:
private SomeSingleton()
{ }
44
The double null check may look weird, but remember that when two threads access Instance at
the same time, both will see that instance is null, and one thread will be locked while the other
creates the instance. After the locked thread is released, it should check for null again or it will
create a second instance.
Other methods on the Singleton can now simply be public instance methods and will behave
like any other. Just keep in mind that the state of a Singleton object is shared throughout the
entire application because it’s static!
So what’s the problem with Singletons? They’re used far too often. I’ve seen Singletons that,
after a year, needed a second instance somewhere in the application! As it turned out, this
Singleton wasn’t a Singleton at all!
Second, Singletons can’t be subclassed. Since the constructor is not accessible by any part of
the application except the Singleton itself, not even subclasses can access it (meaning they
won’t be able to construct themselves).
Last, Singletons are hard to test. Suppose you’re testing a part of the application that internally
uses a Singleton. For a long time there was no way for you to mock the Singleton. It’s now
possible using newer testing frameworks that use code weaving and Aspect Oriented
Programming (AOP), but it still doesn’t feel completely right.
So when should you use a Singleton? Basically when you’re absolutely sure your application
will never need a second instance of an object (or when another instance may even be harmful
for the system). It may also come in handy to provide one-point access to shared resources (like
the print spooler). Logging is often noted as an acceptable use of the Singleton Pattern.
While many objects in .NET logically have only one instance (like Application), I am not
aware of any Singleton implementations in .NET (that’s not to say you can create instances of
Application, the constructor is just internal instead of private). If a rather huge framework like
.NET doesn’t need Singletons, you should think very carefully if you need them or if you can
solve your problem differently.
Structural Patterns
Structural Patterns are about making objects work together and structuring your code
accordingly. Where Creational Patterns are about the creation of objects, structural patterns are
about making objects work together, but without these objects knowing about each other’s
internals.
45
Adapter
An easy and well known Structural Pattern is the Adapter Pattern, or Wrapper. With the Adapter
Pattern, we can make two classes work together even though they have incompatible
interfaces. Suppose we’re creating a data retrieval system, but the client hasn’t decided on
Oracle or SQL Server yet, or they might switch in the future. And let’s say both databases come
with some API with different classes and methods (of course, both already have compatible
.NET API’s). The following code is simplified, but does show the use of the Adapter:
46
The problem here is that if we choose one API, we can’t easily replace it with the other.
SqlServerApi works with DataTables while Oracle works with plain objects, the methods have
different names, and on and on. In the real world you’ll find both interfaces use different classes,
have many different methods (that the other doesn’t have), and more. So let’s create an
interface that can tie these two incompatible API’s together. The problem is what we’ll do with
the DataTables. Our interface can work with DataTables, and then we should make that work
for Oracle, or we can work with objects and convert it to DataTables for SQL Server. A third
option is to create a custom object which can be converted to both a plain object and a
DataTable. For simplicity we’ll work with object.
Now we can implement this for both SQL Server and for Oracle.
47
public object GetData()
{
return api.GetQuery();
}
As you can see, converting from and to DataTables is now an “implementation detail.” We don’t
really care how the SqlServerApiAdapter does it (probably using Reflection), as long as the
public API is correct. You can now work with the IDbApiAdapter and leave the creation of a
specific adapter to another part of the system (using a Factory or Dependency Injection).
The Adapter Pattern is used in .NET when working with legacy COM objects. When referencing
a COM object, .NET creates a wrapper (or adapter) that can be used within .NET to call the
corresponding COM methods.
48
Composite
Composite is also one of the easier patterns. Let’s say you have a collection of something, a
List<Something> if you like. And maybe all these “somethings” have a collection of those
same things too, child somethings. In that case we’ll have a tree of somethings. Now something
has some operation, and when that operation is performed the same operation should be
performed on all child somethings. Sounds abstract, but let’s say that something is a Control
(like TextBox, CheckBox, DataGrid, etc.). So we have a Control which has child Controls
and each child Control can have child Controls as well. And the operation is rendering the
Control. So when we render our topmost Control all child Controls and children of those
children should render too.
The next example may seem a bit farfetched, but it’s not easy to create an example of the
Composite Pattern, so bear with me. In the example, we’re going to print sentences symbol by
symbol. So our operation will be Print. We need to be able to print a single symbol, like “c” or
“#” so let’s create a class that can do just that.
public Symbol(char c)
{
symbol = c;
}
49
Console.Write(symbol);
}
}
With that, we can create an IPrintable containing any single symbol. Let’s create some
additional IPrintables for our convenience (and for the example).
Now we need a composite class that can contain multiple symbols (or IPrintables), a
Writing.
50
}
And that’s it. We can now use these classes to compose words and sentences and print them
on screen. In a simple Console application, the usage looks as follows:
// Print hello.
hello.Print();
// Remove the line break, so we can re-use hello.
hello.Remove(br);
Console.ReadKey();
In .NET, this pattern is used, as mentioned, in WinForms when rendering Controls (and
probably in WPF and ASP.NET as well).
51
Decorator
The Decorator Pattern can be used to add functionality to an object dynamically. It’s especially
useful when one object can have multiple functionalities that aren’t always used at the same
time, like different representations of the same data. In that respect it offers a flexible alternative
to inheritance.
Let’s say we have some text message and we want to print and/or email and/or fax (yes, people
still do that) and/or send it to an external system. Additionally, the message must always be
saved to the database. First we’ll need our Message class that contains the message we want to
process and we can implement the default process (after all, we always need to send the
message to the database).
52
We can now create a base decorator. Notice that we always need another IMessage passed to
the constructor (or we’ll get a NullReference, you may want to add a check there). The Msg
property is simply delegated to the root IMessage.
set
{
innerMessage.Msg = value;
}
}
}
Now that we have our base decorator, we can create some sub decorators.
53
public override void Process()
{
base.Process();
Console.WriteLine(String.Format("Sent '{0}' as fax.", Msg));
}
}
We can now process our message in many different ways; we can just save it to the database,
we can save it and email or fax or send it to an external system; we can save, email and fax;
save, email, and send it to the external system; or save, fax, and send it to the external system.
The beauty is that we can easily add new functionality without breaking the already existing
functionality.
Console.WriteLine();
decorator = new EmailDecorator(msg);
decorator.Msg = "Bye";
decorator.Process();
Console.ReadKey();
In .NET we can find the Decorator Pattern when using streams. Many streams, like
MemoryStream, BufferedStream, and FileStream offer the same base functionality (provided
by the Stream base class), but they work differently internally. So the different streams decorate
the Stream class. In the usage of these classes we can often find a Strategy Pattern (explained
later).
54
Behavioral Patterns
Behavioral Patterns are about changing runtime behaviors of algorithms and classes. If
Creational Patterns are about the creation of objects, and Structural Patterns about how the
objects work together, then Behavioral Patterns are more about changing the implementation of
those objects. With the three kinds of Patterns, you can build highly scalable and maintainable
software that is neatly organized into small pieces of code.
Observer
With the Observer Pattern it’s possible for a class, a so-called observable, to notify other
classes, observers, of changes. .NET events are implemented using this pattern.
A few quick notes regarding the Observer Pattern in .NET. First of all, because .NET already
has events, it shouldn’t be necessary to implement this pattern yourself. Let’s assume for a
moment that you still want to. You’re probably going to start out with two interfaces:
IObservable and IObserver. Then you find out .NET already has those interfaces (in a
generic variant). Do not use them. I’ve seen the .NET interfaces being used in the Observer
Pattern, but those interfaces are meant to be used primarily with Reactive Extensions (Rx). I
can’t explain Rx here, but the interfaces make little sense for the “traditional” Observer Pattern
that I’m going to discuss here.
55
void Attach(IObserver observer);
void Detach(IObserver observer);
void Notify();
}
Now let’s implement the IObservable. We’re going to create a product stock, and every time
the stock changes we’re going to notify observers (also called listeners). The code is a bit
lengthy, mostly due to the properties at the bottom. Notice that these properties have nothing to
do with the Observer Pattern, they’re simply necessary to identify the stock.
56
{
return noOfItemsInStock;
}
set
{
noOfItemsInStock = value;
Notify();
}
}
}
// Register observers.
Seller seller = new Seller();
stock.Attach(seller);
Buyer buyer = new Buyer();
stock.Attach(buyer);
stock.NoOfItemsInStock = 5;
Console.ReadKey();
You’ll find a big caveat with this approach though. The buyer and seller get notified, but they
don’t know about what. It’s just some IObservable. There are a few options here. First we can
simply cast the IObservable to Stock. For example, the Seller class would now look as
follows:
57
{
Stock stock = (Stock)observable;
Console.WriteLine(String.Format("Seller was notified about the stock change of
{0} to {1} items.",
stock.ProductName, stock.NoOfItemsInStock));
}
}
This approach is taken in a WinForm event where every Control event has the signature of
(object sender, EventArgs e). The sender can be any type of Control and should be cast
if you’d like to do anything useful with the sender (the initiator of the event).
A second approach is to make your IObservable less generic (or more specific). In that case,
IObservable would get the ProductName and NoOfItemsInStock properties (and you might
want to rename it to IStock).
Of course, the problem with this approach is that you can’t reuse IObservable for other
classes.
So last, but not least, you might want to use Generics. This should solve all your problems.
Remember that IObserver<T> and IObservable<T> already exist for Reactive Extensions, so
we’ll have to use another name. I’ve used INotifier and IListener. Not much changes, but
the implementation is slightly more difficult.
58
{
void Update(T observable);
}
59
{
Console.WriteLine(String.Format("Seller was notified about the stock change of
{0} to {1} items.",
observable.ProductName, observable.NoOfItemsInStock));
}
}
Strategy
The Strategy Pattern allows you to encapsulate a family of algorithms and use them
interchangeably. You can think of many applications for the Strategy Pattern, for example a
video game where units on a battlefield all behave the same in many aspects, such as moving
and rendering, but differ by attack strategy. One unit may be offensive while another is
defensive. The offensive or defensive algorithm can be injected into each unit.
Another example is the sorting of a list. Depending on the size of the list you might want to use
another sorting algorithm, but you don’t want to hard code each algorithm into the list class.
So let’s make a little game. It’s a simple Console application and we’ll just be pressing any
button which will move our units and which may result in an enemy encounter (keep pressing
buttons or press escape to quit). Each unit reacts differently to an enemy encounter. So first
let’s define a generic Unit class.
60
this.behavior = behavior;
this.name = name;
}
So as you can see the Render and Move methods are the same for each Unit.
ReactToOpponent, however, is injected through the constructor. The IUnitBehavior interface
defines the ultimate strategy to use. So let’s define some strategies.
61
foreach (Unit unit in units)
{
unit.Render();
Console.WriteLine();
}
// Returns 0, 1, or 2.
if (rnd.Next(3) == 0)
{
Console.WriteLine("The enemy attacks!");
foreach (Unit unit in units)
{
unit.ReactToOpponent();
}
}
else
{
Console.WriteLine("Nothing happened...");
}
Console.WriteLine();
}
That’s quite a bit of code, but it’s really the first two lines that matter. We’re defining two Units,
but with another IUnitBehavior. When an enemy attacks (chance 1 in 3) you’ll see that each
Unit behaves according to its strategy. It also becomes easy to add another strategy.
// ...
Unit priest = new Unit("Priest", new PriestBehavior());
// ...
units.Add(priest);
// ...
62
The .NET Framework makes use of the Strategy Pattern as well, such as when calling
List<T>.Sort(). You can pass in an optional IComparer<T>. Let’s check that out as it’s
another good example. We’re going to sort people by their first and last names.
We can now create a list, put some people in it, and sort them by first or last name.
ceos.Sort(new FirstNameSorter());
foreach (Person p in ceos)
{
Console.WriteLine(String.Format("{0} {1}", p.FirstName, p.LastName));
}
Console.WriteLine();
ceos.Sort(new LastNameSorter());
foreach (Person p in ceos)
{
Console.WriteLine(String.Format("{0}, {1}", p.LastName, p.FirstName));
}
Console.ReadKey();
63
Template Method
The Template Method Pattern is really very simple. In fact, it’s not much more than simple
inheriting and method overriding. It’s the inheritance variant of the Strategy Pattern (Inheritance
vs. Delegation).
Let’s say we need to retrieve the Product table from a SQL Server database. We can inherit the
BaseDataRetriever and fill in the blanks.
64
Code Listing 75: Inheritance of the Template Class
It would make sense to add another level of depth, so we can implement this for SQL Server,
but not make it query specific. Just rename ProductRetriever to SqlDataRetriever, make it
abstract, and remove the GetQuery method. Now the ProductRetriever would look as
follows:
65
return "SELECT Id, Name, Price FROM Product";
}
}
The usage of the CustomerRetriever class (or any BaseDataRetriever class) is as straight
forward as it gets.
In .NET we find the Template Method frequently. Basically, every method that you can override
is a Template Method. One such example is the Collection<T> class, which was meant as a
base class for custom collections.
66
More Patterns
The patterns discussed so far are “classic” patterns that were systematically described in the
book Design Patterns: Elements of Reusable Object-Oriented Software. However, there are
many more Design Patterns. Many of these are discussed in the book Patterns of Enterprise
Application Architecture by Martin Fowler3 (in Java). The patterns discussed in Fowler’s book
cover different areas of your code base, such as patterns specific for you domain logic,
communication with your data source, concurrency and web session. I will discuss a few of
these patterns that are widely known and used.
Martin Fowler uses a lot of UML sequence diagrams. Like UML class diagrams, sequence
diagrams are outside the scope of the book, but I will add them for reference and visual
explanation.
Lazy Load
The Lazy Load Pattern is about not getting data until you actually use it. It comes in four flavors:
lazy initialization, virtual proxy, value holder, and ghost. We’ll look at lazy initialization only, as
it’s the most common and discussing all of them takes up too much space. I also want to
discuss this one because it has become more and more relevant and widely used. Functional
languages, such as Haskell, have a default lazy loading strategy for everything. Such practices
are becoming more common in .NET as well.
67
We have actually already seen the Lazy Loading Pattern when we implemented the Singleton
Pattern. The Singleton instance was not created until the object was actually used. Let’s take a
look at the (simple) implementation again.
private SomeSingleton()
{ }
The .NET Framework has a Lazy<T> class for lazy loading any class. Let’s say we have a class
that takes five seconds to initialize.
By using a Lazy<T> wrapper we won’t actually need to create the instance until we use it.
68
Code Listing 82: Usage of Lazy<T>
sw.Restart();
lazy.Value.PrintUse();
sw.Stop();
Console.WriteLine(String.Format(
"Using the Lazy<Something>.Value cost: {0} ms.",
sw.ElapsedMilliseconds));
Console.ReadKey();
// ...
Lazy<Something> lazy = new Lazy<Something>(() => new Something(new object()));
// ...
The .NET Framework uses lazy loading extensively with the Entity Framework, an Object
Relation Mapper (ORM). The Entity Framework maps database tables to classes within .NET
and can update your database using these classes. Now imagine you have a SalesOrder table;
each SalesOrder has SalesOrderLines, which is another table. You have classes in C# with
the same name and attributes. Additionally, your C# class has a property, SalesOrderLines,
which is in fact a collection of SalesOrderLines. When loading your SalesOrders, your
SalesOrderLines will be empty until you actually request the SalesOrderLines of a
SalesOrder. This is not necessarily faster if you need ALL SalesOrderLines, but if you only
need some of them, it can be pretty fast and convenient. See the sequence diagram at the
beginning of this section for a visualization.
69
Model View Controller
The Design Patterns book already mentions the Model View Controller pattern, MVC for short,
used in Smalltalk-80, but only to say this pattern makes use of the Observer, Composition, and
Strategy Design Patterns. There is more to the MVC pattern though. It makes use of three
components: the Model, the View, and the Controller [insert Ennio Morricone soundtrack here].
The Model contains some information on the domain, such as a product, a customer, or a sales
order. The Model is strictly non-UI. The UI information is in the View object. If this is a web
page, the view might contain HTML. Or maybe it contains some UI widgets that are displayed
on-screen. The third component, the Controller, glues these two together. It handles requests
from the View, retrieves and manipulates data that is then put in a Model, which is returned to
the View, which can use the Model for display on-screen.
The entire MVC model is about separation of concerns (SoC). Indeed, using MVC it becomes
easy to swap one part of the system in favor of something else. In web development you could
swap the Views or have multiple Views to represent the same data.
The Model View Controller pattern is so prevalent today that Microsoft created an entire
framework around it and named it after the pattern, ASP.NET MVC. The best way to check this
out is to simply start up Visual Studio and create a new ASP.NET MVC project (ASP.NET Web
Application). You’ll get a whole lot of files and folders (an often heard complaint about ASP.NET
MVC), but the classes we’ll be interested in are Controllers, Models and Views folders. The
HomeController, for example, has three methods, Index, About, and Contact. All of them
return a View without a Model. The AccountController has some methods that return a View
and pass in a Model, but they’re a bit complex to discuss here (this isn’t a book about ASP.NET
MVC after all). If you look at the Models, for example the classes in AccountViewModels, you’ll
see that these are just classes with some properties and attributes. The Models are initialized in
the AccountController and used in the Account Views (which is composed of many cshtml
files). For some simpler Views check out the Home Views, About.cshtml, Contact.cshtml and
Index.cshtml.
As a simple example, I’m going to create a new ASP.NET MVC project, rename it to
“MyMvcApp”, change the authentication type to “No Authentication” and create a very simple,
static website. First, throw away all Views, except Home/Index.cshtml. Now I want to show
some data in my View, so I’m going to create a Model, the PersonModel.
70
Code Listing 84: The Model
Next, I’m going to change the HomeController so it will pass a PersonModel to the View.
And finally I’m going to change my Home/Index View (which isn’t exactly valid HTML, but it’ll do)
so it will show the data in the Model.
@using MyMvcApp.Models
@model PersonModel
Now if you change the name in the Controller to something else it will be reflected in the View.
You don’t have to change the Model or the View. To recap, a user requests a View from the
Controller. The Controller (optionally) creates a Model, passes it to the View, and returns the
View. The View displays the data in the Model on the screen.
Two Design Patterns related to MVC are Model View ViewModel (MVVM) and Model View
Presenter (MVP).
71
MVP is a pattern for the user interface. The Presenter sits between the Model and the View and
formats data so the View can use it.
In MVVM, the ViewModel is an abstraction of the View that the View uses for display. Because
of the abstraction of the View, two-way binding is made possible (updates in the Model are
directly presented in the View and updates in the View are directly pushed to the Model). MVVM
was created for Microsoft’s Windows Presentation Foundation (WPF), but can now also be
found in many JavaScript frameworks like KnockoutJS and AngularJS.
Together MVC, MVP, and MVVM are referred to as the MV* Patterns. Note that they are not
mutually exclusive.
Repository
The Repository Pattern is a difficult pattern that, luckily, you don’t have to implement yourself. It
makes use of other patterns, the Data Mapper and the Query Object. A Data Mapper is a piece
of code that maps database records to C# domain objects. The database and the domain
objects are unaware of each other. A Query Object is a C# object that behaves like a database
WHERE clause and which can be passed to the Data Mapper (“aCriteria” in the diagram).
The Repository, finally, is a collection-like interface that can retrieve domain objects and sits
between your domain and data mapping layers. Once again, the benefit to be had is separation
of concerns. Your domain objects don’t know about your database and can be reused for other
purposes. Your database layer can be swapped (for example, going from Oracle to SQL Server)
and you’ll only have to change your Data Mapper. Your Data Mapper, Query Object, and
Repository can also be reused in other projects.
72
As much as I’d like building a Data Mapper, Query Object, and Repository, we’re not going to do
that. That costs a lot of time and can be a book on its own. Instead, I’m going to create a simple
Console application, save it, add an ADO.NET Entity Model to my project, and connect to some
database where I have a Person table. The Entity Framework will generate the Person class for
me (I’m not taking the code first approach).
It will also generate the Repository, which inherits from DbContext, and which gives access to
my Person objects like they were just in memory C# objects.
And here comes the beauty. The usage of the Repository Pattern (when done right) is just really
easy.
Personally I’m a fan of the whole “lambda creates Expression (Query Object)” philosophy, but
it does obscure the pattern a bit. Other APIs that I’ve used have a more explicit Query Object.
73
Code Listing 90: Explicit Query Object
A word of caution when using a Repository: everything may look like plain C#, but the dark truth
is that it isn’t. Ultimately, some query will be sent to your database, and if you’re not careful it’s
not going to be pretty. The Entity Framework (and other ORM’s) are capable of joining,
aggregating, using inner queries, what have you. Some SQL code will have to be generated and
if you don’t know what you’re doing it will be ugly and slow. Sometimes it’s just a lot quicker to
write some SQL and be done with it!
The Takeaway
There are many more patterns. Some patterns can be generally applied in any (object-oriented)
language, while others are language specific. Some patterns are even specific to a certain
programming paradigm. For example, JavaScript, which has no access modifiers, has Design
Patterns, like Module, to still be able to hide object internals. When you’re building a multi-
threaded application, you might want to use patterns specifically designed to simplify multi-
threaded code. To discuss all these patterns, you’d need many books that aren’t exactly
succinct. Design Patterns, like most things in life, have fans and opponents. While it’s true that
Design Patterns do not guarantee beautiful software, and may even lead to overly complex
software, it’s also important that you know the tools and methods that are available to you.
Design Patterns are in no way the holy grail of programming, but, when applied correctly, can
help you in creating robust and maintainable software.
The .NET Framework makes use of many other Design Patterns that aren’t discussed here, for
example; the Iterator Pattern, with IEnumerable and IEnumerator, making it possible to loop
through collections; the Builder Pattern, for constructing complex objects, see for example the
ConnectionStringBuilder; the Visitor Pattern in the ExpressionVisitor (when working with
Expressions/the Entity Framework); the Proxy Pattern when working with Windows
Communication Foundation (WCF); and the Unit of Work Pattern to gracefully handle database
transactions in the Entity Framework.
74
SHOPMART
Search for something... Filters John Watson
Sales
16 17 18 19 20 21 22 Users
syncfusion.com/communitylicense
Uncompromising quality
Hassle-free licensing
4.6 out of
28000+ customers
5 stars
20+ years in business
One set of patterns that you aren’t going to see a lot are the GRASP patterns, General
Responsibility Assignment Software Patterns or Principles (I’m pretty sure the abbreviation
came first). They are not quite patterns like Design Patterns, they are more like advice that
should help you solve common programming problems. I’m not sure why GRASP is not as
popular as SOLID or Design Patterns, as the principles are no less important and every
developer should know them. Craig Larman discusses them in his book Applying UML and
Patterns – An Introduction to Object-Oriented Analysis and Design and Iterative Development4.
There are a total of nine GRASP principles, and some of them overlap with what was already
discussed. In this chapter I’ll discuss the GRASP Patterns that have no overlap with what we
previously discussed. The ones that overlap are Controller (like we’ve seen in MVC),
Polymorphism (one of the three pillars of OOP), Indirection (another word for Dependency
Inversion), and Protected Variations (another form of Dependency Inversion and
Encapsulation).
Creator
One of the first problems you will encounter with any OO application is that you need to create
an instance of some object, but you’re not sure what other object is going to create it. In some
cases this is obvious, such as when working with certain Design Patterns such as Factory
Method or Singleton. Other times it’s not as obvious. At the start of this book, we saw a small
example with a Car and an Engine class (Inheritance vs. Composition).
4 Craig Larman - Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and
Iterative Development
75
A Car has an Engine, so it should obviously create an Engine, right? Well, maybe. There are a
few pointers for whether one class creates another. If some class contains or aggregates
another class, closely uses another class, or has the initializing data for another class (see also
Information Expert in the next section), it might be a good idea to have that class create another
class. A Car does contain an Engine, but it does not aggregate it. A Car closely uses an
Engine. Does the Car also have the initializing data for an Engine? Who knows? It depends on
your design. In this case I would probably go for another solution, which is to compose the Car
with an Engine class through the constructor (or through some other means).
And now that another class creates an Engine, you can give your Car any Engine you want.
Of course, that still doesn’t solve the entire problem, because who creates the Car, and does
that same class or yet another create the Engine?
It is important to note here that these objects are code objects and not domain objects. The
domain, or real world objects, are probably created on some assembly line. Chances are you
haven’t modeled the assembly line in your code, so that’s probably not going to create the Car
or Engine. One thing you know for sure, a Car has never created an Engine in the real world.
Information Expert
Information Expert is a principle that you are probably already applying. Information Expert
addresses the problem of which object handles which responsibility. How often have you
wondered what the right class was for a certain method? The answer lies with Information
Expert and is deceptively simple. A responsibility should be assigned to the class that has all
the information necessary to fulfill that responsibility.
Let’s take a look at an example. Earlier we created an Adapter for a SqlServerApi class.
Here’s a small reminder:
76
Code Listing 94: The SqlServerApiAdapter
Now as it turns out we want to be able to create new databases. That is new functionality as it is
not supported by GetData or SendData. Now where could we put this new CreateDatabase
method? Maybe in our Program class?
class Program
{
static void Main(string[] args)
{
77
CreateDatabase("MyDB");
SqlServerApiAdapter adapter = new SqlServerApiAdapter();
object data = adapter.GetData();
// ...
}
I think you can see the problem here. We’ve gone through all the trouble of creating an Adapter
for the SqlServerApi and now we’re going to use it directly in our application. It makes no
sense, as SqlServerApiAdapter is the much more obvious choice. It already uses
SqlServerApi anyway! And that’s exactly the point of Information Expert. The
SqlServerApiAdapter has all the information that’s necessary to create a new database, so it
is a good candidate for getting this new functionality. The alternative, Program, knows nothing
about SqlServer or databases, so the choice is easily made.
The example here is kind of obvious, but it demonstrates what Information Expert is all about. I’ll
tell you a little secret too: I’ve seen software that had CreateDatabase in Program (well, not
exactly that, but a likewise situation). When a code base grows large, it is not always obvious
where new functionality goes.
Low Coupling
The Low Coupling principle helps in keeping the impact of changes to a minimum. Coupling
between classes is when a class depends upon another. Needless to say that when a lot of
classes depend upon a certain class it becomes difficult to change that class. The Information
Expert Principle actually helps towards this end. Let’s check the previous example with the
SqlServerApi. Putting the CreateDatabase method in Program was bad design because
Program didn’t know about SqlServerApi and shouldn’t need to know about it. It created
unnecessary coupling between SqlServerApi and Program.
78
Figure 21: Sequence Diagram of High Coupling
As you can see in the diagram, there is a direct line between the Program and the
SqlServerApi. If the SqlServerApi changes, it is possible we need to change Program and
SqlServerApiAdapter. In the other design, where the SqlServerApiAdapter creates the
database, we get another figure.
79
Figure 22: Sequence Diagram of Low Coupling
As you see, the Low Coupling principle can be used to compare different design solutions and
we should, in most situations, pick the design which has the lowest coupling between classes.
Because Information Expert guides you in finding the class that has all the necessary
information for a certain responsibility, it helps lead to a design with the least coupling.
High Cohesion
Cohesion is the degree to which certain elements of a class belong together. The High
Cohesion Principle states that a class’ cohesion should be high. In other words, the methods
and properties of a class should belong together. Let’s look at another example. Suppose we
have a Person class with some properties and methods:
80
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
Cohesion is high because all properties and methods describe a person. Let’s add a method.
The cohesion of Person just went down. It’s not completely wrong, but you should ask yourself
if a Person really needs to know about a SalesOrder. It’s not unthinkable that you want to use
the Person class in a context where you don’t also want to depend on the SalesOrder class.
Maybe we could delegate the retrieval of SalesOrders for a Person to some other class.
81
FirstName = "Sander",
LastName = "Rossel",
DateOfBirth = new DateTime(1987, 11, 8)
};
SalesOrderRepository repo = new SalesOrderRepository();
List<SalesOrder> orders = repo.GetPersonsSalesOrders(sander);
I’m not saying this is the best solution, but it does increase the cohesion, and lower the
coupling, of the Person class.
As you see, High Cohesion and Low Coupling go hand in hand. When the cohesion of a class is
high the coupling is typically low. Again, the Information Expert and Low Coupling Principles
lead towards a design with the highest cohesion.
Pure Fabrication
We’ve seen Pure Fabrication a lot already. In fact, it’s what you do when some responsibility
doesn’t fit in any class you already have: you make up a new one specifically designed for this
one task. In the previous example, we created a SalesOrderRepository because getting
SalesOrders for a person in the Person class violated low coupling and high cohesion.
Basically, any class that does not model a domain object is a pure fabrication (a fabrication of
our imagination that is pure because it has only one responsibility).
Let’s look at another example. We still have our Person class. Now what class is going to save
our Person to the database? We don’t have any database classes yet and a Person has most
of the information necessary to save itself to the database. So it would seem alright to have the
Person class do the database logic necessary to save itself to the database. We already know
that’s not quite a good idea, mostly because we want our Person to have low coupling and high
cohesion.
Code Listing 100: Person Class that Breaks Low Coupling and High Cohesion
So we go about and create a pure fabrication, a class with the sole purpose of saving a Person
to the database. I won’t include the code here because I think you get the point. When we apply
other patterns and principles we’ve seen in this book, we end up with a Data Mapper and,
possibly, a Repository.
82
The Takeaway
GRASP is really useful when designing classes. Unlike anything else we’ve seen so far, they
aren’t of a very technical nature, and they don’t describe classes or methods. They describe
how to get an efficient design for your software. This chapter has shown that there is not one
design for an application. In fact, when we only had a Car and an Engine we already had two
design choices (and even more less obvious ones). Keeping GRASP in mind, we can get to
some design that’s at least better than many of the alternatives (there is no such thing as a
“best design”). The fun thing about GRASP is that a lot of it is already common sense to most
developers (like a Person shouldn’t save itself), but with GRASP you have some formal rules
that describe why it makes such common sense.
83
Chapter 6 Architecture
So far you’ve seen a lot of code on small scale. We’ve seen how to design a single class, how
to have multiple classes communicate with each other, and how to abstract away certain
components (like a database). Chances are you need to write more than a few classes though.
When looking at the high level structures of a software system, we speak about the architecture
of that system. In this chapter I’m going to discuss some technical challenges and methods that
you may encounter when building an application.
I want to emphasize what I will not discuss as well. I will not discuss the job of a software
architect, which is talking to the stakeholders, deciding on development processes (Agile or
Waterfall), documentation, budget, and other external factors that you’ll have to deal with when
building an actual application.
The architecture of a system is the part that is not easily changed. Opinions on this vary, but
let’s consider a database. Many people would point at the database, call it the heart of any
system, and tell you it’s pretty hard to change later on in the development process. We now
know, however, that when we abstract away the database behind a Data Mapper and a
Repository (on which the software depends through abstractions) changing databases is
“simply” a matter of switching our Data Mapper, and possibly Repository. Of course it’s still a lot
of work, and everything well have to be tested thoroughly, but we shouldn’t have to change our
front-end, for example.
So what is hard to change, then? Suppose half-way into the project you decide to change the
interface of your Data Mapper or your Repository. That could be pretty problematic. Or maybe
you decide to throw in an MVC and/or MVVM architecture. That will need a good rewriting of
many components.
Suppose you have a Person class which has save logic. We broke low coupling and high
cohesion, but we can save our Person.
84
And now we need a SalesOrder. Because we don’t have a single class that can save domain
objects, we’ll need to write the save functionality again, but this time for our SalesOrder. No
problem, we’ll just copy/paste it from Person!
// ...
It’s a no-brainer, but the programmer copy/pasted the Save method from Person and now the
SalesOrder literally reads “Database logic for Person here.” I have seen this happen many
times, even in production code!
There’s another problem though. The method doesn’t read “Database”, but “Dataase”. It seems
we have another bug. Let’s fix the SalesOrder class.
// ...
Neat, our SalesOrder works now! But our Person class has the same bug. We must now
remember to fix this or it will keep the same bug we just fixed in SalesOrder.
If we had one Save method that worked on both SalesOrder and Person we would not have
the first bug (SalesOrder saving a Person) and we would only have to solve the second bug
once. And that’s why you should strive to make code abstract: so you can write it once, test it
once, fix bugs once, and use it often.
85
Packages
By creating classes and methods, we can reuse our code throughout our application. But many
times you want to reuse code between applications. One example is a tool, maybe an XML or
JSON parser, or a data mapper, that you’ve written and that you want to use in other
applications as well. We’ve seen that copy/pasting, even between applications, is not practical.
You can reuse these components by creating packages (Dynamic Link Libraries or DLL’s) that
can be used by other applications. When you use .NET you’re actually just using packages
Microsoft created. Just like with class design there are some best practices when releasing and
using packages. In his book Agile Principles, Patterns, and Practices in C#, Robert C. Martin
discusses these practices5. I’ll quickly summarize them here.
It might be nice to mention that some script libraries, like jQuery UI (a JavaScript library), allow
you to download only the code that’s necessary for your use. You can then tick the components
you want and leave the rest. Of course, such practice is not possible for compiled packages
because you compile everything or nothing.
86
Acyclic Dependencies Principle (ADP)
The Acyclic Dependency Principle is really not an issue in C# and Visual Studio. According to
this principle, packages cannot depend upon packages that depend upon them, creating a cycle
in your dependencies. Making such dependencies is not possible in Visual Studio, though. If
you attempt to compile .NET code that violates the ADP, you'll get an error with a message that
complains you are creating a circular reference. Let’s dig into it a little deeper anyway. Suppose
you have four packages: Data, Business, UIComponents, and UI. UI depends upon Business
and UIComponents, and Business depends upon Data.
If Business changes we know UI depends on it, so we should check whether UI still works. We
know that UIComponents and Data remain unaltered though. Likewise, if Data changes we
know we should check Business and UI, but not UIComponents.
87
Figure 24: Dependencies with a Cycle
We have now created a cycle. If Business changes now we should check if UI still works, but
because Data now depends upon UI we should also check Data. If UIComponents changes,
you have to revalidate every package. This is tiresome for four packages, but in a real world
application with tens of packages it’s pretty much undoable. In any case, it’s very poor design
and prohibited by Visual Studio.
88
Layers and Tiers
You will often hear the terms layered or tiered software design. A layer is a level of abstraction.
A tier is a physical separation between software responsibilities. A client-server solution, for
example, is a 2-tier architecture. If you decide to throw in an extra server for some business
logic service, you have created a 3-tier architecture. N-tier architecture is relatively easy in
object-oriented programming because modules can easily be reused on different tiers.
When you practice the principles laid out in this book a layered architecture will come almost
naturally. A well-known layered structure is that of the OSI model, a model for describing the
different layers of the Internet. Simply put, your browser has no idea how to send bits and bytes
over a line, nor does your line know about any browser. Yet, through abstraction, both work
together to present websites and applications. The same principle goes for software. Your
application has no knowledge of a database, yet, through some IDataMapper interface, it is
able to communicate with a data storage.
Such a layer can easily be replaced without affecting the rest of the system. When you look at
the Internet, you can easily switch from a dial-up connection to ADSL to cable to wireless. No
need to replace your browser or your computer. Likewise, TCP/IP, the protocol used to send
and receive data on the Internet, can be switched for UDP, another faster, but less secure
protocol for sending data. In your application, you can switch your databases, or rebuild your
user interface, without touching the rest of the system (given that you’ve successfully separated
concerns in different layers).
89
Architectural styles and patterns
All these patterns, layers, and tiers can be combined to create greater architectural styles and
patterns that are not mutually exclusive. Picking what’s right for you and your project is
extremely difficult and probably a matter of what you know and what you prefer. Sure, some
patterns make more sense for specific applications or technologies, but overall you have some
choices.
Consider an ASP.NET MVC application. The name already implies we’re using MVC. The MVC
framework uses REST (Representational State Transfer, meaning, in simplified terms, that your
server just sits there waiting for a request, handles the request, sends a response, and
continues waiting). Perhaps you’re using AngularJS or KnockoutJS in the front-end, which is
MVVM. You’re probably already 3-tiered (HTML, CSS, AngularJS/KnockoutJS on the client, a
web server, and a database server). You can opt to create some additional services for
business logic that you can use for other platforms as well. Additionally, the front-end might
make use of an event-driven design.
As you see, you probably use a lot of patterns already and perhaps didn’t even know it.
Discussing all these patterns individually requires another few books, so I won’t do that. Having
these tough architectural decisions made for you by the framework or technology you’re using
may be how you like it, or you may want to create something on your own. There are pros and
cons to each approach.
The Takeaway
Object-oriented design should have no secrets for you now. You might be wondering how far
you should go in abstraction and reuse. After all, just because you can doesn’t mean you
should. It’s really hard to say where you should draw the line as it’s highly subjective. I once saw
the following abstraction:
90
Is this going too far? Has the programmer lost himself in a sea of abstraction? You might be
tempted to think so, but actually this is pretty smart. Imagine you have to run some tests on a
class that gives different results dependent on the current time (or date). That’s not uncommon
at all; maybe it’s a financial application that needs to get the exchange rate at a given date. So
try testing that if the codebase has DateTime.Now directly in the methods. With the
INowResolver you can inject your now and test for yesterday, now, and tomorrow.
Personally, I’ve never seen abstraction go too far. I have missed lots of abstractions though.
Sure, having many unnecessary abstractions is hard to read, but missing abstractions is hard to
maintain. So the only advice I can give here is to keep thinking, come up with different designs,
compare them using the tools I’ve laid out in this book, and use your best judgement. Luckily,
some of the harder decisions are already made for you by the framework or technology you
choose for your next project.
91
Chapter 7 Other Paradigms
By now I hope you’ve realized that Object-Oriented design is pretty awesome. It’s not the only
way to write software out there though. In fact, C# is a multi-paradigm language. Knowing other
paradigms helps to identify the strengths and weaknesses of OOP.
Procedural Programming
Procedural Programming has been around for a long time. The name comes from procedures or
subroutines, also known as methods. Procedural languages, like OO languages, have methods
(procedures), variables, data structures, and even some sort of modularity. Procedural
languages have no notion of classes, though. If two methods need access to the same variable
that variable must be declared on a global level. In larger applications this becomes problematic
as it’s very easy to accidentally manipulate such a variable and mess up your entire application.
Well known procedural languages are C, Pascal, FORTRAN, and BASIC.
Functional Programming
Even though Functional Programming has been around since the 50’s, it has recently seen an
uptick in popularity. The first functional language, in 1958, was LISP. In Functional Languages
functions, closely related to mathematical functions, have a central role, as just like in
mathematics a function can only work with the input it has been given. This makes it possible to
reason about functional programs because you know functions will not alter any program state.
Since functions are so important, it is easy to compose new functions from existing functions, to
return functions from functions, and to pass functions as input to other functions. We say that
functions are first class citizens. Functional languages often have a sophisticated type system
which makes it unnecessary to declare variable types, yet type safety is guaranteed.
C# has some functional constructs. For example LINQ and lambda’s have been borrowed from
functional languages. Other popular functional languages are F#, ML, Erlang, and Haskell.
Stateless programming
One big difference between Functional and OO Programming is the notion of state. Every OO
language has state, variables inside a class that determine the state of a class. Having state
does more for a language than you might think. For example, consider the following
Incrementer class:
92
public void Increment()
{
counter += 1;
}
The state of any Incrementer instance is determined by the value of counter. When we call
the Increment function we cannot know the state of our instance unless we knew the state
before we called Increment. This makes it very hard to reason about programs. When we call
GetIncrement, we don’t know what it will return because we don’t know the state of the object.
Let’s check out an example. Suppose we have a class Math with a function Add.
In this case, we know that if we call the function with parameters 1 and 2 the result will be 3.
However, and this is very important, in an OO language we can never be sure.
Nothing stops us from writing an Add function that changes the internal state of our Math class.
The change of a class’ internal state is called a side effect.
Functional Programming forbids such side effects. This makes it possible to predict the outcome
of a function given the input parameters. It’s difficult though; try writing an application without
state or side effects.
93
Aspect-Oriented Programming
OOP is great for many things. One thing it isn’t very good at is handling so-called cross-cutting
concerns. A cross-cutting concern is a general responsibility that is used throughout the
application. Think of logging, for example, which you might want to implement in just about any
method in every layer and every project. The result is that all your methods start with something
like Logger.Log(currentMethodName, inputParameters). Another example is something
like the INotifyPropertyChanging and INotifyPropertyChanged interfaces in .NET. They
can be implemented on a class, which should then raise the PropertyChanging and
PropertyChanged events whenever a property changes its value. The implementation is rather
tedious:
94
That’s a lot of boilerplate code! A class that would need one line of code now has over thirty!
Aspect-Oriented Programming aims to fix this issue by altering existing code dynamically. The
Proxy or Decorator Patterns are often used to accomplish this. One of the most known AOP
frameworks is probably PostSharp6. Another is DynamicProxy by Castle Project7.
6 https://www.postsharp.net/
7 http://www.castleproject.org/projects/dynamicproxy/
95
Conclusion
96