21
APPLIED PATTERNS The current project implementation

Applied patterns in the project

  • Upload
    jandv

  • View
    36

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Applied patterns in the project

APPLIED PATTERNSThe current project implementation

Page 2: Applied patterns in the project

TOPICS SOLID Repository pattern Unit of Work pattern Decorator pattern

Page 3: Applied patterns in the project

SOLID Single Responsibility Principle

“a class should have only a single responsibility” Open/closed Principle

“software entities … should be open for extension, but closed for modification.”

Liskov substitution principle “objects in a program should be replaceable with

instances of their subtypes without altering the correctness of that program.”

Interface segregation principle ““many client-specific interfaces are better than one

general-purpose interface.” Dependency inversion principle

one should “Depend upon Abstractions. Do not depend upon concretions.”

Page 4: Applied patterns in the project

REPOSITORY PATTERN Abstraction data access

Database Services Files Etc.

Hide implementation details

Page 5: Applied patterns in the project

SEPERATION Repository.Database

Database context Initializers Migrations Scripts

Repository.Entities Entity objects (POCO)

Repository.DataAccess Repository abstraction layer

Page 6: Applied patterns in the project

REPOSITORY INTERFACEpublic interface IRepository<TEntity>

where TEntity : class{

IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null,Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,

string includeProperties = "");TEntity GetById(object id);TEntity Insert(TEntity entity);TEntity Delete(object id);TEntity Delete(TEntity entityToDelete);void Update(TEntity entityToUpdate);

}

Page 7: Applied patterns in the project

REPOSITORY IMPLEMENTATIONpublic Repository(DatabaseContext context){

this.context = context;

this.dbSet = context.Set<TEntity>();}

Page 8: Applied patterns in the project

DI REGISTRATIONbuilder.RegisterGeneric(typeof(Repository<>))

.As(typeof(IRepository<>));  

builder.RegisterType<DatabaseContext>()

.AsSelf()

.InstancePerLifetimeScope();  

Page 9: Applied patterns in the project

USAGEprotected StoreNewQueueItem( IRepository<ProcessQueue> processQueueRepository, ...){ this.processQueueRepository = processQueueRepository; ...}

...var insertedItem = processQueueRepository .Insert(queueItem);...

Page 10: Applied patterns in the project

UNIT OF WORK PATTERN “A Unit of Work keeps track of everything

you do during a business transaction that can affect the database. When you're done, it figures out everything that needs to be done to alter the database as a result of your work.”SOURCE: http://www.martinfowler.com/eaaCatalog/unitOfWork.html

Committing changes Handling of transaction

Page 11: Applied patterns in the project

COMMON REPOSITORY USAGEvar insertedItem = processQueueRepository .Insert(queueItem);processQueueRepository.Save();

OR

public virtual TEntity Insert( TEntity entity){ var insertedItem = dbSet.Add(entity); context.SaveChanges(); return insertedItem;}

Page 12: Applied patterns in the project

UNIT OF WORK + REPOSITORYpublic class MyCommand{

private readonly IUnitOfWorkFactory factory; public MyCommand(IUnitOfWorkFactory factory)

{this.factory = factory;

} public void Execute()

{using (var context = this.factory.CreateNew()){

this.DoSomeNiceThings(context); context.Commit();

}}

}  

SOURCE: http://stackoverflow.com/a/4944201/352640

Page 13: Applied patterns in the project

NOT A GOOD IMPLEMENTATION UoW + Repository, great idea Some of the greater developer minds are

opponents Violates some principles

Opaque dependencies Open/closed principle Single Responsibility Principle Nominal abstraction

Page 14: Applied patterns in the project

BETTER IMPLEMENTATION? List of example implementations:

SOURCE: https://lostechies.com/derekgreer/2015/11/01/survey-of-entity-framework-unit-of-work-patterns/

Unit of Work Decorator Works everywhere Close to point of need More control Setup is hard!

Page 15: Applied patterns in the project

DECORATOR PATTERN “…the decorator pattern … allows behavior

to be added to an individual object … without affecting the behavior of other objects from the same class. The decorator pattern is often useful for adhering to the Single Responsibility Principle, as it allows functionality to be divided between classes with unique areas of concern.”SOURCE: https://en.wikipedia.org/wiki/Decorator_pattern

Extending functionality Adhering SRP

Page 16: Applied patterns in the project

DECORATOR PATTERN CLASS DIAGRAM Decorator implements same interface

Page 17: Applied patterns in the project

DECORATOR PATTERN EXAMPLE/// <summary>/// The 'Component' abstract class/// </summary>abstract class Component{ public abstract void Operation();} /// <summary>/// The 'Decorator' abstract class/// </summary>abstract class Decorator : Component{ protected Component component; public void SetComponent(Component component) { this.component = component; } public override void Operation() { if (component != null) { component.Operation(); } }}static void Main(){ // Create ConcreteComponent and two Decorators ConcreteComponent c = new ConcreteComponent(); ConcreteDecoratorA d1 = new ConcreteDecoratorA(); ConcreteDecoratorB d2 = new ConcreteDecoratorB(); // Link decorators d1.SetComponent(c); d2.SetComponent(d1); d2.Operation();}

/// <summary>/// The 'ConcreteComponent' class/// </summary>class ConcreteComponent : Component{ public override void Operation() { Console.WriteLine("ConcreteComponent.Operation()"); }}/// <summary>/// The 'ConcreteDecoratorA' class/// </summary>class ConcreteDecoratorA : Decorator{ public override void Operation() { base.Operation(); Console.WriteLine("ConcreteDecoratorA.Operation()"); }} /// <summary>/// The 'ConcreteDecoratorB' class/// </summary>class ConcreteDecoratorB : Decorator{ public override void Operation() { base.Operation(); AddedBehavior(); Console.WriteLine("ConcreteDecoratorB.Operation()"); } void AddedBehavior() { }}

Page 18: Applied patterns in the project

PUTTING IT ALL TOGETHER Create handler

Query Command

Repository Repository actions

Create decorator Committing changes

Page 19: Applied patterns in the project

USAGE THE TRANSACTION DECORATORpublic class TransactionRequestHandlerDecorator<...> :  IConvertorCommandHandler<...>{    private readonly IConvertorCommandHandler<...> decorated;    private readonly  MyDatabaseContext context;    public TransactionRequestHandlerDecorator(

IConvertorCommandHandler<...> decorated,MyDatabaseContext context)

    {        this.decorated = decorated;        this.context = context;    }

public void Handle(TCommand command){    Log.Debug("Starting new transaction.");    using (var transaction = context.Database.BeginTransaction())    {        try        {            decorated.Handle(command);            context.SaveChanges();            Log.Debug("Saving changes.");            transaction.Commit();            Log.Debug("Comitting the transaction.");        } ...

Page 20: Applied patterns in the project

DECORATOR REGISTRATIONforeach (var commandHandler in commandHandlers){ builder.RegisterGeneric(commandHandler) .Named("commandHandler", typeof(IConvertorCommandHandler<,,>));}

builder.RegisterGenericDecorator( typeof(TransactionRequestHandlerDecorator<,,>),  typeof(IConvertorCommandHandler<,,>),  fromKey: "commandHandler") 

.Named("decorated",  typeof(IConvertorCommandHandler<,,>));  

Page 21: Applied patterns in the project

QUESTIONS?