Log In
Or create an account ->
Imperial Library
Home
About
News
Upload
Forum
Help
Login/SignUp
Index
Contents
Introduction
1 Preface
2 Why is decoupling from infrastructure so important?
3 Who is this book for?
4 Overview of the contents
5 The accompanying demo project
6 About the author
7 Acknowledgements
8 Changelog
8.1 April 15th, 2020 (initial version)
8.2 April 23rd, 2020
8.3 May 1st, 2020
8.4 May 6th, 2020
8.5 May 29th, 2020
8.6 June 4th, 2020
8.7 June 12th, 2020
8.8 June 17th, 2020
8.9 June 22nd, 2020
8.10 June 26th, 2020
8.11 July 1st, 2020
8.12 July 6th, 2020
8.13 July 8th, 2020
1 Introduction
1.1 Rule no 1: No dependencies on external systems
1.2 Abstraction
1.3 Rule no 2: No special context needed
1.4 Summary
2 The domain model
2.1 SQL statements all over the place
2.2 Trying to fix it with a table data gateway
2.3 Designing an entity
2.4 Introducing a repository
2.5 Mapping entity data to table columns
2.5.1 Using an ORM
2.5.2 Manual mapping
2.6 Generating the identifier earlier
2.6.1 Using UUIDs instead of (auto-)incrementing integer IDs
2.7 Using a value object for the identifier
2.8 Active Record versus Data Mapper
2.9 Summary
3 Read models and view models
3.1 Reusing the write model
3.2 Creating a separate read model
3.3 Read model repository implementations
3.3.1 Sharing the underlying data source
3.3.2 Using write model domain events
3.4 Using value objects with internal read models
3.5 A specific type of read model: the view model
3.6 Using view models for APIs
3.7 Summary
4 Application services
4.1 Considering other infrastructures
4.2 Designing a use case to be reusable
4.3 Extracting an application service
4.4 Introducing a parameter object
4.5 Dealing with multiple steps
4.6 Summary
5 Service locators
5.1 From service location to explicit dependencies
5.2 Depending on global state
5.3 Injecting dependencies
5.4 Injecting configuration values
5.5 Using method arguments for job-specific data
5.6 Clients of reusable services
5.7 Testing
5.8 Effective testing
5.9 The Composition root is near the entry point
5.10 Summary
6 External services
6.1 Connecting to the external service
6.2 Introducing an abstraction
6.3 Architectural advantages
6.4 Testing
6.5 Summary
7 Time and randomness
7.1 Passing current time and random data as method arguments
7.2 Introducing factories
7.3 Introducing value objects
7.4 Improving the factories
7.5 Manipulating the current time
7.6 Integration tests again
7.7 Summary
8 Validation
8.1 Protecting entity state
8.2 Using value objects to validate separate values
8.3 Form validation
8.4 Using exceptions to talk to users
8.5 When validation is not the answer
8.6 Creating and validating command objects
8.7 Summary
9 Conclusion
9.1 Core code and infrastructure code
9.2 A summary of the strategy
9.2.1 Use dependency injection and inversion everywhere
9.2.2 Make use cases universally invokable
9.3 Focus on the domain
9.4 Focus on testability
9.5 Pure object-oriented code
9.6 Summary
10 Introduction
11 Key design patterns
11.1 Framework-inspired structural elements
11.2 Entities
11.2.1 Protect invariants
11.2.2 Constrain updates
11.2.3 Model state changes as actions with state transitions
11.2.4 Don’t think too much about tables
11.2.5 Record domain events
11.3 Repositories
11.4 Application services
11.4.1 Return the identifier of a new entity
11.4.2 Input should be defined as primitive-type data
11.4.3 Wrap input inside command objects
11.4.4 Translate primitive input to domain objects
11.4.5 Add contextual information as extra arguments
11.4.6 Save only one entity per application service call
11.4.7 Move secondary tasks to a domain event subscriber
11.5 Event subscribers
11.5.1 Move subscribers to the module where they produce their effect
11.5.2 Delegate to an application service
11.6 Read models
11.6.1 Use internal read models when you need information
11.6.2 Choose a standard implementation for the repository
11.6.3 For view models, prepare the data for rendering
11.7 Process modelling
11.8 Summary
12 Architectural layers
12.1 MVC
12.2 A standard set of layers
12.2.1 The infrastructure layer
12.2.2 The application layer
12.2.3 The domain layer
12.2.4 Up and down the layer stack
12.3 The Dependency rule
12.4 Making layers tangible
12.4.1 Documenting the architecture
12.4.2 Using namespaces for layering
12.4.3 Automated verification of design decisions
12.5 Summary
13 Ports and adapters
13.1 Hexagonal architecture
13.2 Ports
13.3 Adapters for outgoing ports
13.4 Adapters for incoming ports
13.5 The application as an interface
13.6 Combining ports and adapters with layers
13.7 Structuring the Infrastructure layer
13.8 Summary
14 A testing strategy for decoupled applications
14.1 Unit tests
14.2 Adapter tests
14.3 Contract tests for outgoing port adapters
14.4 Driving tests for incoming port adapters
14.5 Use case tests
14.6 End-to-end tests
14.7 Development workflow
14.8 Summary
15 Conclusion
15.1 Is a decoupled architecture the right choice for all projects?
15.2 My application is not supposed to live longer than two years
15.3 My application offers only CRUD functionality
15.4 My application is a legacy application
15.5 I can never make my entire application decoupled
15.6 Isn’t this over-engineering?
Notes
← Prev
Back
Next →
← Prev
Back
Next →