6 Design Patterns to Improve Your Web Apps
6 Design Patterns to Improve Your Web Apps
to Improve
Your Web Apps
Steve Smith (@ardalis)
steve@ardalis.com
Ardalis.com
Podcast: WeeklyDevTips.com
Design Patterns
http://flic.kr/p/8XgqKu
Stages of Learning
http://flic.kr/p/6StgW5
Language
http://flic.kr/p/6UpMt9
Design Patterns
Iterator
Unit of
Work Composite
Specification
Most Useful (for web app design)
(Singleton)
Strategy
Repository
Proxy / Decorator
Command
Builder
Null Object
Singleton: Intent
Ensure a class has only one instance
Source: http://csharpindepth.com/Articles/General/Singleton.aspx
Singleton Consequences
The default implementation is not thread-safe
Avoid in multi-threaded environments
Avoid in web server scenarios (e.g. ASP.NET)
http://flic.kr/p/6spkwo
Strategy: Intent
Encapsulate a family of related algorithms
Let the algorithm vary and evolve independently from the class(es) that use it
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
Hidden Dependencies
Classes should declare their dependencies via their constructor
Follow the Explicit Dependencies Principle
Be conscious of the
consequences of using
“new”
http://flic.kr/p/aN4Zv
Also works with WebForms
Repository
Data Access Evolution
Compile Time
Initially no separation of concerns
Runtime
Database
Data Access : Helper
Classes Compile Time
User Interface
Example: Data Access
Application Block (SqlHelper)
Runtime
No way to abstract away data
access
User Interface
Tight coupling
Solution:
Depend on interfaces, not
concrete implementations
What should we call such Database
interfaces? Repositories!
Repository
A Data Access Pattern
Introduced as part of Domain-Driven Design, but very popular outside of DDD as well
Enables
Single Responsibility Principle
Separation of Concerns
Testability
Repository
Frequently Separate Interfaces for Each Entity in
Application
E.g. CustomerRepository, OrderRepository, etc.
Or using Generics: IRepository<TEntity>
22 Queries!
}
@model IEnumerable<LazyLoadingMvc5.Models.Session>
<h2>Sessions</h2>
(3)
Inject the interface using the
Strategy Pattern. Use the local field
of this interface type in place of
previous implementation code.
Where do Repositories Live?
Place interfaces in Core
Core includes Model classes and most business logic
Core has no dependencies (ideally)
Caching logic is a separate concern and should live in a separate class from the
main data access logic
http://flic.kr/p/5Yb5i
Command
Represent an action as an object
A Command is a message
Common scenarios:
Delayed execution
Logging activity
Enabling Undo / Revoke Transaction functionality
Command : Usage
Combine with messaging for scalability
if (env.IsDevelopment())
{
builder.AddUserSecrets<Startup>();
}
builder.AddEnvironmentVariables();
Configuration = builder.Build();
Builder for Test Data (TypeScript)
export class PrincipalBuilder {
private _principal: Principal = this.getTestPrincipal();
constructor() {}
public build() {
const newPrincipal = Object.assign({}, this._principal);
this._principal = this.getTestPrincipal();
return newPrincipal;
}
// getTestPrincipal
}
Builder for Test Data (TypeScript) -
Usage
let builder: PrincipalBuilder;
builder = new PrincipalBuilder();
BaseType
Repository:
Practice PDD
Pain Driven Development
“Don’t apply every pattern
you know to a problem
from the start; practice
Pain Driven Development.”
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
Discuss
Contact
steve@ardalis.com
Twitter: @ardalis
Web: ardalis.com
http://about.me/stevenasmith