1) The document describes the evolution of an architecture from a "Spaghetti Architecture" to using Event Sourcing and CQRS. It outlines a maturity model with 6 levels: from Spaghetti to Hexagonal to adding Domain Events to using CQRS as a stepping stone to full Event Sourcing and CQRS.
2) As the architecture evolved through each level, it improved separation of concerns, testability, and addressed new issues like complexity and performance. Domain Events were added to help decompose tasks and sync events. CQRS was introduced to improve performance of read models.
3) Fully implementing Event Sourcing would involve entities being reconstituted from stored events rather than loaded from a
A Journey from Hexagonal Architecture to Event Sourcing - SymfonyCon Cluj 2017
1. A Journey from
Hexagonal Architecture
to Event Sourcing
Carlos Buenosvinos (@buenosvinos)
SymfonyCon Cluj 2017, November 16th, 2017
2. Who am I?
Carlos Buenosvinos
• VP of Technology @ XING
• Consultant as a Hobby
• +10 years on Tech Leadership
(CTO, VP of Engineering, Director)
• Teams up to 100 people
• E-Commerce, E-Learning,
Payments, Classifieds, Recruiting
• Atrápalo (500M EUR),
PCComponentes (300M EUR)
9. Spaghetti
Architecture
9
• Multiple Application Entry Points
- create_user.php, delete_user.php, …
• Infrastructure and Domain Together
- PHP and SQL within HTML
• Lack of Testing
• Difficult to Maintain
10. Framework Fanboy
Architecture
10
• Single Application Entry Point
- app.php
• Some structure is present (MVC)
• Still Mixing Infrastructure and Domain
- Long Controllers with SQL and
Business Logic, Dummy Entities
(getters and setters)
• No testing or using Web Framework
• Difficult to upgrade Infrastructure
Components
15. Moving to
Hexagonal Architecture
15
1. Pick an action in the Web Controller
Identify Infrastructure references (ORM,
HTTP Rest Calls, Caching, etc.)
Extract Variable and move them to the top
2. Extract Business Logic into Application
Services (Extract Class/Copy & Paste)
3. Move Infrastructure references away
ORM flush() into add() in Repositories
4. Start Unit Testing from Application
Services
16. New Tech Policies in the Team:
1. Everything New: Hexagonal Architecture
2. Touching an Old Feature: Boy Scout Rule ("Always leave
the campground cleaner than you found it.”)
3. 100% Coverage in the Application Services
16
23. Team starts to
face new issues
23
• # of Dependencies Grows
• Application Service complexity Grows
• More Chances to introduce Bugs
- More developers touching the same
file (Main Task and Subtasks mixed)
• More Subtasks in the same feature,
Worse Performance!!
34. TechPoliciesAdded (ok, it’s a bad joke!)
1. Subtasks of a Feature are developed in a different
Application Service and attached via Listener
2. Fire any new Event that Business may be interested
3. Let’s have a TV screen to monitor realtime Business
metrics to be proactive.
34
46. What strategies to deal with these
inconsistencies can we follow?
46
• Let inconsistencies happen
- The Command Handler will manage
itself (firing ArticleWasAdded, sent to
RabbitMQ, but failed Database Tx)
- Feasible for most operational tasks
(sending email, non-critical tracking,
etc.)
• New Article Added Action and its Event
persisted in the same Tx. Then Worker
to move Events to Rabbit.
• Global TX (Noooooooooo!)
50. Changes from Hexagonal Architecture
to Stepping Stone (CQRS)
50
• Entity state is still fetched from the
database (read)
- 3rd Normal Form
- Now database is a cache
• Entities hold events triggered
- Use a trait or a base class
• Repositories now only persist a bunch
of events to your queue (no updates)
- You will only send messages to
RabbitMQ or your queue
55. What’s remaining to
get to Event Sourcing?
55
• Entities state is not loaded from the
database, is reconstituted from the
Events from the Event Store.
• Migrate Entities one at a time.
• Enjoy!