The Flexible Edition Part 1
Preventing a big mess, the value of use cases and how to keep objects flexible.
Welcome back to Practical Software Design.
Here’s what we’re covering:
Preventing the Big Ball Of Mud
Use Cases
Interfaces > Behaviour
We all want flexible apps. Let’s see a few ways of how we can make this happen.
Preventing The Big Ball Of Mud
Ever worked on an app that's devolved into a big ball of mud?
Yup. Me too.
How can you start improving it?
Bounded contexts can be a great place to start.
Eric Evans has said that if he had to rewrite the DDD book he'd put bounded contexts at the start, not the end.
What are they?
They split your app up into broad areas
Within one bounded context the language is consistent
Across bounded contexts the same word can mean something different
Example: a customer mean something slightly different between the sales bounded context and operations
Bounded contexts can talk to each other but it should be fairly minimal chat
What are the advantages?
Reduces bloat in God classes
Segregates the app and imposes some order
Allows different parts of the app to evolve alongside a department
Bounded contexts are difficult to do, especially in many frameworks (I'm looking at you Rails) but they're possible.
And they make reasoning about your code way easier.
Use Cases
Start using use cases.
What's a use case?
Why bother?
Great questions.
A use case is an object that wraps an interaction of some kind.
Example - creating an invoice.
You'd have a class called "InvoiceCustomer"
This class is instantiated from a controller.
It would have a single method to kick off the use case.
That method accepts various parameters the class needs to do its job.
It might be the customer ID. The invoice type maybe. The amount.
Then it talks to many different classes to do its job.
It might talk to the Stripe or FreeAgent API.
It might talk to the database.
Then it delivers back a result - success or failure.
The failure contains the errors to render in the view.
The success returns the invoice.
What's the difference between this and a service object?
Well, use cases generally wrap a whole transaction whereas service objects can do... but don't need to.
Advantages
Encourages ubiquitous language
Testable
Describes the actions the app takes
Can wrap complex transactions
Disadvantages
More code
A later of abstraction
I love use cases - I find them excellent abstractions that sit between controllers and the domain.
Focus on the interface
Want to build flexible object oriented apps?
Ignore implementation.
Focus on the interface.
Huh?
Most engineers obsess about implementation details.
Should I use a Map? Or a Set?
Let's use this cool framework shortcut to save 2 lines of code
Let's add a guard clause
I'm not saying this stuff is irrelevant...
...but it's much less important than the interface to your class.
What's the secret to flexible OO code?
Well... a big one is swappability.
Imagine you want to add a new feature.
What's the usual process?
Find the code to hook into (2 hours)
Figure out the tangled web of dependencies (2 hours)
Think about how you're going to change that code (1 hour)
Change 4 methods and 2 classes and add 2 arguments (3 hours)
Fix the 23 tests that break (4 hours)
You've changed so much though...
...what happens if an area with low test coverage breaks in production?
Here's the alternative:
* Find the code to hook into (2 hours)
* Understand 3 interfaces (2 hours)
* Write 2 classes matching the interface with different behaviour using TDD (2 hours)
* Plug into existing code (20 minutes)
Lean back and relax knowing you've hardly changed any code.
Want Some Help?
I have two options:
Book a 1 hour coaching session (normally $200, FREE for a limited time)
Have a great week!