YOW West 2017OUR SPONSORS
Cost of a dependency
Dev at CashiesTrainer – Practical Rx
Lee CampbellAuthor of eBook and website IntroToRx.com Conference Circuit
Project success
LongevityHow long will your project need to be used for?
How long will it need to be maintained for?
How long will each of it’s dependent parts be relevant for?
FreedomsSingle man dependencies vs Fungible assets
Technology lock-in vs Technology agnostic
A case studyA COLLECTION OF EXPERIENCES
A case study
How did it get like this?COMPOUNDING EFFECTS
1. Single repo
Single repo\GUI
\Server
\Datastore
Single repo\GUI
◦ FeatureA
◦ FeatureB
\Server◦ FeatureA
◦ FeatureB
◦ Shared
\Datastore
Single repo\GUI
◦ FeatureA
◦ FeatureB
◦ FeatureC
\Server◦ FeatureA
◦ FeatureB
◦ FeatureC
◦ Shared◦ Logic
◦ Scripts (Builds, Deployments)
\Datastore
Single repo\GUI
◦ FeatureA
◦ FeatureB
◦ FeatureC
\Server◦ FeatureA
◦ FeatureB
◦ FeatureC
◦ Shared◦ Logic
◦ Scripts (Builds, Deployments)
\Datastore◦ FeatureA
◦ FeatureB
◦ FeatureC
Single repo\GUI
◦ FeatureA
◦ FeatureB
◦ FeatureC
◦ Shared
\Server◦ FeatureA
◦ FeatureB
◦ FeatureC
◦ Shared◦ Logic
◦ Contracts
\Framework◦ Comms Layer
◦ Data Persistence abstraction
◦ Scripts (Builds, Deployments)
\Datastore◦ FeatureA
◦ FeatureB
◦ FeatureC
Single repoWho defines requirements and budget for each part of the system?
Can this progression be maintained for the expected lifetime of the system?
Do these things change together?
Single repo - ConsequencesBuild times increase
Testing burden
Friction to innovate
Blurry boundaries
Lack of responsibility
2. Depend on abstractions
Interface all the thingsView Models
Translators
Validators
ConsequencesTesting now becomes an exercise in mocking
Debugging is always a case of hitting finding "implementations of"
ConsequencesFocus is diluted
Cognitive load is increased through indirection
Depend on (external) abstractionsWe can also take dependencies on interface define by someone else
So maybe you just mock out your ◦ IoC Continer
◦ SqlConnection
◦ ORM UnitOfWork
But these are normally defined in their package, with the implementation.
3. Deep layering
Deep layeringDeep system dependencies
Deep layering
Deep layeringMy application
◦ My libraries◦ My Framework
◦ My Framework subsystem
◦ Generic public packages
◦ Low level generic public packages
Deep layeringMy application
◦ My libraries (Domain, Data Access, Comms, Controls, Styles)◦ My Framework (DataAccess, Comms, Contracts, Generic Utilities, Controls, Styles)
◦ My Framework subsystem (Implementation specific DataAccess, Comms etc)
◦ Generic public packages (ORM, Serializers, Web Platform, Messaging, Document manipulation)
◦ Low level generic public packages (Network interfaces, Collections Libraries)
Deep layeringNon linear growth
3 deep with each dependency having 3 children
1 + 3 + 9 = 13 total
Deep layeringNon linear growth
Add 2 more layers (5 layers)
1 + 3 + (9 * 13) = 121 total
1
1 1 1
13 13 13 13 13 13 13 13 13
Deep layeringNon linear growth
Add 2 more layers (7 layers)
1 + 3 + (9 * 121) = 1093 total
1
1 1 1
121 121 121 121 121 121 121 121 121
+ baggagePackages that include
◦ minified and original resource
◦ Documentation (JavaDoc/Intellisense)
◦ Tooling
Deep call stacksI depend on abstractions
But they also depend on abstractions
So I have deep call stacks
Deep call stackshttps://twitter.com/gregyoung/status/734713437146734592
ConsequencesCognitive load increases exponentially with each layer
Technical freedom is slowly eroded as each layer add more dependencies
Compounding Consequences
Compounding consequencesBuild times
Test times
Lack of Ownership
Compensating behaviourMagic Build scripts
Using the real IoC Container in tests
AOP
Complicated becomes complexCant be rationalised about
Emergent behaviour (bugs, not features)
AlternativesIS THERE A BETTER WAY?
Single repoFEATURE DEPENDENCY
If it changes together, it lives togetherWays to identify
◦ The person that has final say on requirements is different
◦ Release cadences are different
◦ Code change cadence is different
◦ Failures are ignored
"Decompose your applications based on volatility" - Juval Lowy
Single repo\GUI
◦ FeatureA
◦ FeatureB
◦ FeatureC
◦ Shared
\Server◦ FeatureA
◦ FeatureB
◦ FeatureC
◦ Shared◦ Logic
◦ Contracts
\Framework◦ Comms Layer
◦ Data Persistence abstraction
◦ Scripts (Builds, Deployments)
\Datastore◦ FeatureA
◦ FeatureB
◦ FeatureC
Multi repoFeatureA
◦ GUI
◦ Server
◦ DataStore
◦ Contracts
FeatureB◦ GUI
◦ Server
◦ DataStore
◦ Contracts
FeatureC
◦ GUI
◦ Server
◦ DataStore
◦ Contracts
GUI Lib
Comms Lib
Persistence Lib
Multi repoInherently parallel to build and test
Forces the discussion about design by contract
Can reduce the knee jerk reaction to share code
Encapsulation
Justify the interfaceWhat is the benefit of this being injected?
Can it be encapsulated into this unit?
Private by defaultInstead of Reuse being a goal, aim for encapsulation.
Rule of 3
Reuse is an evolution
The snip ruleAvoid dependencies that require finesse to remove
Single line to cut
Code in actionA DOMAIN MODEL WITH NO DEPENDENCIES
Only depends on .NET
So how does it do anythingThe Domain Model defines the interfaces for the things it needs
◦ IRepository<T>
Can you tell what technology we are using here?
Consumers are responsible to implement it
We are isolating the business logic from our technology choices.
Inversion of Control
Hosts compose shallow dependenciesHexagonal Architecture (Alistair Cockburn)
Ports and Adapters
Onion Architecture
We define our PortsIRepository is one of our ports
We may have a SQLServer adapter, or perhaps a MongoDB one
Composition
App Service
Domain Model
Data Service
ORM Data store
Comms Service
SerializationMessaging platform
Composition
Domain Model
Commsadapter
Data adapter
App Service
Data store
Comms
AdaptersCODE BREAK OUT
Composition instead of AOPI can just use normal old Decorator pattern
ResultsMulti repo
◦ Division of labour
◦ Cohesive code base
◦ Reduced cognitive load
◦ Technical freedom
ResultsEncapsulation
◦ Reduced cognitive load
◦ Less busy work
◦ Snip rule
ResultsInversion of Dependencies / Ports and Adapter
◦ Focused code
◦ Fast tests
◦ Shallow stacks
◦ Technical Freedom
Know your costsCognitive load
Onboarding friction
Technical Freedom
Time to prod
More informationLeeCampbell.com
Implementing Domain Driven Design – Vaugh Vernon
Greg Young – Good enough software
Hex Arch – Alistair Cockburn
Having the computer to do what you want isn’t the hard part,having a person understand the intent of your code is.
Top Related