Podcast: Play in new window | Download
Subscribe: Apple Podcasts | Spotify | TuneIn | RSS
It’s time for another deep dive into Robert C. Martin’s Clean Architecture as Joe puts us on the spot, Allen has a new mission, and Michael shares his Easter eggs.
Sponsors
- FreshBooks.com/Coding – Use code “CODING BLOCKS” in the “How Did You Hear About Us?” section
Survey Says
While we patiently wait for Spring to arrive, we ask: When you’re not coding for work/school, in your free time do you …
News
- We take a moment to appreciate and thank those that left us a review:
- iTunes: Srolesen
- Stitcher: JackOfAllPythons
- The 5 worst programming languages to learn in 2018 – TechRepublic
- In the Orlando area March 17th? Come see Joe speak at the Orlando Code Camp. Head to https://www.orlandocodecamp.com/ for more information.
- Care to help us out? Visit our sponsors and affiliate resources.
main.c
Presenters and Humble Objects
- Humble Object Pattern – strip all the hard to test portions of an app into separate classes.
- Humble = harder to test.
- Things like the UI.
- View object is the transport object that isn’t tested.
- Presenter object is what takes data from the application (business tiers), and formats it and passes it to the view.
- Application –> Presenter –> ViewModel –> View
- ViewModel will have a mapping of all fields / properties that can be modified in the UI and that data will be filled in by the Presenter.
- Humble = harder to test.
- Testing is made possible by good architecture.
- The separation of behaviors into those that can be tested and those that can’t is (often) a boundary.
Database Gateways
- Contains all the interfaces for the CRUD operations to be implemented.
- The gateways sit between the use cases and the database.
- NO SQL LIVES HERE – these interfaces are to be implemented by the appropriate classes – database implementations, etc.
Data Mappers
- No such things as ORMs.
- Objects are not data structures from the user’s point of view.
- The users can only see the exposed behaviors.
- Objects are not data structures from the user’s point of view.
- A data structure has no implied behavior, which is what an ORM creates.
- ORMs belong in the database layer – the layer that implements the Database Gateway Interfaces.
- ORMs are a type of humble object boundary between the gateway interfaces and the database.
Service Listeners
- Also implements the humble object patterns.
- You’ll basically have data transformation proxy classes set up to take data from the application, format it and pass it over to an external service.
- Same basic principle for incoming data from a service – it’ll be received, transformed, and passed to the application layer.
Partial Boundaries
- Full blown architectural boundaries are expensive!!!
- Must implement polymorphic interfaces both ways.
- Must have sets of input and output classes.
- Dependency management for both sides.
- Expensive to build and work to maintain.
- Sometimes, rather than do the full on implementation, you make a decision to do a Partial Boundary.
- One way to do this is to keep everything in a single component – the inputs, outputs, interfaces, etc.
- What does this buy you? Simpler build pipeline, no version number tracking for interoperability, multiple component releases, etc.
- One way to do this is to keep everything in a single component – the inputs, outputs, interfaces, etc.
- Full on implementation also requires two way reciprocation of the implementation of the boundary interfaces – quite a bit of work.
- A solution is to use the strategy pattern (selecting an algorithm at runtime).
- Weekly Dev Tips episode on Strategy Pattern: http://www.weeklydevtips.com/019
- Client –> Service Boundary Interface –> Service Implementation
- Only problem with this is someone could easily bypass the interface and just use the Service Implementation.
- Another solution is the Facade pattern.
- The facade will call the necessary services when the client makes a call / request.
- This means that the client is still dependent on all the services and any service changes will require recompiles of the client.
- There is no inversion of control in this pattern.
- A solution is to use the strategy pattern (selecting an algorithm at runtime).
Layers and Boundaries
- Remember that boundaries are expensive, but when ignored, they are *very* expensive to add, even with test cases.
- So what’s the architect to do? Guess. Wisely.
- Discover where the boundaries currently are.
- Weigh the costs of the boundaries: which can be ignored, which should be partially vs fully implemented.
- Rinse-n-repeat. It is *not* a one time decision.
- Watch for friction where boundaries don’t exist, then reevaluate.
- The goal is to implement the boundaries when the cost to implement is less than the cost to ignore.
Main Component
- The entry point / overseer of everything else.
- “The Ultimate Detail” – the lowest-level policy.
- Nothing other than the OS depends on it.
- Should create all the factories, strategies, global facilities, etc.
- This is where dependencies should be injected by a DI framework.
- It’s “the dirtiest of all dirty components”. It’s the outermost circle.
- Main does all the dirty work.
- Creates the game engine by passing in the NAME of the class.
- Sets up all the constants.
- Creates the input stream and contains the main loop of the game.
- But it defers all other processing to higher level components.
- Main is basically a plugin, so you can have many versions of it – Dev, Prod, etc.
- You _can_. But _should_ you?
Resources We Like
- Clean Architecture by Robert C. Martin (Amazon)
Tip of the Week
- Use tools, such as WebStorm, to make your life easier.
- Use the show notes in your podcast player to follow along.
- Go to definition using CTRL+Click in VSCode
- Named arguments in C# – Available since C# v4
- Get rid of long parameter lists
- eShopOnContainers