Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
MODULARITY AND DOMAIN
DRIVEN DESIGN
a killer combination?
Tom De Wolf
Architect
tom.dewolf@aca-it.be
@tomdw
Stijn Van den ...
initial development maintenance phase
Software Design Customer Satisfaction
Separation of Concerns
Low coupling High Cohes...
Vehicle
Option
Make
Warranty
Model
Transport
Location
Domain Driven Design
Without modularity
BusinessPartner
Address
Cont...
Vehicle
Option
Make
Warranty
Owner
Model
Transported Item
Transport
Transport Supplier
Transport Consumer
Vehicle Context ...
transport
vehicle
MODULAR DATABASE SCHEMA
• cross domain database structures not allowed
• queries cannot cross domain bou...
BENEFITS …
• Domain modules can migrate independently
to next version!
• Database schema is internal to the domain
bundle,...
Mmodular database migration
cross domain transactions
Tx
Scross domain search and reporting
C
H
A
L
L
E
N
G
E
S
Mmodular database migration
M
Dev Machine 1
MIGRATION CHALLENGE
Dev Machine 2
Continuous
Integration
Test
environment
Acceptance
environment
Productio...
M
LIQUIBASE
DATABASECHANGELOG table to track executed changesets for each environment
In versioned source code
XML based D...
M
MODULAR LIQUIBASE
transportvehicle business partner
deployment 1
deployment 2
deployment 3
Migrate modules separately Mi...
M
THE EXTENDER PATTERN
bundle A
bundle B
bundle C
bundle D
extender bundle
Extension Pattern ?!
no match
/OSGI-INF/liquiba...
Tcross domain transactionsx
JTA OR NOT?
• No persistence layer — direct jdbc/sql access — 1 datasource



• Multiple datasources
• Different types of ...
MODULAR PERSISTENCE
T osgi-datasource
XA enabled
vehicle-domaintransport-domain
javax.transaction.TransactionManager
trans...
Scross domain search
Scross domain search
SEARCH
the tale of the evil joins
NO
cross
module
search
A. Search encapsulated in a separate module leveraging
the functionality of other domain modules
search-
module
domainA
do...
domainA
B. Search is using a separate query model
search-
module
domainB
SearchAPI
EventProvider
Update	

Events
Update
$ curl -XPUT ‘localhost:9200/vehicle/external/1’ -d ‘{	
	“make”: “BMW”,	
	 “VIN”: “30203232012102”	
}’
index document_type...
$ curl -XPOST ‘localhost:9200/vehicle/external/1/
_update’ -d ‘{	
	“doc”: {“make”: “Alpina”}	
}’
Update a document
index d...
$ curl -XPOST localhost:9200/vehicle/_search?pretty -d
‘{"query":{"match":{"make":"BMW"}}}'	
index
Querying an index
$ curl -XPOST localhost:9200/vehicle/_search?pretty -d
‘{"query":{"match":{"mark":"BMW"}}}'	
{	
"took" : 3,	
"timed_out" :...
• Distributed (shards/replicas)	

• Advanced Quering (lucene/geo/
aggregation)	

• Facets (terms/ranges/histogram)	

• API...
1Populate the index
1Populate the index
package be.vabfs.search.api;	
!
public interface SearchIndexService {	
	 	
	 void update(Object entity...
1Populate the index
search
SearchIndexService
update(entity)
Synchronise onTransaction
Track updated entities
A
Map entiti...
1Populate the index
Map entities to searchData
B
package be.vabfs.search.api.data;	
!
import java.util.List;	
!
public int...
1Populate the index
Map entities to searchData
B
SearchDataProvider
domainB
Entity
SearchData
1Populate the index
A
search
SearchIndexService
update(entity)
Synchronise onTransaction
Track updated entities
Bulk updat...
2Enhancing Search
2Enhancing Search
2Enhancing Search
search
SearchService
package be.vabfs.search.api;	
!
import …	
!
public interface SearchService {	
	
…	
...
2Enhancing Search
package be.vabfs.search.api.criteria;	
!
import java.util.List;	
!
public interface SearchCriteriaProvid...
2Enhancing Search
search
SearchService
domainB
SearchCriteriaProvider
domainB
LESSONS LEARNED
@deployment time migration = RISK
• have CI build continuously migrate current production
data
Refactor wr...
WHAT IS NEXT?
Multiple module versions active? Multiple schema versions
active?
• e.g. feature try-out to limited customer...
M
Modular migration
Liquibase extender @ DeployT
Cross domain transactions
Distributed JTA transactionsx S
Cross domain se...
Tom De Wolf
Architect
tom.dewolf@aca-it.be
@tomdw
Stijn Van den Enden
CTO
stijn.vandenenden@aca-it.be
@stieno
www.aca-it.be
Modularity and Domain Driven Design - A killer combination - T De Wolf & S van Den Ende
Upcoming SlideShare
Loading in …5
×

Modularity and Domain Driven Design - A killer combination - T De Wolf & S van Den Ende

2,538 views

Published on

Applying domain driven design in a modular fashion has implications on how your data is structured and retrieved. A modular domain consists out of multiple loosely coupled sub-domains, each having their own modular schema in the database. How can we migrate and evolve the database schema’s separately with each new sub-domain version? And how do we match this with reporting and cross-domain use cases, where aggregation of data from multiple sub-domains is essential?

A case study concerning an OSGi-based business platform for automotive services has driven us to solve these challenges without sacrificing the hard-worked-on modularity and loose coupling.

In this presentation you will learn how we used Modular Domain Driven Design with OSGi. 'Liquibase' is elevated to become a first class citizen in OSGi by extending multiple sub-domains with automatic database migration capabilities. On the other hand, 'Elasticsearch' is integrated in OSGi to become a separate search module coordinating cross-domain use cases.

This unique combination enabled us to satisfy two important customer requirements. Functionally, the software should not be limited by module boundaries to answer business questions. Non-functionally, a future-proof platform is required in which the impact of change is contained and encapsulated in loosely coupled modules.

Bios:
Tom De Wolf
Tom is currently technical lead of a Java software factory delivering multiple projects for multiple clients. His background skills include software architecture, designing & implementing enterprise systems using the Java eco-system. He has specialised in building OSGi based platforms using Agile methodologies and at the same time shaping a technological base platform for future ACA projects. His background as a PhD. in Computer Science at the Katholieke Universiteit Leuven enabled Tom to travel the world and present at multiple international conferences.

Stijn van Den Ende
Stijn is CTO at ACA IT-Solutions. His background skills include software architecture, designing & implementing enterprise class systems based on XML & WebServices, Enterprise Application Integration and B2B integration. He also has a strong background in agile methods. Instructing Java, Patterns, Architecture & XML courses is another way of his involvement with the JEE technology. He advises customers with regards to their enterprise system blueprints, and how to streamline their development process while defining and maintaining the technical roadmap for ACA IT-Solutions.

Published in: Technology

Modularity and Domain Driven Design - A killer combination - T De Wolf & S van Den Ende

  1. 1. MODULARITY AND DOMAIN DRIVEN DESIGN a killer combination? Tom De Wolf Architect tom.dewolf@aca-it.be @tomdw Stijn Van den Enden CTO stijn.vandenenden@aca-it.be @stieno www.aca-it.be
  2. 2. initial development maintenance phase Software Design Customer Satisfaction Separation of Concerns Low coupling High Cohesion B AB A • Change A impacts all modules = costly • Change B requires split of module = costly • Change A only impacts other module if api change • Change B limited to module Encapsulate Source of Change Predictable Cost of Change Constant change Business Driven Aim for 1-on-1 mapping from business changes onto software constructs Source of Change = Business Functional Modularisation
  3. 3. Vehicle Option Make Warranty Model Transport Location Domain Driven Design Without modularity BusinessPartner Address Contact consumer supplier transports owner from to
  4. 4. Vehicle Option Make Warranty Owner Model Transported Item Transport Transport Supplier Transport Consumer Vehicle Context Transport Context Domain Driven Design Modularity with Bounded Contexts BusinessPartner AddressContact Business Partner Context Location from to
  5. 5. transport vehicle MODULAR DATABASE SCHEMA • cross domain database structures not allowed • queries cannot cross domain boundaries NO foreign key business partner UUID MAKE MODEL OWNER_ID djdfjfdkjdk221 Ford C-Max BE1234567 TRANSPORTED_ITEM_ID FROM CONSUMER_ID djdfjfdkjdk221 454 BE1234567 LOCATION_ID ADDRESS 454 Sunstreet 23 foreign key VAT_NUMBER NAME BE1234567 Company A
  6. 6. BENEFITS … • Domain modules can migrate independently to next version! • Database schema is internal to the domain bundle, i.e. NOT part of the API! • Persistence and/or database technology can differ between modules in one system!
  7. 7. Mmodular database migration cross domain transactions Tx Scross domain search and reporting C H A L L E N G E S
  8. 8. Mmodular database migration
  9. 9. M Dev Machine 1 MIGRATION CHALLENGE Dev Machine 2 Continuous Integration Test environment Acceptance environment Production environment Version 1.0.0 Version 1.0.1 Version 1.0.2 Version ? Version ? Version ? environment x Module 1 Module 2 Module 3 Version 1.0.0 Version 3.0.0 Version 2.0.2 Manually track which scripts have run on which environment for which module ?
  10. 10. M LIQUIBASE DATABASECHANGELOG table to track executed changesets for each environment In versioned source code XML based DSL for changeSets www.liquibase.org
  11. 11. M MODULAR LIQUIBASE transportvehicle business partner deployment 1 deployment 2 deployment 3 Migrate modules separately Migrate @deploy of module migrate to initial version migrate to initial version migrate to initial version no db changes, no migration migrate to version 2 migrate to version 2 migrate to version 3
  12. 12. M THE EXTENDER PATTERN bundle A bundle B bundle C bundle D extender bundle Extension Pattern ?! no match /OSGI-INF/liquibase/db.changelog-master.xml osgi-liquibase-extender framework dependency Liquibase change sets domain A change sets domain B change sets domain C • Only extender depends on Liquibase framework • Update of single bundle triggers Liquibase update • New Liquibase process 
 for each matching bundle
  13. 13. Tcross domain transactionsx
  14. 14. JTA OR NOT? • No persistence layer — direct jdbc/sql access — 1 datasource
 
 • Multiple datasources • Different types of persistence layers (JPA, NoSQL, …) • JPA persistence layer in each domain bundle • instead of one big persistence unit • even on 1 datasource T 1 transaction spanning multiple modular domains JTA not needed JTA required x
  15. 15. MODULAR PERSISTENCE T osgi-datasource XA enabled vehicle-domaintransport-domain javax.transaction.TransactionManager transaction provider e.g. atomikos javax.sql.DataSource persistence context persistence context commit x
  16. 16. Scross domain search
  17. 17. Scross domain search SEARCH the tale of the evil joins
  18. 18. NO cross module search
  19. 19. A. Search encapsulated in a separate module leveraging the functionality of other domain modules search- module domainA domainB x x Repository Repository Stop • requires specific implementation for every search • complexity increases with number of modules • inability to leverage power of the datastore SearchAPI
  20. 20. domainA B. Search is using a separate query model search- module domainB SearchAPI EventProvider Update Events Update
  21. 21. $ curl -XPUT ‘localhost:9200/vehicle/external/1’ -d ‘{ “make”: “BMW”, “VIN”: “30203232012102” }’ index document_type id Index a document
  22. 22. $ curl -XPOST ‘localhost:9200/vehicle/external/1/ _update’ -d ‘{ “doc”: {“make”: “Alpina”} }’ Update a document index document_type id
  23. 23. $ curl -XPOST localhost:9200/vehicle/_search?pretty -d ‘{"query":{"match":{"make":"BMW"}}}' index Querying an index
  24. 24. $ curl -XPOST localhost:9200/vehicle/_search?pretty -d ‘{"query":{"match":{"mark":"BMW"}}}' { "took" : 3, "timed_out" : false, "_shards" : { "total" : 5, "successful" : 5, "failed" : 0 }, "hits" : { "total" : 2, "max_score" : 0.30685282, "hits" : [ { "_index" : "vehicle", "_type" : "external", "_id" : "1", "_score" : 0.30685282, "_source" : {"make": "BMW", "VIN": "30203232012102"} }, { "_index" : "vehicle", "_type" : "external", "_id" : "2", "_score" : 0.30685282, "_source" : {"makes": "BMW", "VIN": "30203232012112"} } ]}} ! Querying an index
  25. 25. • Distributed (shards/replicas) • Advanced Quering (lucene/geo/ aggregation) • Facets (terms/ranges/histogram) • API (HTTP/Java/JavaTesting) • … {
  26. 26. 1Populate the index
  27. 27. 1Populate the index package be.vabfs.search.api; ! public interface SearchIndexService { void update(Object entityToUpdate); void delete(Object entityToRemove); ! void populate(); ! void clear(); ! } search SearchIndexService domainB Entity EntityListener @PrePersist @PostUpdate @PostRemove
  28. 28. 1Populate the index search SearchIndexService update(entity) Synchronise onTransaction Track updated entities A Map entities to searchData B Bulk update search index C
  29. 29. 1Populate the index Map entities to searchData B package be.vabfs.search.api.data; ! import java.util.List; ! public interface SearchDataProvider { ! Class<? extends Object> getEntityClass(); List<SearchData> index(Object entity); ! } domainB Entity SearchData
  30. 30. 1Populate the index Map entities to searchData B SearchDataProvider domainB Entity SearchData
  31. 31. 1Populate the index A search SearchIndexService update(entity) Synchronise onTransaction Track updated entities Bulk update search index C Map entities to searchData B SearchDataProvider domainB A
  32. 32. 2Enhancing Search
  33. 33. 2Enhancing Search
  34. 34. 2Enhancing Search search SearchService package be.vabfs.search.api; ! import … ! public interface SearchService { … ! SearchResults query(String query, int start, int rows, String sort, String sortOrder, String documentType); List<String> options(String field, String... documentTypes); List<SearchCriterion> availableCriteria( String... criteriaCategories); }
  35. 35. 2Enhancing Search package be.vabfs.search.api.criteria; ! import java.util.List; ! public interface SearchCriteriaProvider { String getProviderCategory(); List<SearchCriterion> getAvailableCriteria(); } package be.vabfs.search.api.criteria; ! public interface SearchCriterion { ! String getName(); String getKey(); String getUnitName(); SearchCriterionType getType(); SearchCriterionQueryType getQueryType(); String getDocumentType(); ! } "vehicle.mileage" "mileage" SearchCriterionType.NUMBER SearchCriterionQueryType.RANGE_NUMBER "SERVICE_ITEM" "km"
  36. 36. 2Enhancing Search search SearchService domainB SearchCriteriaProvider domainB
  37. 37. LESSONS LEARNED @deployment time migration = RISK • have CI build continuously migrate current production data Refactor wrong modularisation requires unwanted migration dependencies • reset/flatten migration change sets to restore modularisation Migration Cross domain search and reporting Effort to integrate search is limited • due to dynamic osgi service model Advanced search functionality is possible
  38. 38. WHAT IS NEXT? Multiple module versions active? Multiple schema versions active? • e.g. feature try-out to limited customer base Downgrade to older module version? • Previous schema with new data? Hot deploy while users are firing requests? • Migration still busy = failure Migration Cross domain search and reporting Domain Specific Query Language ! Exploiting elastic search capabilities beyond search, e.g. reporting
  39. 39. M Modular migration Liquibase extender @ DeployT Cross domain transactions Distributed JTA transactionsx S Cross domain search Elasticsearch view Functionally not limited by domain module boundaries to answer business questions Non-functionally future-proof platform with impact of change contained in loosely coupled domain modules
  40. 40. Tom De Wolf Architect tom.dewolf@aca-it.be @tomdw Stijn Van den Enden CTO stijn.vandenenden@aca-it.be @stieno www.aca-it.be

×