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

Building JavaScript applications based on DDD, CQRS and EventSourcing

Dec 01, 2014

Download

Software

Johannes Becker

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.
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
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