DDD | Domain-Driven Design |
Domain-Driven Design ("DDD") is a software design approach that focuses on the domain of the system rather than technology. There is an emphasis on building a shared mental model and representing that domain model in code in the simplest way possible. Technical details such as database storage, frameworks, etc., are considered to be secondary aspects of the design. The module will focus on DDD and design in general and related topics, such as documentation and some aspects of software architecture. This course uses basic functional programming concepts to express the domain and design: types as documentation, and functions (and composition of functions) for implementation. Object-oriented equivalents and OO design patterns may also be introduced when appropriate.
Frequency
This course will run once a year.
Course dates
20th October 2025 | Oxford University Department of Computer Science - Held in the Department | 10 places remaining. |
Objectives
On completing the class, attendees will:
- Understand the principles of domain-driven design and how it differs from object-oriented design, database-driven design, etc.
- Understand when and why to use DDD instead of other approaches.
- Know how to interview domain experts to understand the key concepts and activities in a domain, with a strong emphasis on communication and developing shared mental models.
- Know how to document these concepts and activities using algebraic types and functions
- Know how to use types to capture as many details of the domain as possible, and how to "make illegal states unrepresentable" and reduce the need for unit tests.
- Know the principles of composition, applied to both functions and types, and how to compose an activity (modelled as a function) from smaller functions.
- Understand how to apply the DDD approach to error handling.
- Understand how to integrate non-pure elements into the design (I/O, databases, etc) and manage state within an application.
- Understand the DDD approach to partitioning a design ("bounded contexts") and how a design might relate to software architecture.
Contents
- Understanding a domain:
- the software development process; requirements, analysis, design; communication and feedback; use-cases, stories, workflows
- Modelling a domain:
- algebraic types and function types; inheritance, interfaces; request/response vs. input/output
- Refining the domain:
- using types to capture constraints; optional and sum types; identity, entities, value objects; refactoring
- Modelling state and time:
- state machines; invariants; commands and events; event sourcing; temporal interactions
- Designing for errors:
- total functions; “honest” function signatures; domain errors; modelling and composing error-generating functions; validation
- Purity, I/O , and testing:
- database-centric vs. domain-centric architectures; stateful vs. stateless designs; determinacy and unit testing; moving IO to the edge; error recovery, transactions, compensation; immutable data, ledgers
- Domain-driven designs and databases:
- persistence to database or document-store; command-query separation; storing state machines in databases; snapshot storage, temporal databases, event sourcing; reporting
- Partitioning and architecting a domain-driven design:
- bounded contexts; context maps, the “reverse Conway manoeuvre”; public domain events vs. internal events; serializing domain objects; deployment (modular monolith, SOA/microservices, serverless)
- Putting it all together:
- review of all techniques; building a complete app, including requirements gathering, design, implementation, error handling, and database storage
Assessment criteria
The assignment is intended to determine, in order of decreasing importance:
- Have you understood the key principles of domain driven design? Can you explain how DDD is different from other software design approaches?
- Have you demonstrated how to represent a domain using algebraic types that can be understood by non-technical domain experts and other stakeholders?
- Do you understand how to avoid primitives and how to represent simple constrained types, optional data, etc? Can you show how to refine a design to eliminate certain kinds of errors and the need for defensive programming?
- Do you understand the DDD approach to state management and databases?
- Do you understand to partition a design and plan an architecture around this?
Requirements
The course will require basic programming skills, such as use of an editor, use of git, etc. No prior knowledge of DDD or functional programming is required - all concepts will be introduced as needed within the course. It is not intended to cover functional programming in any depth; it is independent of but complementary to FPR.
The programming language used in this course is F#, as it supports both object-oriented and functional styles of programming. No prior experience of F# is needed.