oncodedesign.com/implementing-clean-architecture
Drive predictability through Software
Design
Florin Coroș
florin@onCodeDesign.com
linkedin.com/in/florincoros
Implementing Clean Architecture
oncodedesign.com/implementing-clean-architecture
Drive predictability through Software Design
oncodedesign.com/DevTalks-Cluj
Software Architect Consultant
Technical Trainer
Founder of Code Design
enjoing playing GO
enjoing traveling
Florin Coroș
oncodedesign.com/implementing-clean-architecture
Drive predictability through Software
Design
Florin Coroș
florin@onCodeDesign.com
linkedin.com/in/florincoros
Implementing Clean Architecture
oncodedesign.com/implementing-clean-architecture
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
oncodedesign.com/implementing-clean-architecture
Decompose - Separation of Concerns
5
Title
Title
Title
Title
Title
Title
Title
oncodedesign.com/implementing-clean-architecture
Manage the Complexity and Size
when projects do fail for reasons that are
primarily technical, the reason is often
uncontrolled complexity
6
oncodedesign.com/implementing-clean-architecture
The Architecture is Separation of
Concerns and a Set of Rules
7
External
Interfaces
UI Frameworks
Devices
Controllers
Entities
Entities
Use Cases
oncodedesign.com/implementing-clean-architecture
Implementing the Architecture
8
External
Interfaces
UI Frameworks
Devices
Controllers
Entities
Entities
Use Cases
oncodedesign.com/implementing-clean-architecture
Structure that Supports the Architecture
9
External
Interfaces
UI Frameworks Devices
Controllers
Entities
Entities
Use Cases
Clean Architecture
10
External
Interfaces
UI Frameworks
Devices
Controllers
Entities
Entities
Use Cases
http://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html
Presenter
Controller
UseCase
Implementation
Presenter
Controller
UseCase
Implementation
UseCase
InputAbstraction
UseCase
OutputAbstraction
Dependencies should be in one direction only
Source code dependencies can only point inwards
oncodedesign.com/implementing-clean-architecture
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
oncodedesign.com/implementing-clean-architecture
<<interface>>
ILogger
+LogError()
Logger
+LogError()
Creating a Structure for Clean
Architecture
12
External
Interfaces
UI Frameworks
Devices
Controllers
Entities
Entities
Use Cases
<<public interface>>
ILogger
+LogError()
<<Internal class>>
Logger
+LogError()
oncodedesign.com/implementing-clean-architecture
Hide External Libraries from App Code
13
<<Internal class>>
Exception Wrappers
<<public
Interface>>
API Interfaces
<<Internal class>>
Decorators
oncodedesign.com/implementing-clean-architecture
14
<<Interface>>
TDataModel
IRepository
+GetEntities<TDataModel>()
<<Interface>>
TDataModel
IUnitOfWork
+GetEntities<TDataModel>()
+SaveChanges()
Database
EfRepository EfUnitOfWork
<<Stereotype>>
<<DTO>>
Order
<<DTO>>
Person
Enforce Separation of Data Access Concerns
iQuarcDataAccess
14
oncodedesign.com/implementing-clean-architecture
DIP to Enforce Separation of Data Access
Concern
15
<<Interface>>
IDbContextFactory
+CreateContext()
Database
<<DTO>>
Customer
<<DTO>>
Order
<<DTO>>
Person
UnitOfWork
Repository DbContextFactory
<<Interface>>
TDataModel
IRepository, IUnitOfWork
+GetEntities()
+SaveEntities()
15
oncodedesign.com/implementing-clean-architecture
<<Attribute>>
ServiceAttribute
+ServiceAttribute(interface : Type )
IBootstrapper
+Run()
<<Internal>>
DependencyContainerAdapter
iQuarcAppBoot
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
}
}
oncodedesign.com/implementing-clean-architecture
AppBoot: DI Abstractions & Type Discovery
17
<<Interface>>
IDbContextFactory
+CreateContext()
Database
<<DTO>>
Customer
<<DTO>>
Order
<<DTO>>
Person
UnitOfWork
Repository DbContextFactory
<<Interface>>
TDataModel
IRepository, IUnitOfWork
+GetEntities()
+SaveEntities()
<<Attribute>>
ServiceAttribute
oncodedesign.com/implementing-clean-architecture
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
oncodedesign.com/implementing-clean-architecture
25
Create Development Patterns in Code
25
oncodedesign.com/implementing-clean-architecture
/iQuarc
Implementing Clean Architecture through
Structure
26
External
Interfaces
UI Frameworks
Devices
Controllers
Entities
Entities
Use Cases
<<Attribute>>
<<Attribute>>
ServiceAttribute
RepositoryImpl
+ GetEntities<T>() : IQueriable()
+ SaveChanges()
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
/iQuarc
oncodedesign.com/implementing-clean-architecture
Drive predictability through Software Design
Implementing Clean
Architecture
florin@onCodeDesign.com
linkedin.com/in/florincoros
oncodedesing.com/training
oncodedesing.com/implementing-clean-
architecture
calendly.com/florin-oncodedesign/short-call
Florin Coroș
Software Architect Consultant
Technical Trainer

Implementing Clean Architecture - Conference Talk

Editor's Notes

  • #4 4’ – 5’
  • #6 10’
  • #7 11’
  • #8 13’
  • #10 starts: 17’ ends: 26’ The Clean Architecture aims directly to the target: Reduce the Cost, more importantly the cost of change It does that by protecting the most important code that we write, from change The most important code for our application is the BusinessLogic code, the one that implements the application use cases flows and the one that describe the Rules of our application domain To protect it the Clean architecture emphases that: The Application Code should NOT depend on Frameworks, it should be the other way around. The frameworks should depend on the Application Code This means that it will only change if the Application changes if the Business rules change. Not because the frameworks change! To describe this main idea Clean Architecture uses concentric circles or better said disks one on top of the other
  • #11 26’
  • #12 29’ The abstraction defines the application needs It will only change if application needs change
  • #13 35’ Addresses the conflict between the library creator and library user! Libraries can be used for any kind of applications. We are not interested in building any kid of application, we are interested in building THIS specific application
  • #15 We could even take out from the VS Solution the DbContextProvider project if the Context.tt generate is triggered by the SalesEntities.tt and a post build event of the DataModel assembly also builds the DbContextProvider.csproj
  • #16 36’ - By hiding the underlying DI Container it makes that the configuration of it can ONLY be done at app startup through annotations or conventions
  • #17 37’
  • #18 39’ Dependencies are visible in the constructor Dependencies are on interfaces ONLY  Loose Coupled code  testable code Dependencies are visible, so we can see classes that have too many dependencies –> poor cohesion  refactor to loose coupling The Implementation depends on INTERFACES of other services it uses and on DTOs which are paramenters
  • #22 There is no other way to get an implementation of the IRepository than DI - IRepository used to get data for read-only - Light implementation that can only be obtained through DI - Returns IQueriable<T> - Central place for all queries to the database Testable code No need to pass IRepository as parameters!
  • #23 The UnitOfWork can only be created through this factory method on the repository The UnitOfWork is in an using statement. It has a very well defined scope It is not to be passed as parameters to methods
  • #25 40’ By implementing Clean Architecture principles and by enforcing the we also create patterns in the way the entire application code gets written These patterns create consistency in code which also reduces the cost of change I do this through structure
  • #26 41’
  • #28 - When does quality pay off? All projects have a slower start and then the efficiency increases. The project reaches an healthy productivity rate after the design payoff line Interesting aspects about intersection point Prj finishes before the intersection point: prototype, throw away, PoC Technical / strategic debt can be done bellow. - Cannot be done above: even if you pay less attention/effort on quality you will still need TOO much time to add a feature and the quality still drops - less quality  slower you are Above the line we were in the initial example, but without knowing it! CHALLENGE: unaware of having bad code or taking too big technical debt. It takes us by surprise I will show how by doing GOOD unit tests you can keep this under control by having indicators of when your quality drops By being on the blue line with our prj most of the times we have done a great job in making our customers/managers not to trust us! It is important to know where you are. As long as you are under the line you may take technical debt but you must be aware! To be able to keep it under control Good UT can help us knowing when our quality drops and we sleep over the line
  • #29 All projects have a slower start and then the efficiency increases. The project reaches an healthy productivity rate after the design payoff line
  • #31 A question I always get A: You need to convince management on the benefits it has. The best way to talk to management is to use their language. There are two words management knows: COST and PROFIT Explain the benefits in these terms
  • #33 - Technical / strategic debt can be done bellow the line No Design, no trade-off: no matter how less attention I will pay to the design I will still go slow. I am impeded by the mess. Less quality -> less options -> more unexpected things -> slower you are Design: I can make the trade-off - Red team productivity NEVER decreases. See above chart with productivity going to 0. - It is important to know where you are. As long as you are under the line you may take technical debt but you must be aware! To be able to keep it under control - When not pay attention to design: - Prj finishes before the intersection point: prototype, throw away, PoC - CHALLENGE: unaware of having bad code or taking too big technical debt. It takes us by surprise - By being on the blue line with our prj most of the times we have done a great job in making our customers/managers not to trust us!
  • #34 51’