liveBook · Manning

What you will learn in Simple Object-Oriented Design: Create clean, maintainable applications

Create clean, maintainable applications

by Maurício Aniche

Chapter by chapter

Chapter 1: It’s all about managing complexity

1.1 Object-oriented design and the test of time · 1.2 Designing simple object-oriented systems · 1.2.1 Simple code · 1.2.2 Consistent objects · 1.2.3 Proper dependency management · 1.2.4 Good abstractions · 1.2.5 Properly handled external dependencies and infrastructure · 1.2.6 Well modularized · 1.3 Simple design as a day-to-day activity · 1.3.1 Reducing complexity is similar to personal hygiene · 1.3.2 Complexity may be necessary but should not be permanent · 1.3.3 Consistently addressing complexity is cost effective · 1.3.4 High-quality code promotes good practices · 1.3.5 Controlling complexity isn’t as difficult as it seems · 1.3.6 Keeping the design simple is a developer’s responsibility · 1.3.7 Good-enough designs · 1.4 A short dive into the architecture of an information system · 1.5 The example project: PeopleGrow! · 1.6 Exercises · 1.7 Summary

What you learn in chapter 1 →

Chapter 2: Making code small

2.1 Make units of code small · 2.1.1 Break complex methods into private methods · 2.1.2 Move a complex unit of code to another class · 2.1.3 When not to divide code into small units · 2.1.4 Get a helicopter view of the refactoring before you do it · 2.1.5 Example: Importing employees · 2.2 Make code readable and documented · 2.2.1 Keep looking for good names · 2.2.2 Document decisions · 2.2.3 Add code comments · 2.2.4 Example: Deciding when to send an update email · 2.3 Move new complexity away from existing classes · 2.3.1 Give the complex business logic a class of its own · 2.3.2 Break down large business flows · 2.3.3 Example: Waiting list for offerings · 2.4 Exercises · 2.5 Summary

What you learn in chapter 2 →

Chapter 3: Keeping objects consistent

3.1 Ensure consistency at all times · 3.1.1 Make the class responsible for its consistency · 3.1.2 Encapsulate entire actions and complex consistency checks · 3.1.3 Example: The Employee entity · 3.2 Design effective data validation mechanisms · 3.2.1 Make preconditions explicit · 3.2.2 Create validation components · 3.2.3 Use nulls carefully or avoid them if you can · 3.2.4 Example: Adding an employee to a training offering · 3.3 Encapsulate state checks · 3.3.1 Tell, don’t ask · 3.3.2 Example: Available spots in an offering · 3.4 Provide only getters and setters that matter · 3.4.1 Getters that don’t change state and don’t reveal too much to clients · 3.4.2 Setters only to attributes that describe the object · 3.4.3 Example: Getters and setters in the Offering class · 3.5 Model aggregates to ensure invariants in clusters of objects · 3.5.1 Don’t break the rules of an aggregate root · 3.5.2 Example: The Offering aggregate · 3.6 Exercises · 3.7 Summary

What you learn in chapter 3 →

Chapter 4: Managing dependencies

4.1 Separate high-level and low-level code · 4.1.1 Design stable code · 4.1.2 Interface discovery · 4.1.3 When not to separate the higher level from the lower level · 4.1.4 Example: The messaging job · 4.2 Avoid coupling to details or things you don’t need · 4.2.1 Only require or return classes that you own · 4.2.2 Example: Replacing the HTTP bot with the chat SDK · 4.2.3 Don’t give clients more than they need · 4.2.4 Example: The offering list · 4.3 Break down classes that depend on too many other classes · 4.3.1 Example: Breaking down the MessageSender service · 4.4 Inject dependencies, aka dependency injection · 4.4.1 Avoid static methods for operations that change the state · 4.4.2 Always inject collaborators: Everything else is optional · 4.4.3 Strategies to instantiate the class together with its dependencies · 4.4.4 Example: Dependency injection in MessageSender and collaborators · 4.5 Exercises · 4.6 Summary

What you learn in chapter 4 →

Chapter 5: Designing good abstractions

5.1 Design abstractions and extension points · 5.1.1 Identifying the need for an abstraction · 5.1.2 Designing an extension point · 5.1.3 Attributes of good abstractions · 5.1.4 Learn from your abstractions · 5.1.5 Learn about abstractions · 5.1.6 Abstractions and coupling · 5.1.7 Example: Giving badges to employees · 5.2 Generalize important business rules · 5.2.1 Separate the concrete data from the generalized business rule · 5.2.2 Example: Generalizing the badge rules · 5.3 Prefer simple abstractions · 5.3.1 Rules of thumb · 5.3.2 Simple is always better · 5.3.3 Enough is enough · 5.3.4 Don’t be afraid of modeling abstractions from day one · 5.3.5 Example: Revisiting the badge example · 5.4 Exercises · 5.5 Summary

What you learn in chapter 5 →

Chapter 6: Handling external dependencies and infrastructure

6.1 Separate infrastructure from the domain code · 6.1.1 Do you need an interface? · 6.1.2 Hide details from the code, not from the developers · 6.1.3 Changing the infrastructure someday: Myth or reality? · 6.1.4 Example: Database access and the message bot · 6.2 Use the infrastructure fully · 6.2.1 Do your best not to break your design · 6.2.2 Example: Cancelling an enrollment · 6.3 Only depend on things you own · 6.3.1 Don’t fight your frameworks · 6.3.2 Be aware of indirect leakage · 6.3.3 Example: Message bot · 6.4 Encapsulate low-level infrastructure errors into high-level domain errors · 6.4.1 Example: Handling exceptions in SDKBot · 6.5 Exercises · 6.6 Summary

What you learn in chapter 6 →

Chapter 7: Achieving modularization

7.1 Build deep modules · 7.1.1 Find ways to reduce the effects of changes · 7.1.2 Keep refining your domain boundaries · 7.1.3 Keep related things close · 7.1.4 Fight accidental coupling, or document it when you can’t · 7.2 Design clear interfaces · 7.2.1 Keep the module’s interface simple · 7.2.2 Backward-compatible modules · 7.2.3 Provide clean extension points · 7.2.4 Code as if your module will be used by someone with different needs · 7.2.5 Modules should have clear ownership and engagement rules · 7.3 No intimacy between modules · 7.3.1 Make modules and clients responsible for the lack of intimacy · 7.3.2 Don’t depend on internal classes · 7.3.3 Monitor the web of dependencies · 7.3.4 Monoliths or microservices? · 7.3.5 Consider events as a way to decouple modules · 7.3.6 Example: The notification system · 7.4 Exercises · 7.5 Summary

What you learn in chapter 7 →

Chapter 8: Being pragmatic

8.1 Be pragmatic and go only as far as you must · 8.2 Refactor aggressively but in small steps · 8.3 Accept that your code won’t ever be perfect · 8.4 Consider redesigns · 8.5 You owe this to junior developers · 8.6 References · 8.7 Exercises · 8.8 Summary

What you learn in chapter 8 →

Concepts explained in this book

These guides are generated from the text of Manning books by Manning's knowledge graph and link to the sections they draw on. The full books are available on liveBook and at manning.com.