6. Ubiquitous Language
A Language structured around the Domain Model
and used by all team mebers.
7. Bounded Context
An explicit Boundary within which a Domain
Model exists.
Inside the boundary all terms have specific meaning.
They are part of the context‘s Ubiquitous Language.
12. Core Domain
The distinctive part of the Model, central to the user‘s
goals, that differentiates the application and makes it
valuable.
The most important Subdomain.
15. we don‘t use DDD when
there‘s no value in formalizing
the problem
16. we only use DDD in parts where
we get a competitive advantage
17. Aggregate
A cluster of associated objects that are treated as a
unit for the purpose of data changes.
A set of consistency rules applies within the
Aggregate‘s boundaries.
18. Exercise # 1: A simple Model
We have Students, Courses, and Teachers
A Student can take multiple Courses
A Course can have multiple Students
A Course is hosted by a Teacher
A Teacher can host multiple Courses
19. public class Teacher
{
public List<Course> Courses { get; private set; }
}
public class Course
{
public Teacher Teacher { get; private set; }
public List<Student> Students { get; private set; }
}
public class Student
{
public List<Course> Courses { get; private set; }
}
20. Exercise # 2: Assign Teacher
A Course ist hosted by a Teacher
Constraint: A Teacher has a maximum number of
students
21. public class Teacher
{
public List<Course> Courses { get; private set; }
public int MaximumNumberOfStudents { get; private set; }
public void Assign(Course course) {
if (course.Students.Count >= MaximumNumberOfStudents)
throw ...
this.Courses.Add(course);
course.AssignTo(this);
}
}
public class Course
{
public Teacher Teacher { get; private set; }
public void AssignTo(Teacher teacher) {
this.Teachers.Add(teacher);
}
}
22. public class Teacher
{
public List<Course> Courses { get; private set; }
public int MaximumNumberOfStudents { get; private set; }
public void Assign(Course course) {
if (course.Students.Count >= MaximumNumberOfStudents)
throw ...
this.Courses.Add(course);
course.AssignTo(this);
}
}
public class Course
{
public Teacher Teacher { get; private set; }
public void AssignTo(Teacher teacher) {
this.Teachers.Add(teacher);
}
}
23. Pattern # 1: Responsibility
We don‘t know where to put things.
Responsibilities must be clear.
Have one way of doing something, not many.
24. public class Teacher
{
public List<Course> Courses { get; private set; }
public int MaximumNumberOfStudents { get; private set; }
public void Assign(Course course) {
if (course.Students.Count >= MaximumNumberOfStudents)
throw ...
this.Courses.Add(course);
// course.AssignTo(this);
course.Teacher = this;
}
}
public class Course
{
public Teacher Teacher { get; private set; }
/* public void AssignTo(Teacher teacher) {
this.Teachers.Add(teacher);
} */
}
25. public class Teacher
{
public List<Course> Courses { get; private set; }
public int MaximumNumberOfStudents { get; private set; }
public void Assign(Course course) {
if (course.Students.Count >= MaximumNumberOfStudents)
throw ...
this.Courses.Add(course);
// course.AssignTo(this);
course.Teacher = this;
}
}
public class Course
{
public Teacher Teacher { get; private set; }
/* public void AssignTo(Teacher teacher) {
this.Teachers.Add(teacher);
} */
}
26. Pattern # 2: Don‘t be stupid
No rules on Teacher.Courses or Course.Teacher.
We don‘t need the relationship.
31. Exercise # 3: Enroll Student
A Student can enroll in a Course
Constraint: A Student can only enroll in up to five
Courses
Constraint: A Student‘s Courses may not overlap
32. public class Course
{
public int MaximumNumberOfStudents { get; private set; }
public void Students { get; private set; }
private void TryEnroll(Student student) {
if (Students.Count() >= MaximumNumberOfStudents) throw ...
}
public void Enroll(Student student) {
this.TryEnroll(student);
student.TryEnroll(this);
this.Students.Add(student);
student.EnrollIn(this);
}
}
public class Student
{
public List<Course> Courses { get; private set; }
public void TryEnrollIn(Course course) {
foreach (var c in Courses) {
if (c.OverlapsWith(course)) throw ...
}
}
public void EnrollIn(Course course) {
this.Courses.Add(course);
}
}
33. public class Course
{
public int MaximumNumberOfStudents { get; private set; }
public void Students { get; private set; }
private void TryEnroll(Student student) {
if (Students.Count() >= MaximumNumberOfStudents) throw ...
}
public void Enroll(Student student) {
this.TryEnroll(student);
student.TryEnroll(this);
this.Students.Add(student);
student.EnrollIn(this);
}
}
public class Student
{
public List<Course> Courses { get; private set; }
public void TryEnrollIn(Course course) {
foreach (var c in Courses) {
if (c.OverlapsWith(course)) throw ...
}
}
public void EnrollIn(Course course) {
this.Courses.Add(course);
}
}
34. Pattern # 3: Capture Concepts
We‘re missing an explicit concept:
A Student has a Schedule
The Schedule consists of Enrollments
Constraint: Enrollments may not overlap
Constraint: A Schedule may contain up to 5
Enrollments
35. public class Course
{
public int MaximumNumberOfStudents { get; private set; }
public void Students { get; private set; }
private void TryEnroll(Student student) {
if (Students.Count() >= MaximumNumberOfStudents) throw ...
}
internal void Enroll(Student student) {
// this.TryEnroll(student);
// student.TryEnroll(this);
this.Students.Add(student);
// student.EnrollIn(this);
}
}
public class Student
{
public List<Course> Courses { get; private set; }
public Schedule Schedule { get; private set; }
public void EnrollIn(Course course) {
var enrollment = course.CreateEnrollment(course);
Schedule.TryAddEnrollment(enrollment);
course.TryEnroll(this);
Schedule.AddEnrollment(enrollment);
course.Enroll(this);
}
}
36. public class Course
{
public int MaximumNumberOfStudents { get; private set; }
// public void Students { get; private set; }
public int NumberOfStudents { get; private set; }
private void TryEnroll(Student student) {
// if (Students.Count() >= MaximumNumberOfStudents) throw ...
if (NumberOfStudents >= MaximumNumberOfStudents) throw ...
}
internal void Enroll(Student student) {
this.NumberOfStudents++;
}
}
public class Student
{
public List<Course> Courses { get; private set; }
public Schedule Schedule { get; private set; }
public void EnrollIn(Course course) {
var enrollment = course.CreateEnrollment(course);
Schedule.TryAddEnrollment(enrollment);
course.TryEnroll(this);
Schedule.AddEnrollment(enrollment);
course.Enroll(this);
}
}
37. Aggregate
A cluster of associated objects that are treated as a
unit for the purpose of data changes.
A set of consistency rules applies within the
Aggregate‘s boundaries.
38. In other words:
A Transaction should only affect one Aggregate.
39. What if ...
... they don‘t need to be done in one Transaction?
... we TryEnroll() but not Enroll()?
41. Domain Events
A Domain Event is a full-fledged part of the Domain
Model, a representation of something that happened
in the Domain.
Something happened that Domain Experts care
about, e.g. a Student enrolled in a Course.
42. public class Course
{
public int MaximumNumberOfStudents { get; private set; }
public int NumberOfStudents { get; private set; }
private void TryEnroll(Student student) {
if (NumberOfStudents >= MaximumNumberOfStudents) throw ...
}
/* public void Enroll(Student student) {
this.NumberOfStudents++;
} */
public void Handle(StudentEnrolledInCourse event) {
this.NumberOfStudents++;
}
}
public class Student
{
public List<Course> Courses { get; private set; }
public Schedule Schedule { get; private set; }
public void EnrollIn(Course course) {
var enrollment = course.CreateEnrollment(course);
Schedule.TryAddEnrollment(enrollment);
course.TryEnroll(this);
Schedule.AddEnrollment(enrollment);
// course.Enroll(this);
Bus.Publish(new StudentEnrolledInCourse( ... ));
}
}
43. But, once again, what if ...
... the Student drops out of a Course?
45. 1. don‘t be stupid
2. denormalize
3. break up consistencies
46. References & Further Reading:
Inspiration for the exercises: The works of Greg Young
Domain-Driven Design – Tackling Complexity in the Heart of Software,
by Eric Evans, Addison-Wesley, 2004
Implementing Domain-Driven Design by Vaughn Vernon, Addison-Wesley, 2012
http://domaindrivendesign.org - DDD-Forum maintained by Eric Evans, et al.
Effective Aggregate Design: bit.ly/ncCOTH
Google Group: groups.google.com/forum/?fromgroups#!forum/dddcqrs