8. Singleton: Intent
Ensure a class has only one instance
Make the class itself responsible for
keeping track of its sole instance
“There can be only one”
12. Singleton Consequences
The default implementation not thread-safe
Avoid in multi-threaded environments
Avoid in web server scenarios (e.g. ASP.NET)
Singletons introduce tight coupling among collaborating
classes
Shameless Plug:
But why would you
Telerik JustMock can be
intentionally write code
Singletons are notoriously difficult to test usedcan mocktest with
you to only and test
Commonly regarded as an anti-pattern certainSingletons tools?
premium
Violate the Single Responsibility Principle
Class is responsible for managing its instances as well as whatever it
does
Using an IOC Container it is straightforward to avoid the
coupling and testability issues
15. Strategy: Intent
Encapsulate a family of related algorithms
Let the algorithm vary and evolve independently from the
class(es) that use it
Allow a class to maintain a single purpose
Single Responsibility Principle (SRP)
Also enables Open/Closed Principle (OCP)
Learn more about SRP and OCP here:
http://pluralsight.com/training/Courses/TableOfContents/principles-oo-design
17. Strategy : Common Usage
Dependency Inversion and Dependency Injection
Decouple class dependencies and responsibilities
Refactoring Steps
Create interfaces for each responsibility
Inject the implementation of the interface via the constructor
Move the implementation to a new class that implements the
interface
18. Hidden Dependencies
Classes should declare their dependencies via their
constructor
Avoid hidden dependencies
Anything the class needs but which is not passed into constructor
Avoid making non-stateless static calls
Avoid directly instantiating classes (except those with no
dependencies, like strings)
Instead, move these calls to an interface, and call a local instance of the
interface
19. “New is Glue”
“new” creates tight coupling
between classes
Be conscious of the
consequences of using
“new”
If you need loose
coupling, replace
“new” with Strategy
Pattern
http://flic.kr/p/aN4Zv
21. Data Access Evolution
No separation of concerns: Compile Time
Runtime
Data access logic baked directly into UI
ASP.NET Data Source Controls
Classic ASP scripts User Interface
Data access logic in UI layer via codebehind
ASP.NET Page_Load event
ASP.NET Button_Click event
Database
22. Data Access : Helper
Classes Compile Time
Calls to data made through a
utility Runtime
Example: Data Access
Application Block (SqlHelper) User Interface
Logic may still live in UI layer
Helper Class
Or a Business Logic Layer may
make calls to a Data Access
Layer which might then call the
helper
Database
23. What’s Missing? Compile Time
Abstraction! Runtime
No way to abstract away
data access User Interface
Tight coupling
Leads to Big Ball of Mud Core Infrastructure
system IFooRepository SqlFooRepository
Solution:
Depend on interfaces, not
concrete implementations
What should we call such Database
interfaces? Repositories!
24. Repository
A Data Access Pattern
Separates persistence responsibility from business classes
Enables
Single Responsibility Principle
Separation of Concerns
Testability
Frequently Separate Interfaces for Each Entity in Application
E.g. CustomerRepository, OrderRepository, etc.
Or using Generics: IRepository<TEntity>
May also organize Repositories based on
Reads vs. Writes
Bounded Contexts
26. Repository - Example
(1)
Create/extend an interface to represent
the data access you need
(2)
Copy the
implementation from
your class into a new
class implementing this
interface.
(3)
Inject the interface using the
Strategy Pattern. Use the local field
of this interface type in place of
previous implementation code.
27. Where do Repositories Live?
Place interfaces in Core
Core includes Model classes and most business logic
Core has no dependencies (ideally)
Place implementation in Infrastructure
Infrastructure references Core
UI layer references both Core and Infrastructure
Responsible for creating object graph, either manually or via an
IOC Container
29. Proxy
A class that controls access to another
Implemented via subclass or via delegation using a
common interface
Frequent use cases:
Remote Proxy for web services / network calls
Lazy loading implementations
Security / access control
31. Adding Caching to a
Repository
Caching is frequently added to query methods in repositories
Caching logic is a separate concern and should live in a
separate class from the main data access logic
Proxy pattern provides a straightforward means to control
access to the “real” data, versus the cache
33. Implementing with IOC
// Strategy Pattern with Proxy Pattern (using composition)
x.For<IAlbumRepository>().Use<CachedAlbumRepository>()
.Ctor<IAlbumRepository>().Is<EfAlbumRepository>();
35. Command
Represent an action as an object
Decouple performing the action
from the client that is issuing the
command
Common scenarios:
Delayed execution
Logging activity
Enabling Undo / Revoke
Transaction functionality
39. Factory: Intent
Separate object creation from the decision of which object to
create
Defer creation of objects
Only create them if and when needed
Add new classes and functionality without breaking client code
Only factory needs to know about new types available
Store possible objects to create outside of program
Configuration
Persistent Storage
Plug-in assemblies
43. References
Design Patterns, http://amzn.to/95q9ux
Design Patterns Explained, http://amzn.to/cr8Vxb
Design Patterns in C#, http://amzn.to/bqJgdU
Head First Design Patterns, http://amzn.to/aA4RS6
Pluralsight Resources
N-Tier Application Design in C# http://bit.ly/Msrwig
Design Patterns Library http://bit.ly/vyPEgK
SOLID Principles of OO Design http://bit.ly/OWF4la
My Blog
http://ardalis.com
44. Summary
Design Patterns can be used during
refactoring or initial design to improve code
quality
Become comfortable with a number of design
patterns, but focus on the most common ones
Use design patterns to address pain in your
design, such as tight coupling or excessive
repetition
Design patterns can be combined in powerful
ways, such as Strategy-Proxy-Repository
Notas del editor
General, reusable solutions to common problemsNot a complete, finished solutionA template, recipe, or approach to solving certain problemsEach has a specific name, so we can discuss common elements of design using a common vocabulary
Learning anything – a musical chord, a martial arts technique, etc.Zero: You used a what? Never heard of it.Awakening:Wow, I just learned how XYZ pattern can improve my design. I’m not really sure where it would work in my code, but I’m definitely looking.Overzealous:I totally “get” the XYZ pattern; I’m adding it everywhere I can shoehorn it into my code. My design’s gonna be better now, for sure!Mastery: In response to some specific design pain points, the XYZ pattern was a logical next step and was achieved through a simple refactoring.
Design pattern names provide placeholders or complex abstractions and sets of refactorings. Consider the difference between:We have some tight coupling to the database here. We can probably fix it if we apply these refactorings;extract an interface, extract a method, Extract a class,Replace local with parameterORLet’s apply the Repository pattern to fix it.
Used Regularly or Daily by most respondentsFactory (194)Repository (185)Iterator (139)Adapter/Wrapper (122)Observer (113)Command (106)Singleton (105)Strategy (101)Proxy (91)
It’s possible for the new Singleton(); line to be called more than once.
Here are three example registration commands using an IOC container, in this case StructureMap. If you’re not familiar with IOC containers, they’re basically just factories on steroids, which you configure to create instances of types according to certain rules.In the first case, one new instance of the type is created per thread, or per HTTP request. Thus, in an ASP.NET application, a new DbContext will be created with each new web request, but if we used this same code in a non-web context, such as in an integration test, it would create a single instance per thread. In the second case, the Singleton() call will literally configure the lifetime of the instance to be a singleton, with one and only one instance available for the life of this application. In the last, default case, each new request for an instance will get its own, separate instance of the requested type.The benefit of this approach is that it makes it very clear which objects are configured with which lifetimes, and none of the objects themselves are cluttered with these concerns. The resulting code has less repetition, is simpler, and its classes have fewer responsibilities.
Note – this cannot easily be tested without an actual database instance in place.
Apply patterns via refactoring,Not Big Design Up Front
Show the MvcMusicStore applicationHg clone https://hg.codeplex.com/forks/ssmith/mvcmusicstorerepositorypattern
Talk about the CacheDependencyBug in AdSignia and how it was introduced by moving a hard-coded instantiation to a parameter, and then fixed by replacing the parameter with a Factory (lambda).