Has implementing Clean Architecture become more of an ideal than a reality in your projects? Despite its clear rules and intended separations, the complexity of growing codebases and the crunch of time often render these principles invisible in practice. When projects technically fail, the culprit i...
Has implementing Clean Architecture become more of an ideal than a reality in your projects? Despite its clear rules and intended separations, the complexity of growing codebases and the crunch of time often render these principles invisible in practice. When projects technically fail, the culprit is frequently uncontrolled complexity – where Clean Architecture remains a concept on paper, not in code.
In this session, I will show how to get predictability by implementing Clean Architecture through structure, rather than relying on discipline and code reviews only. I’ll show how to create a structure that makes it easy to write the code that follows your architecture and at the same time it makes it difficult to write the code that doesn’t.
You will walk away with a recipe and building blocks for creating a foundation in code that sustains Clean Architecture and the level of quality in your code that can control the complexity of the project.
This structure will enforce separation of concerns and how dependencies are created. It will deliver predictability by creating a Code Design that is maintainable, extensible and reusable.
oncodedesign.com/ DevTalks -Cluj Software Architect Consultant Technical Trainer Founder of Code Design e njoing playing GO e njoing traveling Florin Coro ș
Why is Architecture Important -- Robert C. Martin, Clean Architecture The goal of software architecture is to minimize the human resources required to build and maintain the required system 4
Decompose - Separation of Concerns 5
Manage the Complexity and Size when projects do fail for reasons that are primarily technical, the reason is often uncontrolled complexity 6
The Architecture is Separation of Concerns and a Set of Rules 7
Implementing the Architecture 8
Structure that Supports the Architecture 9
Clean Architecture 10 http://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html Dependencies should be in one direction only Source code dependencies can only point inwards
Implementing Clean Architecture through Structure 11 Hide external frameworks to enforce the way they are used Use assemblies and references among them to enforce rules Enforce Constructor Dependency Injection that encourages Programming Against Interfaces Create a structure that makes it difficult to write bad code and it makes it easy to write good code , code that follows the architecture and the design
Creating a Structure for Clean Architecture 12
Hide External Libraries from App Code 13
Enforce Separation of Data Access Concerns \iQuarc\ DataAccess 14 14
DIP to Enforce Separation of Data Access Concern 15 15
\iQuarc\ AppBoot AppBoot Hides the DI Framework under Abstractions 16 public interface IPriceCalculator { int CalculateTaxes ( Order o, Customer c); int CalculateDiscount ( Order o, Customer c); } [ Service ( typeof ( IPriceCalculator ), Lifetime .Instance )] interal class PriceCalculator : IPriceCalculator { public int CalculateTaxes ( Order o, Customer c) { return 10; // do actual calculation } public int CalculateDiscount ( Order o, Customer c) { return 20; // do actual calculation } }
AppBoot : DI Abstractions & Type Discovery 17
Patterns on how most of the code is written [ Service ( typeof ( IOrderingService ))] private class OrderingService : IOrderingService { private readonly IRepository repository; private readonly IPriceCalculator calculator; private readonly IApprovalService orderApproval ; public OrderingService ( IRepository repository, IPriceCalculator calculator, IApprovalService orderApproval ) { this .repository = repository; this .calculator = calculator; this .orderApproval = orderApproval ; } public SalesOrderInfo [] GetOrdersInfo ( string customerName ) { var orders = repository.GetEntities < SalesOrderHeader >() ... return orders.ToArray (); } public SalesOrderResult PlaceOrder ( string customerName , OrderRequest request) { ... } } 18
Enforce Constructor DI to Prevent Circular Dependencies [ Service ( typeof ( IApprovalService ))] class ApprovalService : IApprovalService { private readonly IPriceCalculator priceCalculator ; public ApprovalService ( IPriceCalculator priceCalculator ) { this .priceCalculator = priceCalculator ; } ... } [ Service ( typeof ( IPriceCalculator ), Lifetime .Instance )] public class PriceCalculator : IPriceCalculator { private readonly IApprovalService approvalService ; public PriceCalculator ( IApprovalService approvalService ) { this .approvalService = approvalService ; } ... } 19 19
Encapsulate Data Access Concerns \iQuarc\ DataAccess [ Service ( typeof ( IRepository ))] internal class EfRepository : IRepository , IDisposable { private readonly IDbContextFactory contextFactory ; private readonly IInterceptorsResolver interceptorsResolver ; private DbContext context; private readonly IEnumerable < IEntityInterceptor > interceptors; public EfRepository ( IDbContextFactory contextFactory , IInterceptorsResolver resolver) { this .contextFactory = contextFactory ; this .interceptorsResolver = interceptorsResolver ; this .interceptors = resolver.GetGlobalInterceptors (); } ... } 20 20
public interface IRepository { IQueryable < TDbEntity > GetEntities < TDbEntity >() where TDbEntity : class ; IUnitOfWork CreateUnitOfWork (); } public interface IUnitOfWork : IRepository , IDisposable { void SaveChanges (); void Add< T >( T entity) where T : class ; void Delete< T >( T entity) where T : class ; void BeginTransactionScope ( SimplifiedIsolationLevel isolation); } Create Separated Patterns for Read-Only and Read-Write 21 21