Building JavaScript applications based on DDD, CQRS and EventSourcing

37
Building JavaScript applications based on DDD, CQRS and EventSourcing MunichJS, 04. Sept 2014

description

Video: http://www.youtube.com/watch?v=XSc7NPedAxw&feature=youtu.be Model-View-Controller (MVC) was born in the 1970s and is still one of the most used architectural patterns in the software world. On top of that it's common to connect Data-Models using Object-relational Mapping (ORM) to a Database and provide easy Create-Read-Update-Delete (CRUD) Routes as an API for applications. In this talk I will show an alternative approach and how to easily apply it using JavaScript. Live coding included. In the process the audience will learn about Domain-driven Design (DDD), Command Query Responsibility Seggregation (CQRS), EventSourcing and how to explicitly capture your domain events - something the ThoughtWorks TechnologyRadar2014 also outlined as an emerging technique, because it makes developers and business people happy.

Transcript of Building JavaScript applications based on DDD, CQRS and EventSourcing

Page 1: Building JavaScript applications based on DDD, CQRS and EventSourcing

Building JavaScript applicationsbased on DDD, CQRS and EventSourcing

MunichJS, 04. Sept 2014

Page 2: Building JavaScript applications based on DDD, CQRS and EventSourcing

DomainDomain Model Model

Page 3: Building JavaScript applications based on DDD, CQRS and EventSourcing

ORMORM

CRUDCRUD

Updates Manipulates

Sees Uses

Page 4: Building JavaScript applications based on DDD, CQRS and EventSourcing

Our Domain

We are a SchoolSchoolWe have StudentsStudents and CoursesCourses

Students should be able to- join a Course- leave a Course

Page 5: Building JavaScript applications based on DDD, CQRS and EventSourcing

var studentSchema = new MongooseSchema({ name: String});

var courseSchema = new MongooseSchema({ name: String});

Page 6: Building JavaScript applications based on DDD, CQRS and EventSourcing

Relationships with ORM

Students should be able to join Courses

Page 7: Building JavaScript applications based on DDD, CQRS and EventSourcing

var courseSchema = new MongooseSchema({ name: String, students: [ studentSchema ]});

Page 8: Building JavaScript applications based on DDD, CQRS and EventSourcing
Page 9: Building JavaScript applications based on DDD, CQRS and EventSourcing

app = express()

// C(reate)app.post('/course/create', course.create);

// R(ead)app.get('/course', course.read);app.get('/course/:id', course.read);

// U(pdate)app.post('/course/update/:id', course.update);

// D(elete)app.get('/course/delete/:id', course.delete);

Page 10: Building JavaScript applications based on DDD, CQRS and EventSourcing

Where did theWhere did theBusiness-Logic go?Business-Logic go?

Page 11: Building JavaScript applications based on DDD, CQRS and EventSourcing

Business -

Page 12: Building JavaScript applications based on DDD, CQRS and EventSourcing

Reporting

Which Students first joined a Course but left it again?

Page 13: Building JavaScript applications based on DDD, CQRS and EventSourcing

var courseSchema = new MongooseSchema({ name: String, students: [ studentSchema ], studentsLeftIds: Array});

Page 14: Building JavaScript applications based on DDD, CQRS and EventSourcing

// U(pdate) Routecourse.update = function(courseId, updatedCourse) { currentCourse = course.findById(courseId);

Page 15: Building JavaScript applications based on DDD, CQRS and EventSourcing

// U(pdate) Routecourse.update = function(courseId, updatedCourse) { currentCourse = course.findById(courseId);

// add students to "studentsLeft" that left the course currentCourse.studentsLeftIds = calculateStudentsLeftTheCourse(currentCourse,updatedCourse);

// save currentCourse.save()};

Page 16: Building JavaScript applications based on DDD, CQRS and EventSourcing

// U(pdate) Routecourse.update = function(courseId, updatedCourse) { currentCourse = course.findById(courseId);

// remove students from "studentsLeft" that enrolled again currentCourse.studentsLeftIds = calculateStudentsJoinedTheCourseAgain(currentCourse, upatedCourse);

// add students to "studentsLeft" that left the course currentCourse.studentsLeftIds = calculateStudentsLeftTheCourse(currentCourse, updatedCourse);

// save currentCourse.save()};

Page 17: Building JavaScript applications based on DDD, CQRS and EventSourcing
Page 18: Building JavaScript applications based on DDD, CQRS and EventSourcing

Another approachAnother approach

Page 19: Building JavaScript applications based on DDD, CQRS and EventSourcing

BoundedContext

Encapsulates your DomainModel(s)

Page 20: Building JavaScript applications based on DDD, CQRS and EventSourcing

var school = eventric.context('school');

Page 21: Building JavaScript applications based on DDD, CQRS and EventSourcing

Ubiquitous Language

Behaviors in your Domain

Page 22: Building JavaScript applications based on DDD, CQRS and EventSourcing

EventStormingEventStorming

Page 23: Building JavaScript applications based on DDD, CQRS and EventSourcing

DomainEventsDomainEvents

Page 24: Building JavaScript applications based on DDD, CQRS and EventSourcing

school.defineDomainEvents({ StudentJoinedCourse: function(params) { this.courseId = params.courseId; }, StudentLeftCourse: function(params) { this.courseId = params.courseId; }});

Page 25: Building JavaScript applications based on DDD, CQRS and EventSourcing

Aggregate

Page 26: Building JavaScript applications based on DDD, CQRS and EventSourcing

school.addAggregate('Student', function() { this.joinInCourse = function(courseId) { this.$emitDomainEvent('StudentJoinedCourse', { courseId: params.courseId }); }

Page 27: Building JavaScript applications based on DDD, CQRS and EventSourcing

school.addAggregate('Student', function() { this.joinInCourse = function(courseId) { this.$emitDomainEvent('StudentJoinedCourse', { courseId: params.courseId }); } this.leaveCourse = function(courseId) { this.$emitDomainEvent('StudentLeftCourse', { courseId: params.courseId }); }});

Page 28: Building JavaScript applications based on DDD, CQRS and EventSourcing
Page 29: Building JavaScript applications based on DDD, CQRS and EventSourcing

CommandHandler

Page 30: Building JavaScript applications based on DDD, CQRS and EventSourcing

school.addCommandHandlers({

StudentJoinCourse: function(params, done) { studentRepository = this.$repository('Student'); studentRepository.findById(params.studentId) .then(function(student) {

student.joinCourse(params.courseId);student.joinCourse(params.courseId);

studentRepository.save(params.studentId); }) .then(function() { done(); }) }

Page 31: Building JavaScript applications based on DDD, CQRS and EventSourcing

StudentLeaveCourse: function(params, done) { studentRepository = this.$repository('Student'); studentRepository.findById(params.studentId) .then(function(student) {

student.leaveCourse(params.courseId);student.leaveCourse(params.courseId);

studentRepository.save(params.studentId); }) .then(function() { done(); }) }

});

Page 32: Building JavaScript applications based on DDD, CQRS and EventSourcing

Reporting using Projections

Page 33: Building JavaScript applications based on DDD, CQRS and EventSourcing

school.addProjection(function() { this.studentsLeft = {}

this.handleStudentLeftCourse = function(domainEvent) { // make sure the object has the correct format this.studentsLeft[domainEvent.aggregate.id] .course[domainEvent.payload.courseId] = true; } });

Page 34: Building JavaScript applications based on DDD, CQRS and EventSourcing

school.addProjection(function() { this.studentsLeft = {}

this.handleStudentJoinedCourse = function(domainEvent) { // make sure the object has the correct format delete this.studentsLeft[domainEvent.aggregate.id] .course[domainEvent.payload.courseId] }

this.handleStudentLeftCourse = function(domainEvent) { // make sure the object has the correct format this.studentsLeft[domainEvent.aggregate.id] .course[domainEvent.payload.courseId] = true; } });

Page 35: Building JavaScript applications based on DDD, CQRS and EventSourcing

CQRS + EventSourcingCQRS + EventSourcing

Page 36: Building JavaScript applications based on DDD, CQRS and EventSourcing

to the Livecoding..to the Livecoding..

Page 37: Building JavaScript applications based on DDD, CQRS and EventSourcing

Johannes Becker@dieserjohannes

eventricjs.orgeventricjs.org

github.com/efacilitation/eventricgithub.com/efacilitation/eventricgithub.com/efacilitation/eventric-todoMVCgithub.com/efacilitation/eventric-todoMVC