Publicité

DCI with groovy

Deputy CTO at Inera AB à Inera AB
2 Feb 2011
Publicité

Contenu connexe

Publicité

DCI with groovy

  1. My goal with this talk is to… … make your brain boil of inspiration!
  2. DDD works well for this…
  3. But less well for this… … which is quite common in midsize- to large systems
  4. Because you either end up with this…
  5. … or this….
  6. What if…. … use-case logic could be ATTACHED to domain objects when needed but still OWNED by the application modul?
  7. Like this….
  8. Compile-time…
  9. Deploy-time…
  10. Runtime view…. … of an interaction within the ProduceQuarterlyForecast use-case…
  11. Runtime view…. … of an interaction within the SendSignedOrdersToSupplier use-case…
  12. Taking a look at the role implementation…. public class Article { List<OrderItem> ordered ; PriceList pricelist ; public BigDecimal calcNextQuaterSales() { BigDecimal qSales = … ordered .findAll {OrderItem item -> item.deliveryDate > Calendar.nextQuaterStart && item.deliveryDate < Calendar.nextQuaterEnd}.each {OrderItem item -> qSales += item.amount * pricelist .meanPriceBetweenDates (Calendar.nextQuaterStart, Calendar.nextQuaterEnd) } return qSales } }
  13. Groovy Mixin Simple Sample Context: CalculateNetPriceContext Data: a BigDecimal Interaction: netPrice on Role PriceRole
  14. The code – Define the Role (the mixin) class PriceRole { BigDecimal getNetPrice() { return this * 0.8 } } class CalculateNetPriceContext { def priceRole CalculateNetPriceContext(BigDecimal amount) { amount.metaClass.mixin(PriceRole) priceRole = amount } BigDecimal executeContext() { return priceRole.netPrice } } println new CalculateNetPriceContext(100.00).executeContext()
  15. The code – Context assigns role to data class PriceRole { BigDecimal getNetPrice() { return this * 0.8 } } class CalculateNetPriceContext { def priceRole CalculateNetPriceContext(BigDecimal amount) { amount.metaClass.mixin(PriceRole) priceRole = amount } BigDecimal executeContext() { return priceRole.netPrice } } println new CalculateNetPriceContext(100.00).executeContext()
  16. The code – method to execute interaction class PriceRole { BigDecimal getNetPrice() { return this * 0.8 } } class CalculateNetPriceContext { def priceRole CalculateNetPriceContext(BigDecimal amount) { amount.metaClass.mixin(PriceRole) priceRole = amount } BigDecimal executeContext() { return priceRole.netPrice } } println new CalculateNetPriceContext(100.00).executeContext()
  17. The code – ask the context to conduct the interaction class PriceRole { BigDecimal getNetPrice() { return this * 0.8 } } class CalculateNetPriceContext { def priceRole CalculateNetPriceContext(BigDecimal amount) { amount.metaClass.mixin(PriceRole) priceRole = amount } BigDecimal executeContext() { return priceRole.netPrice } } println new CalculateNetPriceContext(100.00).executeContext()
  18. Let ’ s revisit the BIG system….
  19. Clean dependency graph!
  20. Thanks for listening! Questions? ?

Notes de l'éditeur

  1. Domändriven design förknippas med programmeringsspråk, ramverk och kanske modellering för att kunna beskriva och realisera system – både data och logik – utgående från den information som hanteras. I praktiken handlar det för oss utvecklare om att få fram programkod som i form av klasser, metoder och kanske mappningar mot databaser representerar domänobjekten. Vi har blivit ganska bra på att bygga EN applikation / ett system i ETT team enligt denna modell. Vi har olika sätt att fördela logik mellan tjänster och domänobjekt. Så länge det är ett utvecklings/förvaltningsobjekt (gemensamt ansvar) för alla lager, behöver vi inte fundera så mycket på hur förändringar påverkar olika lager. Vi kan prioritera en domänmodell med mycket logik för att få en objektorienterad programmeringsmodell. Det är helt ok att domänklasserna förändras i varje release av produkten. I en rik domänmodell kan koden bli svår att förstå. Det är lätta att fragmenteringen gör att man tappar greppet om helheten/användningsfallet. Det en baksida av att prioritera återanvändning. Det gör också att det tar ganska lång tid för nya medlemmar i teamet att bli produktiva. Eftersom vårt system är ett “ stuprör ” samverkar det med andra system genom integration. Komplexiteten ökar gradvis när nya användningsfall tillkommer. Förr eller senare önskar vi att vi hade ett mer procedurellt angreppssätt
  2. DDD blir betydligt mer komplext när systemet blir större och behöver modulariseras. Domänklasserna får fler intressenter och det blir plötsligt vikltigt att domänmodellen releasas separat och att den hålls så stabil som möjligt. Vi behöver hitta sätt att partitionera domänmodellen. Vi får svårare att knyta logik till domänklasserna eftersom all kunskap om användningsfallen inte finns fullt ut hos alla i teamet som är beroende av domänmodellen. Det blir svårt med relase-hanteringen när två team med olika leveransplaner är inne och hackar i domänklasserna.
  3. Håller man fast vid att ha logik i domänklasserna (vad som tillkommer pga ett use-case och vad som “ tillhör domänobjektet och har återanvändningspotential ” är ju en glidande skala. Det kostar möten och det kostar samordning, vilket fördyrar och komplicerar
Publicité