Your SlideShare is downloading. ×
0
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Ddd cqrs - Forat Latif
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Ddd cqrs - Forat Latif

1,121

Published on

Le slide di Forat Latif presentate a Codemotion Roma 2014

Le slide di Forat Latif presentate a Codemotion Roma 2014

0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,121
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
15
Comments
0
Likes
2
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. ROME 11-12 april 2014ROME 11-12 april 2014 Moving Away From CRUD: Domain Driven Design (DDD) and Command Query Responsibility Segregation (CQRS) Email: forat.latif@gmail.com Twitter: @foratlatif Forat Latif
  • 2. ROME 11-12 april 2014 - Speaker’s name Time to start a greenfield project
  • 3. ROME 11-12 april 2014 - Speaker’s name Process 1) Gather Requirements 2) Model our “Entities” 3) Scaffold our projects and our database based on those entities
  • 4. ROME 11-12 april 2014 - Speaker’s name What the Architecture looks like?
  • 5. ROME 11-12 april 2014 - Speaker’s name Our Domain class Product { String name; String description; Integer price; Integer discount; String category; } class Customer { Address address; String name; } class Order { String description; Customer customer; List<LineItems> lineItems; } class LineItem { Product product; }
  • 6. ROME 11-12 april 2014 - Speaker’s name Just what do we mean by Entity? class Product { String name; String description; Integer price; Integer discount; String category; String getDescription() { return this.description; } void setDescription(String aDescription) { this.description = aDescription; } String getName() { ……. …… }
  • 7. ROME 11-12 april 2014 - Speaker’s name So … Where is the business logic? class ProductService { public void discountProduct(String productId, Integer discount) { Product product = productRepository.find(productId); product.setDiscount(discount); if (discount > 30) { product.setStatus(“Super Discount”); } productRepository.save(aProduct); } }
  • 8. ROME 11-12 april 2014 - Speaker’s name So … Where is the business logic? class ProductController { public void updateProduct(Product product) { productRepository.save(product); } }
  • 9. ROME 11-12 april 2014 - Speaker’s name Are we really doing OOP? Objects are supposed to have a state and behavior that modifies that state State shouldn’t be exposed (getters and setters are not encapsulation) Objects should be loosely coupled Business rules should be placed in one place class Product { String name; String description; String category; String getName() { return this.description; } void setName(String name) { this.name= name; } String getPrice() { ……. …… }
  • 10. ROME 11-12 april 2014 - Speaker’s name Implicit Business Rules class PromoService { void discountProduct (String productId, Integer discount) { Product product = productRepository.find(productId); product.setDiscount(discount); if (discount > 30) { product.setStatus(“Super Discount”); } } } class AnotherService { void discountSomethinElse (String productId) { Product product = productRepository.find(productId); someValue = calculateValue(); product.setDiscount(someValue); } }
  • 11. ROME 11-12 april 2014 - Speaker’s name Objects should expose BEHAVIOR class Product { String name; String status; Integer price; Integer discount; String category; void discount(Integer discount) { this.discount = discount; if (discount > 30) { this.status = “Super Discount”; } } }
  • 12. ROME 11-12 april 2014 - Speaker’s name Back to our “Entities” class Customer { String name; Address address; } class Address { String street; Integer streetNumber; }
  • 13. ROME 11-12 april 2014 - Speaker’s name Entities and Value Objects Entities in DDD are not defined by their attributes, they are defined by a conceptual identity and we care about its changes Value Objects represent a description of something at a certain point in time. Thats why they are immutable and we care only about its attributes
  • 14. ROME 11-12 april 2014 - Speaker’s name What a purchase looks like class OrderService { @Transactional public void purchaseOrder(String orderId) { Order order = orderRepository .find(orderId); order.purchase(); productService.removeFromInventory(order.products()); emailService.sendConfirmationEmail(order); } }
  • 15. ROME 11-12 april 2014 - Speaker’s name Suddenly our mail server goes down …
  • 16. ROME 11-12 april 2014 - Forat Latif Domain Events A Domain Event, represents something that already happened, that is relevant to the business
  • 17. ROME 11-12 april 2014 - Forat Latif Domain Events class Service { void handle(SomeEvent event) { doSomething(); } }
  • 18. ROME 11-12 april 2014 - Forat Latif Domain Events class OrderService { @Transactional public void purchaseOrder(String orderId) { Order order = orderRepository .find(orderId); order.purchase(); productService.removeFromInventory(order.products()); eventBus.push(new OrderPurchased(order.orderId()); } } class EmailSender { public void handle(OrderPurchased orderPurchased) { Order order = orderRepository.find(orderPurchased.orderId); emailService.sendConfirmationEmail(order); } }
  • 19. ROME 11-12 april 2014 - Forat Latif Sales of a Product skyrocket ….
  • 20. ROME 11-12 april 2014 - Forat Latif Eventual Consistency class OrderService { @Transactional public void purchaseOrder(String orderId) { Order order = orderRepository .find(orderId); order.purchase(); eventBus.push(new OrderPurchased(order.orderId()); } } class OrderProcessManager { public void handle(OrderPurchased orderPurchased) { Order order = orderRepository.find(orderPurchased.orderId); productService.removeFromInventory(order.products()); } }
  • 21. ROME 11-12 april 2014 - Forat Latif Aggregate Roots Aggregate is a pattern in Domain-Driven Design. A DDD aggregate is a cluster of domain objects that can be treated as a single unit. An aggregate has a root that acts as an outside interface and keeps all invariants inside the aggregate. Each request should strive to load one aggregate and execute a single operation on it. Hence, Aggregates guarantee transactional consistency inside its boundaries
  • 22. ROME 11-12 april 2014 - Forat Latif What our new Architecture looks like
  • 23. ROME 11-12 april 2014 - Forat Latif Product Inventory and Catalog class Product { String name; Integer price; Integer priceFromSupplier; String supplier; String shippingStatus; String shippingMethod; }
  • 24. ROME 11-12 april 2014 - Forat Latif Bounded Contexts Explicitly define the context within which a model applies. Explicitly set boundaries in terms of team organization, usage within specific parts of the application, and physical manifestations such as code bases and database schemas. Keep the model strictly consistent within these bounds, but don’t be distracted or confused by issues outside. Inventory E-commerce Shipping
  • 25. ROME 11-12 april 2014 - Forat Latif Bounded Contexts class Product { String name; Integer price; } class Item { String shippingStatus; String shippingMethod; } class Product { Integer priceFromSupplier; String supplier; } E-Commerce Context Inventory Context Shipping Context
  • 26. ROME 11-12 april 2014 - Forat Latif Communication between BCs Inventory E-commerce Shipping
  • 27. ROME 11-12 april 2014 - Forat Latif How to identify BCs Ubiquitous Language Goals and Concerns Teams Organizational Structure
  • 28. ROME 11-12 april 2014 - Forat Latif So .. just what is DDD? Domain Driven Design is an approach to software development in which the Domain is the center of attention. - Strategic Design - Tactical Design We should focus on what matters, and thats adding value to our business through software, the software itself is just a byproduct of our strategy
  • 29. ROME 11-12 april 2014 - Forat Latif What about User Interfaces? class ProductController { Product viewProduct (String productId) { Product product = productRepository.find(productId); return product; } }
  • 30. ROME 11-12 april 2014 - Forat Latif User dashboard
  • 31. ROME 11-12 april 2014 - Forat Latif User Dashboard class ProductController { ProductDTO viewProduct (String productId) { //Solution 1: Do a manual query and map it to the DTO //Solution 2: Use your ORM to get all the objects you need // and map them to the DTO return productDTO; } }
  • 32. ROME 11-12 april 2014 - Forat Latif List the products of a category
  • 33. ROME 11-12 april 2014 - Forat Latif Category Tree
  • 34. ROME 11-12 april 2014 - Forat Latif Category Tree Model class Category { String name; Category parent; } class Product{ Category category; }
  • 35. ROME 11-12 april 2014 - Forat Latif “Simple” change request …
  • 36. ROME 11-12 april 2014 - Forat Latif Possible Solutions Nested Query: with CTQ as ( select * from Categories c where c.parentId = 1 union all select * from CTQ p, Categories c where c.parentId = p.categoryId ) select * from CTQ
  • 37. ROME 11-12 april 2014 - Forat Latif Possible Solutions Modify The domain: //Impedance Mismatch Pain class Category { List<Product> products; List<Category> children; } class Product { Category category; }
  • 38. ROME 11-12 april 2014 - Forat Latif Possible Solutions Another possibility: class Category { String parent1Id; String parent2Id; String parent3Id; …. String categoryId; String name; }
  • 39. ROME 11-12 april 2014 - Forat Latif Command Query Separation (CQS) Principle Command–query separation (CQS) is a principle that states that every method should either be a command that performs an action, or a query that returns data to the caller, but not both. In other words, asking a question should not change the answer Commands and Queries have different concerns
  • 40. ROME 11-12 april 2014 - Forat Latif Command Query Responsibility Segregation (CQRS) We can do CQS at the architectural level too ..... class CategoryReadService{ List<Categories> getChildrenCategories(String categoriId); } class CategoryWriteService{ void addCategory (String parendId, String name); }
  • 41. ROME 11-12 april 2014 - Forat Latif Command Query Responsibility Segregation (CQRS) where are do we need to do queries? when returning a DTO, not when performing a write operation when it comes to queries just query the database, why load a behavioral object to show data on a screen? You should modify your domain objects only when you need that change for write operations. If queries become too complex thats another sign that they are two different concerns
  • 42. ROME 11-12 april 2014 - Forat Latif Back to the User Dashboard
  • 43. ROME 11-12 april 2014 - Forat Latif User Dashboard with CQRS class UserDashboardProjector { handle(ProductAdded productAdded) { //insert into “user dashboard entry” with the data in the event } handle(ProductShipped productShipped) { //update “user dashboard entry” with the data in the event } } class ProductQueryProcessor { List<UserDashboardEntryDTO> getProducts(String userId) { //Select from “user dashboard entry” where userId = userId } }
  • 44. ROME 11-12 april 2014 - Forat Latif Category Tree with CQRS
  • 45. ROME 11-12 april 2014 - Forat Latif Category Tree with CQRS Books Technical Accademi c DDD Blue Book Some Weird Book Category Book Book Category
  • 46. ROME 11-12 april 2014 - Forat Latif Category Tree with CQRS class CategoryProjector { handle(CategoryAdded categoryAdded) { Vertex child = createVertex(); child.setProperty(“name”, categoryAdded.name()); Vertex parent = getVertex(categoryAdded.parentId()); parent.addEdge(child); } } class ProductQueryProcessor { List<ProductDTO> getProducts(String categoryId) { // graph query to get all children of type x; } }
  • 47. ROME 11-12 april 2014 - Forat Latif Multiple categories
  • 48. ROME 11-12 april 2014 - Forat Latif Multiple categories Without CQRS: Nested Query : …. Modify the domain (even more Impedance mismatch pain) Mixed: (join table unavoidable)
  • 49. ROME 11-12 april 2014 - Forat Latif Multiple categories With CQRS: class Product { List<Categories> categories; } and … thats it! The read model doesnt need to be modified
  • 50. ROME 11-12 april 2014 - Forat Latif Notice a pattern? Read model is data driven Write model is Domain Driven (database not important) To design your write model you can imagine that you dont need a database (you have infinite persisant RAM)
  • 51. ROME 11-12 april 2014 - Forat Latif Aggregates as Documents - consistency easier to maintain, - performance - scalability - technical simplicity (no lazy load config nor impedence mismatch) class Product { String productId; @EmbedSomehow // hopefully with a doc database List<String> categoryIds; }
  • 52. ROME 11-12 april 2014 - Forat Latif Commands class OrderService { @Transactional public void purchaseOrder(String orderId) { …… } } class PurchaseOrderCommandHandler { @Transactional public void handle(PurchaseOrderCommand command) { …… } }
  • 53. ROME 11-12 april 2014 - Forat Latif Advantages of Commands Command log (not your regular log) Clear user intention Improved Testability Integration Get rid of AOP Command Sourcing
  • 54. ROME 11-12 april 2014 - Forat Latif Advantages of Commands Represent an intention, which usually maps to a command method in your aggregate, which causes one or many events to be pushed. class ChangeCustomerTelephoneCommandHandler { @Transactional public void handle(ChangeCustomerTelephoneCommand command) { …… } }
  • 55. ROME 11-12 april 2014 - Forat Latif Overview of CQRS
  • 56. ROME 11-12 april 2014 - Forat Latif Recap of CQRS CQS is a principle that can be applied at the architecturale level. Read and Write are two separate concerns You cannot solve all problems with the same model, especially if the problem domains have different points of view
  • 57. ROME 11-12 april 2014ROME 11-12 april 2014 Moving Away From CRUD: Domain Driven Design (DDD) and Command Query Responsibility Segregation (CQRS) Forat Latif Email: forat.latif@gmail.com Twitter: @foratlatif Questions?

×