Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The Arrows Make the Difference

The Arrows Make the Difference

Designing systems and discussing architectural decisions is hard, because there are so many concerns to respect.
Explicitly distinguishing control flow, information flow, model flow and dependencies helps to clear up the confusion . This allows for richer and more powerful designs - from class level all the way up to bounded contexts and team organization.
I will explain how to fully utilize these concepts and share stories of how tiny arrowheads can make a huge difference, for better and worse.

Richard Wallintin

January 18, 2024
Tweet

More Decks by Richard Wallintin

Other Decks in Programming

Transcript

  1. social.wps.de/@RichardWallintin A B Apple Harvest Box Packaging «information flow» 🍎🍏🍏

    POST /boxes HTTP/1.1 Host: box.packaging Content-Type: apples 🍎🍏🍏
  2. social.wps.de/@RichardWallintin «information flow» 🍎🍏🍏 CONSTRAINED BY • Availability of information

    • Legal restrictions to information exchange • Technical restrictions like bandwidth CONSTRAINS • Ability to perform processes • Locality of processes (à Availability of information)
  3. social.wps.de/@RichardWallintin A B Apple Harvest Box Packaging POST /boxes HTTP/1.1

    Host: box.packaging Content-Type: apples 🍎🍏🍏 «control flow»
  4. social.wps.de/@RichardWallintin A B Apple Harvest Box Packaging POST /boxes HTTP/1.1

    Host: box.packaging Content-Type: apples 🍎🍏🍏 @RestController class PackagingController { @PostMapping(“/boxes”) fun package(apples: …) { … } } «control flow»
  5. social.wps.de/@RichardWallintin A B Apple Harvest Box Packaging @RestController AppleHarvestController {

    @GetMapping(“/apples”) fun fetchApples() { … return “🍎🍏🍏” } } GET /apples HTTP/1.1 Host: apple.harvest «control flow»
  6. social.wps.de/@RichardWallintin A B Apple Harvest Box Packaging jms.convertAndSend( “apples”, “🍎🍏🍏”

    ) @JmsListener( destination = ”apples” ) fun package(apples: String?) { … } «async control flow»
  7. social.wps.de/@RichardWallintin A B Apple Harvest Box Packaging apples jms.convertAndSend( “apples”,

    “🍎🍏🍏” ) @JmsListener( destination = ”apples” ) fun package(apples: String?) { … } «async control flow»
  8. social.wps.de/@RichardWallintin «control flow» CONSTRAINED BY • Technical reachability of systems

    (firewalls, routing) • Capability to actively send (energy consumption) • Capacity to accept incoming data • Capacity to retain outgoing data CONSTRAINS • Timeliness of information exchange • Runtime Availability Coupling
  9. social.wps.de/@RichardWallintin A B Apple Harvest Box Packaging INSERT (🍎🍏🍏) INTO

    BOXES CREATE TABLE BOXES ( A apple not null, B apple not null, … ) «dependency»
  10. social.wps.de/@RichardWallintin A B Apple Harvest Box Packaging class AppleHarvester( val

    packager: BoxPackager ) { … fun afterHarvesting(apples: Apples) { packager.package(apples) … } } class Apples: Items { … } class BoxPackager { fun package(items: Items) { … } } interface Items { … } «dependency»
  11. social.wps.de/@RichardWallintin A B Apple Harvest Box Packaging class AppleHarvester {

    fun fetchApples(): Apples { … return apples } } class Apples { … } class BoxPackager( val harvester: AppleHarvester ) { override fun package() { val apples = harvester.fetchApples() … } } «dependency»
  12. social.wps.de/@RichardWallintin A B Apple Harvest Box Packaging POST /boxes HTTP/1.1

    Host: box.packaging Content-Type: apples 🍎🍏🍏 openapi: 3.0.3 info: title: Box-Packaging description: Box-Packaging version: 1.0.0 servers: - url: http://box.packaging/ paths: /boxes: post: summary: send items for packaging requestBody: required: true description: items to be packaged content: apples: schema: ... «dependency»
  13. social.wps.de/@RichardWallintin A B Apple Harvest Box Packaging POST /boxes HTTP/1.1

    Host: box.packaging Content-Type: apples 🍎🍏🍏 openapi: 3.0.3 info: title: Box-Packaging description: Box-Packaging version: 1.0.0 servers: - url: … paths: /boxes: post: … «dependency» @RestController class PackagingController { @PostMapping(“/boxes”) fun package(apples: …) { … } } C?
  14. social.wps.de/@RichardWallintin CONSTRAINED BY • Ability to modify the code of

    a component CONSTRAINS • Flow of changes through the development process • Impact of changes, incl. unintended • Limitation of Knowledge, Complexity • Ability to act fast & independent «dependency»
  15. social.wps.de/@RichardWallintin A B Apple Harvest Box Packaging class AppleHarvester( val

    packager: BoxPackager ) { … fun afterHarvesting(apples: Apples) { packager.package(apples) … } } class Apples: Items { … } 🍎🍏🍏 class BoxPackager { fun package(items: Items) { … } } interface Items { … }
  16. social.wps.de/@RichardWallintin A B Apple Harvest Box Packaging class AppleHarvester( val

    packager: ApplePackager ) { … fun afterHarvesting(apples: Apples) { packager.package(apples) … } } interface ApplePackager { fun package(apples: Apples) } class Apples { … } 🍎🍏🍏 class BoxPackager: ApplePackager { override fun package(apples: Apples) { … } }
  17. social.wps.de/@RichardWallintin A B Apple Harvest Box Packaging 🍎🍏🍏 class AppleHarvester

    { fun fetchApples(): Apples { … return apples } } class Apples { … } class BoxPackager( val harvester: AppleHarvester ) { override fun package() { val apples = harvester.fetchApples() … } }
  18. social.wps.de/@RichardWallintin A B Apple Harvest Box Packaging 🍎🍏🍏 class AppleHarvester

    : ItemSource { fun fetchItems(): Apples { … return apples } } class Apples : Items { … } class BoxPackager( val source: ItemSource ) { fun package() { val items = source.fetchItems() … } } interface ItemSource { fun fetchItems(): Items } class Items { … }