applied patterns in the project
TRANSCRIPT
![Page 1: Applied patterns in the project](https://reader036.vdocuments.net/reader036/viewer/2022062412/5878a58f1a28ab42588b65c1/html5/thumbnails/1.jpg)
APPLIED PATTERNSThe current project implementation
![Page 2: Applied patterns in the project](https://reader036.vdocuments.net/reader036/viewer/2022062412/5878a58f1a28ab42588b65c1/html5/thumbnails/2.jpg)
TOPICS SOLID Repository pattern Unit of Work pattern Decorator pattern
![Page 3: Applied patterns in the project](https://reader036.vdocuments.net/reader036/viewer/2022062412/5878a58f1a28ab42588b65c1/html5/thumbnails/3.jpg)
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](https://reader036.vdocuments.net/reader036/viewer/2022062412/5878a58f1a28ab42588b65c1/html5/thumbnails/4.jpg)
REPOSITORY PATTERN Abstraction data access
Database Services Files Etc.
Hide implementation details
![Page 5: Applied patterns in the project](https://reader036.vdocuments.net/reader036/viewer/2022062412/5878a58f1a28ab42588b65c1/html5/thumbnails/5.jpg)
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](https://reader036.vdocuments.net/reader036/viewer/2022062412/5878a58f1a28ab42588b65c1/html5/thumbnails/6.jpg)
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](https://reader036.vdocuments.net/reader036/viewer/2022062412/5878a58f1a28ab42588b65c1/html5/thumbnails/7.jpg)
REPOSITORY IMPLEMENTATIONpublic Repository(DatabaseContext context){
this.context = context;
this.dbSet = context.Set<TEntity>();}
![Page 8: Applied patterns in the project](https://reader036.vdocuments.net/reader036/viewer/2022062412/5878a58f1a28ab42588b65c1/html5/thumbnails/8.jpg)
DI REGISTRATIONbuilder.RegisterGeneric(typeof(Repository<>))
.As(typeof(IRepository<>));
builder.RegisterType<DatabaseContext>()
.AsSelf()
.InstancePerLifetimeScope();
![Page 9: Applied patterns in the project](https://reader036.vdocuments.net/reader036/viewer/2022062412/5878a58f1a28ab42588b65c1/html5/thumbnails/9.jpg)
USAGEprotected StoreNewQueueItem( IRepository<ProcessQueue> processQueueRepository, ...){ this.processQueueRepository = processQueueRepository; ...}
...var insertedItem = processQueueRepository .Insert(queueItem);...
![Page 10: Applied patterns in the project](https://reader036.vdocuments.net/reader036/viewer/2022062412/5878a58f1a28ab42588b65c1/html5/thumbnails/10.jpg)
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](https://reader036.vdocuments.net/reader036/viewer/2022062412/5878a58f1a28ab42588b65c1/html5/thumbnails/11.jpg)
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](https://reader036.vdocuments.net/reader036/viewer/2022062412/5878a58f1a28ab42588b65c1/html5/thumbnails/12.jpg)
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](https://reader036.vdocuments.net/reader036/viewer/2022062412/5878a58f1a28ab42588b65c1/html5/thumbnails/13.jpg)
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](https://reader036.vdocuments.net/reader036/viewer/2022062412/5878a58f1a28ab42588b65c1/html5/thumbnails/14.jpg)
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](https://reader036.vdocuments.net/reader036/viewer/2022062412/5878a58f1a28ab42588b65c1/html5/thumbnails/15.jpg)
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](https://reader036.vdocuments.net/reader036/viewer/2022062412/5878a58f1a28ab42588b65c1/html5/thumbnails/16.jpg)
DECORATOR PATTERN CLASS DIAGRAM Decorator implements same interface
![Page 17: Applied patterns in the project](https://reader036.vdocuments.net/reader036/viewer/2022062412/5878a58f1a28ab42588b65c1/html5/thumbnails/17.jpg)
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](https://reader036.vdocuments.net/reader036/viewer/2022062412/5878a58f1a28ab42588b65c1/html5/thumbnails/18.jpg)
PUTTING IT ALL TOGETHER Create handler
Query Command
Repository Repository actions
Create decorator Committing changes
![Page 19: Applied patterns in the project](https://reader036.vdocuments.net/reader036/viewer/2022062412/5878a58f1a28ab42588b65c1/html5/thumbnails/19.jpg)
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](https://reader036.vdocuments.net/reader036/viewer/2022062412/5878a58f1a28ab42588b65c1/html5/thumbnails/20.jpg)
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](https://reader036.vdocuments.net/reader036/viewer/2022062412/5878a58f1a28ab42588b65c1/html5/thumbnails/21.jpg)
QUESTIONS?