Code Quality Through Application Software Infrastructure (Florin Coros)

35
Premium community conference on Microsoft technologies itcampro @ itcamp14 # Code Quality through Application Software Infrastructure Florin Coros www.rabs.ro [email protected] @florincoros blog.iquarc.com/florin

description

Badly designed code is one of the highest price we pay as an industry. In many cases the cost of adding or changing features increases with the time we advance into the project. The bigger the project gets, the more complex it gets and the more costly it is to work on it, if it lacks structure. In this session I will show from real world projects experience how to keep your team efficient and how to reduce the cost of change with what I call the Application Software Infrastructure. It gives the means to control the size and complexity in large projects. It assures code quality through structure rather than relying on discipline only. It documents the architecture into code and bridges this way the architectural diagrams and the code structures.

Transcript of Code Quality Through Application Software Infrastructure (Florin Coros)

Page 1: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

Code Quality through Application Software Infrastructure

Florin Coros

[email protected]

@florincoros

blog.iquarc.com/florin

Page 2: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

Huge thanks to our sponsors & partners!

Page 3: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

About me

Co-Founder

Software Architect@florincoros

Founder & Partner

Page 4: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

Inspired

Page 5: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

Why Code Quality?

Page 6: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

How to Get to Code Quality?

Architecture

App Software Infrastructure

Vertical Slice

ReviewGood UTRefactor

DeliverFunctionality

DeliverFunctionality

DeliverFunctionality

Page 7: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

Application Infrastructure

Page 8: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

The Application Foundation

Page 9: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

Wrongly Built House

Page 10: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

Different Solutions to the Same Problem

Page 11: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

Which one is the ONE?

Page 12: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

when projects do fail for reasons that are primarily technical, the reason is

often

uncontrolled complexity

Importance of Managing Complexity

Page 13: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

Importance of Managing Complexity

Scalability

Availability

Multitenancy

Security

Authorization

Page 14: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

App Infrastructure Enforces the Architecture

Page 15: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

App Infrastructure – Primary TOOL to Control Complexity and Size

Page 16: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

Implementing a Complex and Large System

Page 17: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

Good Design vs Bad Design

http://martinfowler.com/bliki/DesignStaminaHypothesis.html

Page 18: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

<<Interface>>

IModule

+ Initialize()

Application

+ Initialize()*

+ Modules[]

AppModule1

+ Initialize()

AppModule2

+ Initialize()

• Modular Application Support

• Application modules do not depend on Frameworks

• Application can be hosted in any .NET process

App Boot: Modularity

3…..

\iQuarc

Page 19: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

• Makes Programming Against Interfaces the de facto programming model

• Abstracts and hides the Dependency Container

• Provides a maintainable mechanism for declaring services implementation

• Dictates how Dependency Injection is used

App Boot: Dependency Injection

<<Attribute>>

ServiceAttribute

+ ServiceAttribute()+ServiceAttribute(Type contract)+ ServiceAttribute(Type t, Lifetime lifetime)

Bootstrapper

+Bootstrapper(Assembly[] assemblies)+Run()

\iQuarc

Page 20: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

[WcfService(typeof(IPolicyAdministrationService))]

public class PolicyAdministrationService : IPolicyAdministrationService

{

private readonly IPolicyClassificationService classificationService;

private readonly IRepository repository;

public PolicyAdministrationService(IPolicyClassificationService

. classificationService, IRepository repository)

{

this.classificationService = classificationService;

this.repository = repository;

}

// . . .

}

[Service(typeof(IPolicyClassificationService))]class PolicyClassificationService : IPolicyClassificationService

{

private readonly IRepository repository;

public PolicyClassificationService(IRepository repository)

{

this.repository = repository;

}

//. . .

}

[Service(typeof(IRepository))]class Repository : IRepository

{

//...

}

App Boot: Declaring Service Implementations

• Allows only Constructor Dependency Injection

• Container configuration is not of the concerns of the application code

• Favors good code design• developers think in terms of services

• Opens opportunities to extend it with other discovery mechanisms• WCF Service

Page 21: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

public interface IOrderApproval{

bool ApproveOrder(Order o);}

[Service(typeof(IOrderApproval))]class CompositeOrderAprovalService : IOrderApproval{private readonly IEnumerable<IOrderApproval> approveActions;

public CompositeOrderAprovalService(IOrderApproval[] approvals){

this.approveActions = approvals.OrderByPriority();}

public bool ApproveOrder(Order o){

return approveActions.All(action => action.ApproveOrder(o));}

}

[Priority(Priorities.High)][Service("Stock Approval", typeof(IOrderApproval))]class StockOrderApproval : IOrderApproval{

private readonly IRepository repository;

public StockOrderApproval(IRepository repository){

this.repository = repository;}

public bool ApproveOrder(Order o){

//...}

}

[Priority(Priorities.Medium)]

[Service("Customer Approval", typeof(IOrderApproval))]

class CustomerOrderApproval : IOrderApproval

{

private readonly IRepository repository;

public CustomerOrderApproval(IRepository repository)

{

this.repository = repository;

}

public bool ApproveOrder(Order o)

{

//...

}

}

[Priority(Priorities.Medium)]

[Service("Ammount Approval", typeof(IOrderApproval))]

class OrderAmountApproval : IOrderApproval

{

private readonly IOrderCalculationsService calculationSrv;

public OrderAmountApproval(IOrderCalculationsService srv)

{

this.calculationsService = calculationsService;

}

public bool ApproveOrder(Order o)

{

//...

}

}

App Boot: Favors Composition and OCS Principle

Page 22: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

public IEnumerable<Policy> GetPolicyFromMutation(Mutation

mutation)

{

var policies = repository.GetEntities<PolicyImage>()

.Where(image => image.MutationId==mutation.Id)

.Select(image => new Policy

{

Id = image.PolicyId,

ValidAt = image.Mutation.Date

//..

}).ToList();

// do other calculations / grouping on data

return policies;

}

public void CalculateChanges(ChangeEvent change)

{

using (var uof = repository.CreateUnitOfWork())

{

var policies = uof.GetEntities<PolicyImage>()

.Where(i => i.Status == ImageStatus.Calculating &&

. i.EvendId == change.Id);

foreach (PolicyImage image in policies)

{

image.Ammunt = GetAmmountFor(image, change);

}

uof.SaveChanges();

}

}

Encapsulate Data Access Concerns

<<Interface>>

IRepository

+GetEntities<T>() : IQueriable<T>

<<Interface>>

IUnitOfWork

+SaveChanges()

Database

Repository UnitOfWork

<<Stereotype>><<DTO>>

Plan<<DTO>>

Contract

+CreateUnitOfWork() +GetEntities<T>():IQueriable<T>

Page 23: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

Consistency through StructureFunctional Modules

Module1

DataModel

Module2.Services

Contracts

Infrastructure

Technical Modules

CRUD.Services

CRUD.Web

Core Infrastructure

Data Access

Web Application

ServicesInfra

ApplicationBoot

WFC Application

WebInfra

CommonInfra

Module1.Web

Module2

DataModel

Module2.Web

Module2.Services

Page 24: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

RepositoryImpl

+ GetEntities<T>() : IQueriable()

IRepository IUnitOfWork

+ SaveChanges()

Consistent Data Access -> Low Extension Costs

Logging Query Execution

Page 25: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

RepositoryImpl

+ GetEntities<T>() : IQueriable()

IRepository IUnitOfWork

+ SaveChanges()

Consistent Data Access -> Low Extension Costs

Data Consistency Validation

public interface IEntityInterceptor<T> : IEntityInterceptorwhere T : class

{void OnLoad(IEntityEntryFacade<T> entry, IRepository rep);void OnSave(IEntityEntryFacade<T> entry, IRepository rep);void OnEntityRemoved(IEntityEntryFacade<T> entity,

. IRepository rep);}

public class Repository : IRepository{//...void InterceptSave(DbContext context, List<object> intercept){

var modifiedEntities = GetModifiedEntities(context);

foreach (object entity in modifiedEntities){

Intercept(allInterceptors, entity,(i, e) => i.OnSave(e, this));

}}

}

Page 26: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

RepositoryImpl

+ GetEntities<T>() : IQueriable()

IRepository IUnitOfWork

+ SaveChanges()

Consistent Data Access -> Low Extension Costs

Auditing

public interface IAuditable{

DateTime? LastEditDate { get; set; }DateTime CreationDate { get; set; }string LastEditBy { get; set; }string CreatedBy { get; set; }

}

[Service("AuditableInterceptor", typeof(IEntityInterceptor))]public class AuditableInterceptor : Interceptor<IAuditable>{public override void OnSave(IEntityEntryFacade<IAuditable> . entity, IRepository rep){

// ...if (entity.State == EntityEntryStates.Added){

entity.Entity.CreationDate = systemDate;entity.Entity.CreatedBy = userName;

}

entity.Entity.LastEditDate = systemDate;entity.Entity.LastEditBy = userName;

}}

Page 27: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

RepositoryImpl

+ GetEntities<T>() : IQueriable()

IRepository IUnitOfWork

+ SaveChanges()

Consistent Data Access -> Low Extension Costs

Data Authorization

public IQueryable<T> GetEntities<T>(){

IQueryable<T> entities = GetEntitiesInternal<T>();

IQueryable<T> filtered = FilterByBrand(entities);

return filtered;}

private IQueryable<T> FilterByBrand<T>(IQueryable<T> entities){int brandLabelId = ClaimsPrincipal.Current

.GetClaimValue<int>(Claims.BrandLabelId);

Expression<Func<T, int?>> selector=SelectBrandIdFrom(entities);

var condition =ExpressionBuilder.BuildWhereExpression(selector, brandLabelId, ExpressionType.Equal);

return entities.Where(condition);}

Page 28: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

RepositoryImpl

+ GetEntities<T>() : IQueriable()

IRepository IUnitOfWork

+ SaveChanges()

Consistent Data Access -> Low Extension CostsData Localization

private IQueryable<T> GetEntitiesInternal<T>(){

DbSet<T> set = context.Set<T>();

return new DataLocalizationQueryable<T>(queryableSet); }

class DataLocalizationQueryable<T> : IOrderedQueryable<T>{private DataLocalizationExpressionVisitor translationVisitor;private IQueryable<T> internalQuery;

public DataLocalizationQueryable(IQueryable<T> query){internalQuery = query;translationVisitor = new DataLocalizationExpressionVisitor();Provider = new DataLocalizationQueryProvider(query.Provider,

this.translationVisitor);

this.ElementType = typeof(T);}

public IEnumerator<T> GetEnumerator(){

return internalQuery.Provider.CreateQuery<T>(translationVisitor.Visit(internalQuery.Expression)).GetEnumerator();

}

Page 29: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

Decomposition by Volatility

Page 30: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

Generic CRUD Screens / Services

Page 31: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

Edit Contract

Monthly

Never

0

Recalculation Period

Recalculation

OKCancel

Minimum Cost: No

Minimum Amount For Cost Recalculation:

Yes

// Contract cost fields are UNAVAILABLE when ...

container

.Register(c => c.RecalculationPeriod_ID,

c => c.CostType.Recalculation != Never);

.Register(c => c.MinAmount,

c => c.CostType.MinAmountForCost == false);

Generic Implementation for Fields Availability

Edit Contract

Monthly

Periodical

0

Recalculation Period

Recalculation

OKCancel

Minimum Cost: No

Minimum Amount For Cost Recalculation:

Yes

Page 32: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

Application Infrastructure – Shaping to Context

.NET Framework

WF

WCF

WEB API

ASP.NET

Entity Framework

. . . Unity

NServiceBus Log4Net

. . .

Application Infrastructure

Application Functionalities

Page 33: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

How to do it?cu

mu

lati

ve f

un

ctio

nal

ity

time

completion

constructionready

design payoff

Page 34: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

How to do it?cu

mu

lati

ve f

un

ctio

nal

ity

time

completion

constructionready

design payoff

time

Arc

Arc

Infr

a

Fun

ctio

nal

ity

Infr

a Fun

ctio

nal

ity

Infr

a Fun

ctio

nal

ity

Fun

ctio

nal

ity

Fun

ctio

nal

ity

Fun

ctio

nal

ity

RepositoryImpl

+ GetEntities<T>() : IQueriable()

IRepository IUnitOfWork

+ SaveChanges()

IModule

<<Attribute>>

ServiceAttribute

\iQuarc

Fun

ctio

nal

ity

Page 35: Code Quality Through Application Software Infrastructure (Florin Coros)

Premium community conference on Microsoft technologies itcampro@ itcamp14#

Thank You!