![Page 1: Building JavaScript applications based on DDD, CQRS and EventSourcing](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/1.jpg)
Building JavaScript applicationsbased on DDD, CQRS and EventSourcing
MunichJS, 04. Sept 2014
![Page 2: Building JavaScript applications based on DDD, CQRS and EventSourcing](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/2.jpg)
DomainDomain Model Model
![Page 3: Building JavaScript applications based on DDD, CQRS and EventSourcing](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/3.jpg)
ORMORM
CRUDCRUD
Updates Manipulates
Sees Uses
![Page 4: Building JavaScript applications based on DDD, CQRS and EventSourcing](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/4.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/5.jpg)
var studentSchema = new MongooseSchema({ name: String});
var courseSchema = new MongooseSchema({ name: String});
![Page 6: Building JavaScript applications based on DDD, CQRS and EventSourcing](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/6.jpg)
Relationships with ORM
Students should be able to join Courses
![Page 7: Building JavaScript applications based on DDD, CQRS and EventSourcing](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/7.jpg)
var courseSchema = new MongooseSchema({ name: String, students: [ studentSchema ]});
![Page 8: Building JavaScript applications based on DDD, CQRS and EventSourcing](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/8.jpg)
![Page 9: Building JavaScript applications based on DDD, CQRS and EventSourcing](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/9.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/10.jpg)
Where did theWhere did theBusiness-Logic go?Business-Logic go?
![Page 11: Building JavaScript applications based on DDD, CQRS and EventSourcing](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/11.jpg)
Business -
![Page 12: Building JavaScript applications based on DDD, CQRS and EventSourcing](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/12.jpg)
Reporting
Which Students first joined a Course but left it again?
![Page 13: Building JavaScript applications based on DDD, CQRS and EventSourcing](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/13.jpg)
var courseSchema = new MongooseSchema({ name: String, students: [ studentSchema ], studentsLeftIds: Array});
![Page 14: Building JavaScript applications based on DDD, CQRS and EventSourcing](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/14.jpg)
// U(pdate) Routecourse.update = function(courseId, updatedCourse) { currentCourse = course.findById(courseId);
![Page 15: Building JavaScript applications based on DDD, CQRS and EventSourcing](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/15.jpg)
// 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](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/16.jpg)
// 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](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/17.jpg)
![Page 18: Building JavaScript applications based on DDD, CQRS and EventSourcing](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/18.jpg)
Another approachAnother approach
![Page 19: Building JavaScript applications based on DDD, CQRS and EventSourcing](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/19.jpg)
BoundedContext
Encapsulates your DomainModel(s)
![Page 20: Building JavaScript applications based on DDD, CQRS and EventSourcing](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/20.jpg)
var school = eventric.context('school');
![Page 21: Building JavaScript applications based on DDD, CQRS and EventSourcing](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/21.jpg)
Ubiquitous Language
Behaviors in your Domain
![Page 22: Building JavaScript applications based on DDD, CQRS and EventSourcing](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/22.jpg)
EventStormingEventStorming
![Page 23: Building JavaScript applications based on DDD, CQRS and EventSourcing](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/23.jpg)
DomainEventsDomainEvents
![Page 24: Building JavaScript applications based on DDD, CQRS and EventSourcing](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/24.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/25.jpg)
Aggregate
![Page 26: Building JavaScript applications based on DDD, CQRS and EventSourcing](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/26.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/27.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/28.jpg)
![Page 29: Building JavaScript applications based on DDD, CQRS and EventSourcing](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/29.jpg)
CommandHandler
![Page 30: Building JavaScript applications based on DDD, CQRS and EventSourcing](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/30.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/31.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/32.jpg)
Reporting using Projections
![Page 33: Building JavaScript applications based on DDD, CQRS and EventSourcing](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/33.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/34.jpg)
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](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/35.jpg)
CQRS + EventSourcingCQRS + EventSourcing
![Page 36: Building JavaScript applications based on DDD, CQRS and EventSourcing](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/36.jpg)
to the Livecoding..to the Livecoding..
![Page 37: Building JavaScript applications based on DDD, CQRS and EventSourcing](https://reader034.vdocuments.net/reader034/viewer/2022052410/547d9961b479597f508b4942/html5/thumbnails/37.jpg)
Johannes Becker@dieserjohannes
eventricjs.orgeventricjs.org
github.com/efacilitation/eventricgithub.com/efacilitation/eventricgithub.com/efacilitation/eventric-todoMVCgithub.com/efacilitation/eventric-todoMVC