Model Tension
Heuristics

Preventing Accidental Design Debt

@julientopcu.com

‪@josianchevalier.bsky.social‬

CHAPTER I

When model exploration
   Whirlpool 
      turns into
 model sinking

TODo

Current Quest

Done

Overlapping ships can be selected

Bug

[Paid Option] Wireless pidgin connexion

Feature

JIRA

Ships departing in the past appear in the Search

Bug

Add cancellation insurance

Feature

TODo

Current Quest

Done

Overlapping ships can be selected

Bug

[Paid Option] Wireless pidgin connexion

Feature

JIRA

Bug

Add cancellation insurance

Feature

Ships departing in the past appear in the Search

{
  "search": {
    "id": "XXXX",
    "criteria": {
      "outBoundDate": "2025-10-06T12:00",
      "inBoundDate": "2025-10-16T11:00"
    },
    "selectionComplete" : true,
    "totalPrice" : "230€",
    "paymentMean": {
      "type": "CREDIT_CARD",
      "number": "***********"
    },
    "travelInsurance" : "40€",
    "ships": [
      {
        "number": "A",
        "bound": "outbound",
        "departureDate": "2025-10-06T13:30",
        "fares": [
          {
            "comfortClass" : "FIRST",
            "price": "100€",
            "seatOptions": [ "ANY", "AISLE", "WINDOW", "PANORAMIC_VIEW", "LOUNGE" ],
            "deckOptions": [ "ANY", "UPPER_DECK", "MIDDLE_DECK", "LOWER_DECK" ],
            "preferences": {
              "seat": "LOUNGE",
              "deck" : "UPPER_DECK"
            },
            "selected": true,
            "booked" : true
          },
          {
            "comfortClass" : "SECOND",
            "price": "50€",
            "seatOptions": [ "ANY", "AISLE", "WINDOW" ],
            "deckOptions": [ "ANY", "MIDDLE_DECK", "LOWER_DECK" ],
            "selected": false,
            "booked" : false
          }
        ]
      },
      {
        "number": "B",
        "bound": "outbound",
        "departureDate": "2025-10-06T15:30",
        "fares": [
          {
            "comfortClass" : "FIRST",
            "price": "80€",
            "selected": false,
            "booked" : false
          }
        ]
      },
      {
        "number": "C",
        "bound": "inbound",
        "departureDate": "2025-10-16T12:00",
        "fares": [
          {
            "comfortClass" : "FIRST",
            "price": "90€",
            "seatOptions": [ "ANY", "AISLE", "WINDOW", "PANORAMIC_VIEW" ],
            "deckOptions": [ "ANY", "UPPER_DECK", "LOWER_DECK" ],
            "preferences": {
              "seat": "PANORAMIC_VIEW",
              "deck" : "UPPER_DECK"
            },
            "selected": true,
            "booked": true
          }
        ]
      },
      {
        "number": "D",
        "bound": "inbound",
        "departureDate": "2025-10-16T14:00",
        "fares": [
          {
            "comfortClass" : "FIRST",
            "price": "100€",
            "seatOptions": [ "ANY", "AISLE", "WINDOW", "PANORAMIC_VIEW" ],
            "deckOptions": [ "ANY", "UPPER_DECK", "LOWER_DECK" ],
            "selected": false,
            "booked" : false
          },
          {
            "comfortClass" : "SECOND",
            "price": "50€",
            "seatOptions": [ "ANY", "AISLE", "WINDOW" ],
            "deckOptions": [ "ANY", "LOWER_DECK" ],
            "selected": false,
            "booked" : false

          }
        ]
      }
    ]
  }
}
{
  "search": {
    "id": "XXXX",
    "criteria": {
      "outBoundDate": "2025-10-06T12:00",
      "inBoundDate": "2025-10-16T11:00"
    },
    "selectionComplete" : true,
    "totalPrice" : "230€",
    "paymentMean": {
      "type": "CREDIT_CARD",
      "number": "***********"
    },
    "travelInsurance" : "40€",
    "ships": [
      {
        "number": "A",
        "bound": "outbound",
        "departureDate": "2025-10-06T13:30",
        "fares": [
          {
            "comfortClass" : "FIRST",
            "price": "100€",
            "seatOptions": [ "ANY", "AISLE", "WINDOW", "PANORAMIC_VIEW", "LOUNGE" ],
            "deckOptions": [ "ANY", "UPPER_DECK", "MIDDLE_DECK", "LOWER_DECK" ],
            "preferences": {
              "seat": "LOUNGE",
              "deck" : "UPPER_DECK"
            },
            "selected": true,
            "booked" : true
          },
          {
            "comfortClass" : "SECOND",
            "price": "50€",
            "seatOptions": [ "ANY", "AISLE", "WINDOW" ],
            "deckOptions": [ "ANY", "MIDDLE_DECK", "LOWER_DECK" ],
            "selected": false,
            "booked" : false
          }
        ]
      },
      {
        "number": "B",
        "bound": "outbound",
        "departureDate": "2025-10-06T15:30",
        "fares": [
          {
            "comfortClass" : "FIRST",
            "price": "80€",
            "selected": false,
            "booked" : false
          }
        ]
      },
      {
        "number": "C",
        "bound": "inbound",
        "departureDate": "2025-10-16T12:00",
        "fares": [
          {
            "comfortClass" : "FIRST",
            "price": "90€",
            "seatOptions": [ "ANY", "AISLE", "WINDOW", "PANORAMIC_VIEW" ],
            "deckOptions": [ "ANY", "UPPER_DECK", "LOWER_DECK" ],
            "preferences": {
              "seat": "PANORAMIC_VIEW",
              "deck" : "UPPER_DECK"
            },
            "selected": true,
            "booked": true
          }
        ]
      },
      {
        "number": "D",
        "bound": "inbound",
        "departureDate": "2025-10-16T14:00",
        "fares": [
          {
            "comfortClass" : "FIRST",
            "price": "100€",
            "seatOptions": [ "ANY", "AISLE", "WINDOW", "PANORAMIC_VIEW" ],
            "deckOptions": [ "ANY", "UPPER_DECK", "LOWER_DECK" ],
            "selected": false,
            "booked" : false
          },
          {
            "comfortClass" : "SECOND",
            "price": "50€",
            "seatOptions": [ "ANY", "AISLE", "WINDOW" ],
            "deckOptions": [ "ANY", "LOWER_DECK" ],
            "selected": false,
            "booked" : false

          }
        ]
      }
    ]
  }
}
public record Search(UUID id, Criteria criteria, SearchType searchType, List<Ship> ships) {

    public Search {
+ 		if(!hasBookedShips()){
          assert ships.stream()
          			.noneMatch(ship -> ship.departureDate().isBefore(now()))
                : "Some ships are departing in the past";
+ 		}
    }
}

Fix Booking history regression #2097

Josian merged 10 commits into

cruising:main

+ 532

- 385

public record Search(UUID id, Criteria criteria, SearchType searchType, List<Ship> ships) {

    public Search {
-		if(!hasBookedShips()){
-         assert ships.stream()
-         			.noneMatch(ship -> ship.departureDate().isBefore(now()))
-               : "Some ships are departing in the past";
 		}
    }
}

Fix "Previous Days Ships" feature #2099

Josian merged 57 commits into

cruising:main

+ 1278

- 843

The Mighty

Big Ball Of Mud

drives

Exploration

&

Experimentation

Business Need

Search for Ship

drives

Exploration

&

Experimentation

Business Need

shape

Search for Ship

Model

drives

Exploration

&

Experimentation

Business Need

shape

Model

needs to account for new

Selection of a Ship's Fare

drives

Exploration

&

Experimentation

Business Need

shape

Whirlpool

needs to account for new

Selection of a Ship's Fare

Model

Model Exploration

drives

Exploration

&

Experimentation

Business Need

expand

needs to account for new

Model

Whirlpool

Model Exploration

drives

Business Need

Exploration

&

Experimentation

Sinking

Model

Model

expand

needs to account for new

drives

Exploration

&

Experimentation

Business Need

Solution-Push

focuses on

Model

needs to account for new

expand

drives

Exploration

&

Experimentation

Business Need

Solution-Push

focuses on

Obsolete

Model

needs to account for new

expand

drives

Exploration

&

Experimentation

Business Need

shape

Model

$$$

needs to account for new

No model is Inherently extensible !

Exploration

&

Experimentation

Business Need

Model

needs to account for new

Business Need

Model

Model Exploration
Whirlpool

challenged by new

Not a confirmation bias

Exploration

&

Experimentation

needs to account for new

Business Need

by shaping

Model

New Model

may

depreciate

Exploration

&

Experimentation

challenged by new

Accidental Design Debt:
the invisible engine of BBOMs

One does not simply

challenge the model

{
  "search": {
    "id": "XXXX",
    "criteria": {
      "outBoundDate": "2025-10-06T12:00",
      "inBoundDate": "2025-10-16T11:00"
    },
    "ships": [
      {
        "number": "A",
        "bound": "outbound",
        "departureDate": "2025-10-06T13:30",
        "fares": [
          {
            "comfortClass" : "FIRST",
            "price": "100€",
          }
        ]
      }
    ]
}

Search ships

{
  "search": {
    "id": "XXXX",
    "criteria": {
      "outBoundDate": "2025-10-06T12:00",
      "inBoundDate": "2025-10-16T11:00"
    },
    "ships": [
      {
        "number": "A",
        "bound": "outbound",
        "departureDate": "2025-10-06T13:30",
        "fares": [
          {
            "comfortClass" : "FIRST",
            "price": "100€",
            "seatOptions": [ "ANY", "..." ],
            "deckOptions": [ "ANY", "..." ],
            "preferences": {
              "seat": "LOUNGE",
              "deck" : "UPPER_DECK"
            },
            "selected": true,
          }
        ]
      }
    ],
    "selectionComplete" : true,
    "totalPrice" : "230€",
}

Search ships

Select ships

{
  "search": {
    "id": "XXXX",
    "criteria": {
      "outBoundDate": "2025-10-06T12:00",
      "inBoundDate": "2025-10-16T11:00"
    },
    "ships": [{
        "number": "A",
        "bound": "outbound",
        "departureDate": "2025-10-06T13:30",
        "fares": [{
            "comfortClass" : "FIRST",
            "price": "100€",
            "seatOptions": [ "ANY", "..." ],
            "deckOptions": [ "ANY", "..." ],
            "preferences": {
              "seat": "LOUNGE",
              "deck" : "UPPER_DECK"
            },
            "selected": true,
            "booked" : true, 
          }]
    }],
    "selectionComplete" : true,
    "totalPrice" : "230€",
    "paymentMean": {
      "type": "CREDIT_CARD",
      "number": "***********"
    },
    "travelInsurance" : "40€",
  }

Search ships

Select ships

Book ships

Accidental
Design Debt

The Ruthless

Accidental Design Debt

Model

Accidental
Design Debt

generates through


misguided decisions

manifests

as complexity in

lower their cohesion and flexibility,

increase their complexity,

and erode their correctness.

introducing coupling in models,

from Decisions that inadvertently

Model

Accidental
Design Debt

generates through


misguided decisions

manifests

as complexity in

More bugs in unrelated parts of the model?

Simple change causing widespread model updates?

Model

Accidental
Design Debt

generates through


misguided decisions

manifests

as complexity in

More bugs in unrelated parts of the model?

Features taking longer to develop?

More bugs in unrelated parts of the model?

Simple change causing widespread model updates?

Model

Accidental
Design Debt

generates through


misguided decisions

manifests

as complexity in

The Unyielding

Model entropy

Features taking longer to develop?

More bugs in unrelated parts of the model?

Simple change causing widespread model updates?

Model entropy

High Entropy

Design effort is dissipated on navigating accidental complexity

Degree of design disorder

low coherency, consistency, cohesiveness

unclear outcomes

unexpected regressions

dissipates the structure
and clarity of

Model
Entropy

produces through accumulation

Model

Accidental
Design Debt

generates through


misguided decisions

dissolves the model into a

BBOM

Model
Entropy

produces through accumulation

dissipates the structure
and clarity of

Model
Sclerosis

hardens into

locking the model into

Model

Accidental
Design Debt

generates through


misguided decisions

Spork Effect:
unveiling the roots of model fragility and rigidity

{
  "search": {
    "id": "XXXX",
    "criteria": {
      "outBoundDate": "2025-10-06T12:00",
      "inBoundDate": "2025-10-16T11:00"
    },
    "selectionComplete" : true,
    "totalPrice" : "230€",
    "paymentMean": {
      "type": "CREDIT_CARD",
      "number": "***********"
    },
    "travelInsurance" : "40€",
    "ships": [
      {
        "number": "A",
        "bound": "outbound",
        "departureDate": "2025-10-06T13:30",
        "fares": [
          {
            "comfortClass" : "FIRST",
            "price": "100€",
            "seatOptions": [ "ANY", "..." ],
            "deckOptions": [ "ANY", "..." ],
            "preferences": {
              "seat": "LOUNGE",
              "deck" : "UPPER_DECK"
            },
            "selected": true,
            "booked" : true

Booking

Search

manifests as

KISS
DRY
YAGNI

Refactoring
Habits

KISS
DRY
YAGNI

Refactoring
Habits

Sunk Cost
Fallacies

Deadlines
Pressure

Intrinsic
Coupling

{}

fosters

fosters

Booking

Search

Intrinsic
Coupling

{
  "search": {
    "id": "XXXX",
    "criteria": {
      "outBoundDate": "2025-10-06T12:00",
      "inBoundDate": "2025-10-16T11:00"
    },
    "selectionComplete" : true,
    "totalPrice" : "230€",
    "paymentMean": {
      "type": "CREDIT_CARD",
      "number": "***********"
    },
    "travelInsurance" : "40€",
    "ships": [
      {
        "number": "A",
        "bound": "outbound",
        "departureDate": "2025-10-06T13:30",
        "fares": [
          {
            "comfortClass" : "FIRST",
            "price": "100€",
            "seatOptions": [ "ANY", "..." ],
            "deckOptions": [ "ANY", "..." ],
            "preferences": {
              "seat": "LOUNGE",
              "deck" : "UPPER_DECK"
            },
            "selected": true,
            "booked" : true

Booking

Search

Booking

Spork  effect

Intrinsic
Coupling

manifests as
strong

Accidental
Design Debt

Responsibilities
Coupling

may induce

"Spork Effect"

"Spork Effect"

causes

Model
Fragility

Intrinsic
Coupling

manifests as
strong

Accidental
Design Debt

Responsibilities
Coupling

may induce

Model
Rigidity

leads to

Model
Entropy

increases

produces
through accumulation

{}

Booking

Search

Intrinsic
Coupling

{
  "search": {
    "id": "XXXX",
    "criteria": {
      "outBoundDate": "2025-10-06T12:00",
      "inBoundDate": "2025-10-16T11:00"
    },
    "selectionComplete" : true,
    "totalPrice" : "230€",
    "paymentMean": {
      "type": "CREDIT_CARD",
      "number": "***********"
    },
    "travelInsurance" : "40€",
    "ships": [
      {
        "number": "A",
        "bound": "outbound",
        "departureDate": "2025-10-06T13:30",
        "fares": [
          {
            "comfortClass" : "FIRST",
            "price": "100€",
            "seatOptions": [ "ANY", "..." ],
            "deckOptions": [ "ANY", "..." ],
            "preferences": {
              "seat": "LOUNGE",
              "deck" : "UPPER_DECK"
            },
            "selected": true,
            "booked" : true

Booking

Search

Booking

Search

Booking

Distinct Models!

Search

Booking

Booking

Model tension as signals of accidental design debt

{
  "search": {
    "id": "XXXX",
    "criteria": {
      "outBoundDate": "2025-10-06T12:00",
      "inBoundDate": "2025-10-16T11:00"
    },
    "selectionComplete" : true,
    "totalPrice" : "230€",
    "paymentMean": {
      "type": "CREDIT_CARD",
      "number": "***********"
    },
    "travelInsurance" : "40€",
    "ships": [
      {
        "number": "A",
        "bound": "outbound",
        "departureDate": "2025-10-06T13:30",
        "fares": [
          {
            "comfortClass" : "FIRST",
            "price": "100€",
            "seatOptions": [ "ANY", "..." ],
            "deckOptions": [ "ANY", "..." ],
            "preferences": {
              "seat": "LOUNGE",
              "deck" : "UPPER_DECK"
            },
            "selected": true,
            "booked" : true

ModelTension

The Fearsome

Model Tension

is a structural stress within a model that signals it is being stretched beyond its conceptual integrity.

conceptual integrity

Model
Tension

is the result

of

Accidental
Design Debt

Intrinsic
Coupling

may
induce

Conceptual Integrity

 is the degree to which a model maintains clarity, coherency, cohesion                            

and its purpose.

is the result

of

Accidental
Design Debt

Model
Tension

Conceptual
Integrity

erodes

prevents

{
  "search": {
    "id": "XXXX",
    "criteria": {
      "outBoundDate": "2025-10-06T12:00",
      "inBoundDate": "2025-10-16T11:00"
    },
    "selectionComplete" : true,
    "totalPrice" : "230€",
    "paymentMean": {
      "type": "CREDIT_CARD",
      "number": "***********"
    },
    "travelInsurance" : "40€",
    "ships": [
      {
        "number": "A",
        "bound": "outbound",
        "departureDate": "2025-10-06T13:30",
        "fares": [
          {
            "comfortClass" : "FIRST",
            "price": "100€",
            "seatOptions": [ "ANY", "..." ],
            "deckOptions": [ "ANY", "..." ],
            "preferences": {
              "seat": "LOUNGE",
              "deck" : "UPPER_DECK"
            },
            "selected": true,
            "booked" : true

Model
Tension

{
  "search": {
    "id": "XXXX",
    "criteria": {
      "outBoundDate": "2025-10-06T12:00",
      "inBoundDate": "2025-10-16T11:00"
    },
    "selectionComplete" : true,
    "totalPrice" : "230€",
    "paymentMean": {
      "type": "CREDIT_CARD",
      "number": "***********"
    },
    "travelInsurance" : "40€",
    "ships": [
      {
        "number": "A",
        "bound": "outbound",
        "departureDate": "2025-10-06T13:30",
        "fares": [
          {
            "comfortClass" : "FIRST",
            "price": "100€",
            "seatOptions": [ "ANY", "..." ],
            "deckOptions": [ "ANY", "..." ],
            "preferences": {
              "seat": "LOUNGE",
              "deck" : "UPPER_DECK"
            },
            "selected": true,
            "booked" : true
{
  "search": {
    "id": "XXXX",
    "criteria": {
      "outBoundDate": "2025-10-06T12:00",
      "inBoundDate": "2025-10-16T11:00"
    },
    "selectionComplete" : true,
    "totalPrice" : "230€",
    "paymentMean": {
      "type": "CREDIT_CARD",
      "number": "***********"
    },
    "travelInsurance" : "40€",
    "ships": [
      {
        "number": "A",
        "bound": "outbound",
        "departureDate": "2025-10-06T13:30",
        "fares": [
          {
            "comfortClass" : "FIRST",
            "price": "100€",
            "seatOptions": [ "ANY", "..." ],
            "deckOptions": [ "ANY", "..." ],
            "preferences": {
              "seat": "LOUNGE",
              "deck" : "UPPER_DECK"
            },
            "selected": true,
            "booked" : true

Model
Tension

Booking

Search

{
  "search": {
    "id": "XXXX",
    "criteria": {
      "outBoundDate": "2025-10-06T12:00",
      "inBoundDate": "2025-10-16T11:00"
    },
    "selectionComplete" : true,
    "totalPrice" : "230€",
    "paymentMean": {
      "type": "CREDIT_CARD",
      "number": "***********"
    },
    "travelInsurance" : "40€",
    "ships": [
      {
        "number": "A",
        "bound": "outbound",
        "departureDate": "2025-10-06T13:30",
        "fares": [
          {
            "comfortClass" : "FIRST",
            "price": "100€",
            "seatOptions": [ "ANY", "..." ],
            "deckOptions": [ "ANY", "..." ],
            "preferences": {
              "seat": "LOUNGE",
              "deck" : "UPPER_DECK"
            },
            "selected": true,
            "booked" : true

Booking

Search

Booking

Selection

Selection

Model
Tension

Crystallized
ModelTension

The Unstoppable

compromises

"fibrosing"

left unresolved

leads to

Model
Tension

Conceptual
Integrity

erodes

Crystallized
Model Tension

Model
Entropy

raises

Model
Sclerosis

hardens into

shapes

left unresolved

leads to

Model
Tension

Crystallized
Model Tension

Model
Obsolescence

signals

ModelTension

as signal of accidental design debt

The Fearsome

ModelTension

as signal of accidental design debt

The Fearsome

invisible

Exploring (intrinsic)
model tensions heuristics

visual elements © Alberto Brandolini

Search
Bound

Select
a Fare on a Ship

Ship + Fare
Selected On Bound

Compute Total Price

Total Price Computation

Total Price Computed

Check
Completion

Fares Selection
COmpleted

Selected Fares

Selected Fares

Fares Selection Found Incomplete

Check Selected Fares
Completion

visual elements © Alberto Brandolini

Search
Bound

Select
a Fare on a Ship

Ship + Fare Selected On Bound

Compute Total Price

Total Price Computation

Total Price Computed

Check
Completion

Check Selected Fares
Completion

Fares Selection
COmpleted

Selected Fares

Fares Selection Found Incomplete

Selected Fares

visual elements © Alberto Brandolini

Search
Bound

Select
a Fare on a Ship

Ship + Fare
Selected On Bound

Compute Total Price

Total Price Computation

Total Price Computed

Check
Completion

Fares Selection
COmpleted

Selected Fares

Selected Fares

Fares Selection Found Incomplete

Check Selected Fares
Completion

visual elements © Alberto Brandolini

Search
Bound

Select
a Fare on a Ship

Ship + Fare
Selected On Bound

Compute Total Price

Total Price Computation

Total Price Computed

Check
Completion

Fares Selection
COmpleted

Selected Fares

Selected Fares

Fares Selection Found Incomplete

Check Selected Fares
Completion

Linguistic Tension

Salience Bias

Salience Bias

Linguistic Tension

A cognitive bias that predisposes people to focus on  information that are more prominent or visible

visual elements © Alberto Brandolini

Search
Bound

Select
a Fare on a Ship

Ship + Fare
Selected On Bound

Compute Total Price

Total Price Computation

Total Price Computed

Check
Completion

Fares Selection
COmpleted

Selected Fares

Selected Fares

Fares Selection Found Incomplete

Check Selected Fares
Completion

Search
Bound

Select
a Fare on a Ship

Ship + Fare
Selected On Bound

Compute Total Price

Total Price Computation

Total Price Computed

Check
Completion

Fares Selection
COmpleted

Selected Fares

Selected Fares

Fares Selection Found Incomplete

Ancillaries

Retrieval

List
Ancillaries

Ship

Fare

Ancillaries
Listed

Ancillaries

visual elements © Alberto Brandolini

Check Selected Fares
Completion

Ancillary
Ship

Select
Ancillary

Ancillary
Selected

Search
Bound

Ship + Fare
Selected On Bound

Compute Total Price

Total Price Computation

Total Price Computed

Check
Completion

Fares Selection
COmpleted

Selected Fares

Selected Fares

Fares Selection Found Incomplete

Ancillaries

Retrieval

List
Ancillaries

Ship

Fare

Ancillaries
Listed

Ancillaries

Select
a Fare on a Ship

visual elements © Alberto Brandolini

Check Selected Fares
Completion

Ancillary
Ship

Select
Ancillary

Ancillary
Selected

Search
Bound

Ship + Fare
Selected On Bound

Compute Total Price

Total Price Computation

Total Price Computed

Check
Completion

Fares Selection
COmpleted

Selected Fares

Selected Fares

Fares Selection Found Incomplete

Ancillaries

Retrieval

List
Ancillaries

Ship

Fare

Ancillaries
Listed

Ancillaries

Select
a Fare on a Ship

Ancillaries

visual elements © Alberto Brandolini

Check Selected Fares
Completion

Ancillary
Ship

Select
Ancillary

Ancillary
Selected

Search
Bound

Ship + Fare
Selected On Bound

Compute Total Price

Total Price Computation

Total Price Computed

Check
Completion

Fares Selection
COmpleted

Selected Fares

Fares Selection Found Incomplete

Ancillaries

Retrieval

List
Ancillaries

Ship

Fare

Ancillaries
Listed

Ancillaries

Select
a Fare on a Ship

visual elements © Alberto Brandolini

Check Selected Fares
Completion

Selected Fares +
Ancillaries

Relationship Tension

Association as a Concept

Selected Fares &
Ancillaries

The contextual association of  seemingly independent concepts hides a cohesive concept

Relationship Tension

Association as a Concept

Selected Fares &
Ancillaries

The contextual association of  seemingly independent concepts hides a cohesive concept

Relationship Tension

Association as a Concept

 

 

Selection

 

 

Ancillary
Ship

Select
Ancillary

Ancillary
Selected

Search
Bound

Ship + Fare
Selected On Bound

Compute Total Price

Total Price Computation

Total Price Computed

Check
Completion

Fares Selection
COmpleted

Selected Fares

Fares Selection Found Incomplete

Ancillaries

Retrieval

List
Ancillaries

Ship

Fare

Ancillaries
Listed

Ancillaries

Select
a Fare on a Ship

Selected Fares

Ancillaries

visual elements © Alberto Brandolini

Check Selected Fares
Completion

Ancillary
Ship

Select
Ancillary

Ancillary
Selected

Search
Bound

Ship + Fare
Selected On Bound

Price
Selection

Total Price Computation

Selection
Priced

Check
Completion

Fares Selection
COmpleted

Selected Fares

Fares Selection Found Incomplete

Ancillaries

Retrieval

List
Ancillaries

Ship

Fare

Ancillaries
Listed

Ancillaries

Select
a Fare on a Ship

Selection

Priced
Selection

visual elements © Alberto Brandolini

Check Selected Fares
Completion

Ancillary
Ship

Select
Ancillary

Ancillary
Selected

Search
Bound

Ship + Fare
Selected On Bound

Check
Completion

Fares Selection
COmpleted

Selected Fares

Fares Selection Found Incomplete

Ancillaries

Retrieval

List
Ancillaries

Ship

Fare

Ancillaries
Listed

Ancillaries

Select
a Fare on a Ship

Price
Selection

Total Price Computation

Selection
Priced

Priced
Selection

Selection

visual elements © Alberto Brandolini

Check Selected Fares
Completion

Ancillary
Ship

Select
Ancillary

Ancillary
Selected

Search
Bound

Ship + Fare
Selected On Bound

Check
Selection
Completion

Check
Selection
Completion

Selection
COmpleted

Selected Fares

Selection Found Incomplete

Ancillaries

Retrieval

List
Ancillaries

Ship

Fare

Ancillaries
Listed

Ancillaries

Select
a Fare on a Ship

Incomplete
Selection

complete
Selection

Price
Selection

Total Price Computation

Selection
Priced

Priced
Selection

Selection

(Selection)

visual elements © Alberto Brandolini

Ancillary
Ship

Select
Ancillary

Ancillary
Selected

Search
Bound

Ship + Fare
Selected On Bound

Check
Selection
Completion

Check
Selection
Completion

Selection
COmpleted

Selected Fares

Selection Found Incomplete

Ancillaries

Retrieval

List
Ancillaries

Ship

Fare

Ancillaries
Listed

Ancillaries

Select
a Fare on a Ship

Incomplete
Selection

complete
Selection

Price
Selection

Total Price Computation

Selection
Priced

Priced
Selection

Selection

(Selection)

visual elements © Alberto Brandolini

Search
Bound

Select
a Fare on a Ship

Ship + Fare
Selected On Bound

Compute Total Price

Total Price Computation

Total Price Computed

Check
Completion

Fares Selection
COmpleted

Selected Fares

Selected Fares

Fares Selection Found Incomplete

Ancillaries

Retrieval

List
Ancillaries

Ship

Fare

Ancillaries
Listed

Ancillaries

Incomplete
Selection

complete
Selection

Priced
Selection

visual elements © Alberto Brandolini

Check Selected Fares
Completion

Lifecycle Tension

Implicit Lifecycle

The lifecycle of a concept is derived from the states of other concepts or from false cognates

Lifecycle Tension

Implicit Lifecycle

Ancillary
Ship

Select
Ancillary

Ancillary
Selected

Search
Bound

Ship + Fare
Selected On Bound

Check
Selection
Completion

Check
Selection
Completion

Selection
COmpleted

Selected Fares

Selection Found Incomplete

Ancillaries

Retrieval

List
Ancillaries

Ship

Fare

Ancillaries
Listed

Ancillaries

Select
a Fare on a Ship

Incomplete
Selection

complete
Selection

Price
Selection

Total Price Computation

Selection
Priced

Priced
Selection

Selection

(Selection)

visual elements © Alberto Brandolini

Select
Ancillary

Check
Selection
Completion

Selection
COmpleted

Selection Found Incomplete

Price
Selection

Selection
Priced

Select
a Fare on a Ship

Ancillary
Selected

Ship + Fare
Selected On Bound

SELECTION

visual elements © Alberto Brandolini

{
  "search": {
    "id": "XXXX",
    "criteria": {
      "outBoundDate": "2025-10-06T12:00",
      "inBoundDate": "2025-10-16T11:00"
    },
    "selectionComplete" : true,
    "totalPrice" : "230€",
    "paymentMean": {
      "type": "CREDIT_CARD",
      "number": "***********"
    },
    "ships": [
      {
        "number": "A",
        "bound": "outbound",
        "departureDate": "2025-10-06T13:30",
        "fares": [
          {
            "comfortClass" : "FIRST",
            "price": "100€",
            "selected": true,
            "booked" : true
{
  "search": {
    "id": "XXX",
    "ships": [
      {
        "number": "A",
        "bound": "outbound",
        "fares": [
          {
            "comfortClass": "FIRST",
            "price": "100€"
          },
          {
            "comfortClass": "SECOND",
            "price": "50€"
          }
        ]
      },
      {
        "number": "B",
        "bound": "outbound",
        "fares": [
          {
            "comfortClass": "FIRST",
            "price": "80€"
          }
        ]
      },
      {
        "number": "C",
        "bound": "inbound",
        "fares": [
          {
            "comfortClass": "FIRST",
            "price": "90€"
          }
        ]
      },
      {
        "number": "D",
        "bound": "inbound",
        "fares": [
          {
            "comfortClass": "FIRST",
            "price": "100€"
          },
          {
            "comfortClass": "SECOND",
            "price": "50€"
          }
        ]
      }
    ]
  }
}
{
  "selection": {
    "id": "YYYY",
    "isComplete": true,
    "totalPrice": "190€",
    "outbound": {
      "number": "A",
      "fare": {
        "comfortClass": "FIRST",
        "price": "100€"
      }
    },
    "inbound": {
      "number": "C",
      "fare": {
        "comfortClass": "FIRST",
        "price": "90€"
      }
    }
  }
}
class Selection {
  TripType tripType;
  Map<Bound, Fare> selectedFares = new HashMap();

  void selectFare(Bound bound, Fare selectedFare) {
    selectedFares.put(bound, selectedFare);
  }

  Price totalPrice() {
    return selectedFares.values().stream()
            .reduce(Fare::add)
            .get();
  }

  boolean isSelectionComplete() {
    if (tripType == ONEWAY){
        return selectedFares.size() == 1;
    } else {
        return selectedFares.size() == 2;
    }
  }
}
public record Search(UUID id, Criteria criteria, SearchType searchType, List<Ship> ships, PaymentMean paymentMean) {

    public Search {
            assert ships.stream().noneMatch(ship -> ship.departureDate().isBefore(now())) 
				: "Some ships are departing in the past";
    }
    /*...*/
}
public record Search(UUID id, Criteria criteria, SearchType searchType, List<Ship> ships, PaymentMean paymentMean) {

    public Search {
        if (!hasBookedShips()) {
            assert ships.stream().noneMatch(ship -> ship.departureDate().isBefore(now())) 
				: "Some ships are departing in the past";
        }
    }
}

public record Search(UUID id, Criteria criteria, SearchType searchType, List<Ship> ships, PaymentMean paymentMean) {

    public Search {
        if (!hasBookedShips()) {
            assert ships.stream().noneMatch(ship -> ship.departureDate().isBefore(now())) 
				: "Some ships are departing in the past";
        }
    }

    public boolean hasBookedShips() {
        Map<Bound, Long> bookedShipsPerBound =
                ships.stream()
                        .flatMap(ship -> ship.fares().stream().filter(Fare::booked).map(_ -> ship))
                        .collect(groupingBy(Ship::bound, counting()));

        if (searchType == SearchType.ONEWAY) {
            return bookedShipsPerBound.get(OUTBOUND) == 1;
        } else { //RoundTrip
            return bookedShipsPerBound.get(OUTBOUND) == 1 && bookedShipsPerBound.get(INBOUND) == 1;
        }
    }

    public List<Ship> getBookedShips() {
        var bookedShips = ships.stream().filter(ship -> ship.fares().stream().anyMatch(Fare::booked)).toList();

        if (bookedShips.isEmpty()) {
            return Collections.emptyList();
        }

        List<Ship> cleanedShips = new ArrayList<>();
        for (var bookedShip : bookedShips) {
            Fare bookedFare = getBookedFare(bookedShip);
            Ship cleanedShip = new Ship(bookedShip.number(), bookedShip.bound(), bookedShip.departureDate(), asList(bookedFare));
            cleanedShips.add(cleanedShip);
        }
        return cleanedShips;
    }

    private Fare getBookedFare(Ship bookedShip) {
        Fare bookedFare = null;
        int i = 0;
        while(i < bookedShip.fares().size()) {
            Fare fare = bookedShip.fares().get(i);
            if(fare.booked()){
                bookedFare = fare;
            }
            i++;
        }
        return bookedFare;
    }

    public void book() {
        if(paymentMean == null) {
            throw new IllegalStateException("Payment mean is missing");
        }

        if (hasBookedShips()) {
            throw new IllegalStateException("Ships are already booked");
        }
        var selectedFaresPerBound = new ArrayList<Entry<Bound, Fare>>();
        for (Ship ship : ships) {
            for (Fare fare : ship.fares()) {
                if (fare.selected()) {
                    selectedFaresPerBound.add(entry(ship.bound(), fare));
                }
            }
        }

        if (selectedFaresPerBound.isEmpty()) {
            throw new IllegalStateException("Ships must be selected before booking");
        }

        var numberOfSelectedFarePerBound = selectedFaresPerBound.stream().collect(groupingBy(Entry::getKey, counting()));
        if (searchType == SearchType.ONEWAY) {
            assert numberOfSelectedFarePerBound.get(OUTBOUND) == 1 && numberOfSelectedFarePerBound.get(INBOUND) == 0 : "Inconsistent number of selected fares";
        } else { //RoundTrip
            assert numberOfSelectedFarePerBound.get(OUTBOUND) == 1 && numberOfSelectedFarePerBound.get(INBOUND) == 1 : "Inconsistent number of selected fares";
        }

        for (Entry<Bound, Fare> selectedFare : selectedFaresPerBound) {
            selectedFare.getValue().book();
        }
    }

    public boolean isSelectionComplete() {
        Map<Bound, Long> selectedFaresPerBound = ships.stream().flatMap(ship -> ship.fares().stream().filter(Fare::selected).map(_ -> ship)).collect(groupingBy(Ship::bound, counting()));

        var selectedOutBounds = selectedFaresPerBound.get(OUTBOUND);
        var selectedInBounds = selectedFaresPerBound.get(INBOUND);

        if (searchType == SearchType.ONEWAY) {
            //This should never happen 👇
            assert selectedOutBounds <= 1 && selectedInBounds <= 0 : "Too many fares are selected";
            return selectedOutBounds == 1;
        } else { //RoundTrip

            //This should never happen 👇
            assert selectedOutBounds <= 1 && selectedInBounds <= 1 : "Too many fares are selected";
            return selectedOutBounds == 1 && selectedInBounds == 1;
        }
    }

    public Price getTotalPrice() {
        return ships.stream().flatMap(ship -> ship.fares().stream().filter(Fare::selected).map(Fare::price)).reduce(Price::add).orElse(Price.ZERO);
    }

    public void selectFareOfShip(Bound bound, String shipNumber, ComfortClass comfortClass) {
        var fareToSelect = ships.stream().filter(ship -> ship.number().equals(shipNumber) && ship.bound() == bound).flatMap(ship -> ship.fares().stream().filter(fare -> fare.comfortClass() == comfortClass)).findFirst().orElseThrow();

        var previousSelectionOnBound = ships.stream().filter(ship -> ship.bound() == bound).flatMap(ship -> ship.fares().stream()).filter(Fare::selected).findFirst();

        previousSelectionOnBound.ifPresent(fare -> fare.setSelected(false));
        fareToSelect.setSelected(true);
    }
}
{
  "search": {
    "id": "XXXX",
    "criteria": {
      "outBoundDate": "2025-10-06T12:00",
      "inBoundDate": "2025-10-16T11:00"
    },
    "selectionComplete" : true,
    "totalPrice" : "230€",
    "paymentMean": {
      "type": "CREDIT_CARD",
      "number": "***********"
    },
    "ships": [
      {
        "number": "A",
        "bound": "outbound",
        "departureDate": "2025-10-06T13:30",
        "fares": [
          {
            "comfortClass" : "FIRST",
            "price": "100€",
            "selected": true,
            "booked" : true
public record Search(UUID id, Criteria criteria, SearchType searchType, List<Ship> ships) {

    public Search {
		assert ships.stream().noneMatch(ship -> ship.departureDate().isBefore(now())) 
			: "Some ships are departing in the past";
    }

   /*...*/
}
public record Booking(UUID id, List<Ship> ships, PaymentMean paymentMean, Boolean finalized) {

	public Booking {
    	if(!finalized){
        	assert ships.stream().noneMatch(ship -> ship.departureDate().isBefore(now())) 
				: "Some ships are departing in the past";
        }
    }

   boolean isFinalized(){/**/}
}

CHAPTER 2

When model sclerosis  
      turns into model

Fragmentation

CRUISING

POST-BOOKING

Text

works around

Sclerosed
Model

Outgrowth
Model

Cruising

Post-Booking

Pursued Lead

Investigative Case

Our respective systems actually form a distributed big ball of mud

POST-BOOKING

CRUISING

Search

Exchange

Cancellation

Search

Booking

Selection

POST-BOOKING

CRUISING

Search

Exchange

Cancellation

Booking

Selection

Search

Selection

Booking

POST-BOOKING

CRUISING

Search

Exchange

Cancellation

Search

Booking

Selection

Selection

Booking

POST-BOOKING

CRUISING

Search

Exchange

Cancellation

Search

Booking

Selection

Selection

Booking

Search

Exchange

Cancellation

noDepartureInThePast()

noDepartureInThePast()

POST-BOOKING

CRUISING

noDepartureInThePast()

noDepartureInThePast()

noScheduleOverlap()

noScheduleOverlap()

POST-BOOKING

CRUISING

Selection

Booking

Search

Exchange

Cancellation

Architectural Tension

Business Logic Leaks

Behaviors, invariants, lifecycles, etc. are scattered across bounded-contexts

Architectural Tension

Business Logic Leaks

POST-BOOKING

CRUISING

noDepartureInThePast()

noDepartureInThePast()

noScheduleOverlap()

noScheduleOverlap()

Booking

Exchange

Selection

Booking

Search

Exchange

Cancellation

Cancellation

Booking

Exchanged
Booking

noDepartureInThePast()

noDepartureInThePast()

noScheduleOverlap()

noScheduleOverlap()

Cancelled
Booking

Selection

Booking

Search

Exchange

Cancellation

POST-BOOKING

CRUISING

Booking

Exchanged
Booking

noDepartureInThePast()

noDepartureInThePast()

noScheduleOverlap()

noScheduleOverlap()

Cancelled
Booking

Completed
Booking

Selection

Booking

Search

Exchange

Cancellation

POST-BOOKING

CRUISING

noDepartureInThePast()

noDepartureInThePast()

noScheduleOverlap()

noScheduleOverlap()

Created

Completed

Exchanged

Cancelled

Selection

Booking

Search

Exchange

Cancellation

POST-BOOKING

CRUISING

Cart

SHOPPING

Order

ORDER

Parcel

DELIVERY

Booking Lifecycle

Created

Completed

Exchanged

Cancelled

POST-BOOKING

CRUISING

Booking Lifecycle

Exchanged

Cancelled

POST-BOOKING

CRUISING

fix ship departing in the past

Created

Completed

Architectural Tension

Fragmented Lifecycle

When separate bounded-contexts handle different states of the same aggregate, while sharing many concepts, personae, and rules.

Architectural Tension

Fragmented Lifecycle

POST-BOOKING

CRUISING

MOBILE APP

Booking

Exchange

Cancellation

Determining current booking status

check booking exists

check if exchange or cancellation exists

Completed

Booking

Created

Completed

Exchanged

Cancelled

POST-BOOKING

CRUISING

MOBILE APP

check if exchanged/cancelled

check booking exists

Determining current booking status

BOOKING

can be both

Architectural Tension

Distributed States

Understanding the state of a concept requires consolidating data from multiple bounded-contexts

Architectural Tension

Distributed States

POST-BOOKING

CRUISING

noDepartureInThePast()

noDepartureInThePast()

noScheduleOverlap()

noScheduleOverlap()

Booking

Exchange

Cancellation

Selection

Booking

Search

Exchange

Cancellation

POST-BOOKING

CRUISING

noDepartureInThePast()

noDepartureInThePast()

noScheduleOverlap()

noScheduleOverlap()

Booking

Exchange

Cancellation

Selection

Booking

Search

Exchange

Cancellation

noDepartureInThePast()

noDepartureInThePast()

noScheduleOverlap()

noScheduleOverlap()

Booking

Exchange

eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nI1WwXLbNlx1MDAxML37KzTqNUWw2Fx1MDAwNbDIrU56yKXTiafTznRyoCVaYkyTXHUwMDFhkorjZvzvfaRcdTAwMTRRVO1hdbAlLPbh7e7bXHUwMDA1vl8tXHUwMDE2y+5ply/fLZb5t1VWXHUwMDE26yZ7XFy+6de/5k1b1Fx1MDAxNUxu+N3W+2Y17Nx23a599/bt6GFW9cPBKy/zh7zqWuz7XHUwMDFiv1x1MDAxN4vvw19YinXv++U6v/3rhp++fGhcdTAwMWWLrdebT9lcdTAwMWafXHUwMDA212HTXHUwMDBmMmVR5ePqNyxcdKlcdTAwMDajkb2N1obAJ+tcdTAwMTOs5JWcIbXsOJKLdLI+XHUwMDE2627b74CT8YnJJ1x1MDAxN9W7OFx1MDAwMmzzYrPtsIdZjWhyNqlcdTAwMGJqddySVZuyJ2ZPK23X1Pf5+7qsm57wT7llYlx1MDAxYTnfZqv7TVPvq/Xre+6KsrzpnspDVrPVdt+cRX044c8jf3exfvJra9Rg9MKRm22Vt+2Ebb3LVkX3dMjDabXnt/u4XHUwMDFlivV5ZNVkXHUwMDBm+ce+WtW+LE/LRbXO+0Isb5t/JsdV6+NxP0o91tFcdTAwMWRXnkfyed4jqziHMvrT+qg2ZuHL5d/qapBcdTAwMWVFXHUwMDE3nNiY4kir/Vx1MDAwMM11XHUwMDAz6l1WtvlYgZ7ar2d6XHUwMDFjQ9zv1tnBhaKoaFRmXHUwMDEyPdkhv/vL+Mt6df/CKbu6OJd7/1x1MDAxOb8txlx1MDAxMlxmP07fP795cTcn41x1MDAxMrlAwslcdTAwMDeb6Nz751x1MDAxNExcdTAwMDBdXHUwMDBiXHUwMDBiTEFkXHUwMDBlTtSQ2OCdXHUwMDE3QKaY/Fx1MDAwNI9cIlx1MDAxOU1cdTAwMTLYojc0OuU5QLJkXHUwMDFjh5RcdTAwMTKpXHUwMDBmnMZKXHUwMDFkXHUwMDAwVYxccjjNxYhcbkeaw3PEhskpXHUwMDFhLiiopilcXFCTlNE0SaOQ1TibP8smhKDOXCJPkdVdXHUwMDA0TN5cYsRcdTAwMTMoWsgopFk8TSaJsorlmJyfhitkOFx1MDAwNMJHJUbHs+FKSIbYXHUwMDA2TFx1MDAxNlEl0JjiReNcdTAwMTGu9ZpQsjRcdTAwMWKtXHUwMDE3b5R9XHUwMDEy21x1MDAwZj6+UEtU45BSdk6QW/WzxVxyYqGvXHUwMDFlXHUwMDA3XHRKYDHNnfeGbITNOzRcdTAwMGJYzuEh0YaVI/6z+kiXWkHpUVxuXHUwMDFjhFlA3oY5PCRcdTAwMDXzXHUwMDFmiUNcdTAwMDKtI1xyUzwnJoq3ySNcdTAwMWKqmPPzYn7tRjhcdTAwMTI0PnhcdTAwMTboXFyciEuzgFx0/YRcdTAwMWVTSdhcdTAwMWODm+DBhk5cdTAwMWKaQygw6SxcdTAwMWF6jZxVSlx1MDAxMTknL+do5PpqeGLvNNggaVx1MDAxNi7GXGKPhEiQoVx1MDAwNDVP4LxcdTAwMThx6Jxoe7WTm9WKS9AqWSRcXFx1MDAxMqWpkMHaQFwiXlLCuKZ55Xmrhq2mZK2ilZgncFxi1VqBjokkoG/jLFx1MDAxZatFYYODUFx1MDAwM0fnJ0pxUCVcbqtOUt+EXHUwMDFh/8dUXHSYQ76XXHUwMDAxcbQ8gcNRuNQtQSr90JFZco7xUFx0jOyhXHUwMDBlooh9mjs1XHUwMDAxQmFFNTxcdTAwMDbz7FBBq2JcbkSrIIdcdTAwMTGP6+NcdTAwMWNcdTAwMGZ3XHUwMDA2Olxml6Z6j7mi811BmFx1MDAwMpg+LkFZYFx1MDAxMya16EfEyI7mb4zX7r+rXHUwMDBir2WZtd37+uGh6HAx/95fqpdcdTAwMTdw22VNd41nSFFtLm15tX7FMnj90jT14zbP/vOogd+rtl1dPm2GJ0nX7PNh9fnqSHmZ7XY3XHUwMDFk3lx1MDAxMKdnz/JrkT9ev/Dou1x1MDAxYj7Lq+MrqH/05cNr6fnq+V/8q0SQIn0=

POST-BOOKING

CRUISING

Fragmented Model

Cancellation

POST-BOOKING

CRUISING

noDepartureInThePast()

noDepartureInThePast()

noScheduleOverlap()

noScheduleOverlap()

Booking

Exchange

eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nI1WwXLbNlx1MDAxML37KzTqNUWw2Fx1MDAwNbDIrU56yKXTiafTznRyoCVaYkyTXHUwMDFhkorjZvzvfaRcdTAwMTRRVO1hdbAlLPbh7e7bXHUwMDA1vl8tXHUwMDE2y+5ply/fLZb5t1VWXHUwMDE26yZ7XFy+6de/5k1b1Fx1MDAxNUxu+N3W+2Y17Nx23a599/bt6GFW9cPBKy/zh7zqWuz7XHUwMDFiv1x1MDAxN4vvw19YinXv++U6v/3rhp++fGhcdTAwMWWLrdebT9lcdTAwMWafXHUwMDA212HTXHUwMDBmMmVR5ePqNyxcdKlcdTAwMDajkb2N1obAJ+tcdTAwMTOs5JWcIbXsOJKLdLI+XHUwMDE2627b74CT8YnJJ1x1MDAxN9W7OFx1MDAwMmzzYrPtsIdZjWhyNqlcdTAwMGJqddySVZuyJ2ZPK23X1Pf5+7qsm57wT7llYlx1MDAxYTnfZqv7TVPvq/Xre+6KsrzpnspDVrPVdt+cRX044c8jf3exfvJra9Rg9MKRm22Vt+2Ebb3LVkX3dMjDabXnt/u4XHUwMDFlivV5ZNVkXHUwMDBm+ce+WtW+LE/LRbXO+0Isb5t/JsdV6+NxP0o91tFcdTAwMWRXnkfyed4jqziHMvrT+qg2ZuHL5d/qapBcdTAwMWVFXHUwMDE3nNiY4kir/Vx1MDAwMM11XHUwMDAz6l1WtvlYgZ7ar2d6XHUwMDFjQ9zv1tnBhaKoaFRmXHUwMDEyPdkhv/vL+Mt6df/CKbu6OJd7/1x1MDAxOb8txlx1MDAxMlxmP07fP795cTcn41x1MDAxMrlAwslcdTAwMDeb6Nz751x1MDAxNExcdTAwMDBdXHUwMDBiXHUwMDBiTEFkXHUwMDBlTtSQ2OCdXHUwMDE3QKaY/Fx1MDAwNI9cIlx1MDAxOU1cdTAwMTLYojc0OuU5QLJkXHUwMDFjh5RcdTAwMTKpXHUwMDBmnMZKXHUwMDFkXHUwMDAwVYxccjjNxYhcbkeaw3PEhskpXHUwMDFhLiiopilcXFCTlNE0SaOQ1TibP8smhKDOXCJPkdVdXHUwMDA0TN5cYsRcdTAwMTMoWsgopFk8TSaJsorlmJyfhitkOFx1MDAwNMJHJUbHs+FKSIbYXHUwMDA2TFx1MDAxNlEl0JjiReNcdTAwMTGu9ZpQsjRcdTAwMWKtXHUwMDE3b5R9XHUwMDEy21x1MDAwZj6+UEtU45BSdk6QW/WzxVxyYqGvXHUwMDFlXHUwMDA3XHRKYDHNnfeGbITNOzRcdTAwMGJYzuEh0YaVI/6z+kiXWkHpUVxuXHUwMDFjhFlA3oY5PCRcdTAwMDXzXHUwMDFmiUNcdTAwMDKtI1xyUzwnJoq3ySNcdTAwMWKqmPPzYn7tRjhcdTAwMTI0PnhcdTAwMTboXFyciEuzgFx0/YRcdTAwMWVTSdhcdTAwMWODm+DBhk5cdTAwMWKaQygw6SxcdTAwMWF6jZxVSlx1MDAxMTknL+do5PpqeGLvNNggaVx1MDAxNi7GXGKPhEiQoVx1MDAwNDVP4LxcdTAwMThx6Jxoe7WTm9WKS9AqWSRcXFx1MDAxMqWpkMHaQFwiXlLCuKZ55Xmrhq2mZK2ilZgncFxi1VqBjokkoG/jLFx1MDAxZatFYYODUFx1MDAwM0fnJ0pxUCVcbqtOUt+EXHUwMDFh/8dUXHSYQ76XXHUwMDAxcbQ8gcNRuNQtQSr90JFZco7xUFx0jOyhXHUwMDBlooh9mjs1XHUwMDAxQmFFNTxcdTAwMDbz7FBBq2JcbkSrIIdcdTAwMTGP6+NcdTAwMWNcdTAwMGZ3XHUwMDA2Olxml6Z6j7mi811BmFx1MDAwMpg+LkFZYFx1MDAxMya16EfEyI7mb4zX7r+rXHUwMDBir2WZtd37+uGh6HAx/95fqpdcdTAwMTdw22VNd41nSFFtLm15tX7FMnj90jT14zbP/vOogd+rtl1dPm2GJ0nX7PNh9fnqSHmZ7XY3XHUwMDFk3lx1MDAxMKdnz/JrkT9ev/Dou1x1MDAxYj7Lq+MrqH/05cNr6fnq+V/8q0SQIn0=

Extrinsic Coupling

eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nI1WTW/bRlx1MDAxML37V1xi6jXd7M7sx0xuddKiuVx1MDAwNC2SXCKHXCJcdTAwMDdGoiXCNCmQVGwh8H/vI62Iolx1MDAxY4PlQVwid2bfzs68+fh+tVgsu8MuX75ZLPOHVVZcdTAwMTbrJrtfvurXv+VNW9RcdTAwMTVENHy39b5ZXHKa267btW9ev1x1MDAxZXeYVX33tCsv87u86lro/YvvxeL78Fx1MDAwYkmx7veG61x1MDAwZvff2j/efb752316+Och/HnY2GHroPTDmLKo8nH1XHUwMDAxS55scMY6XCJOITlcdTAwMTfDSXyA2EUvyTgrXHUwMDFhyHtcdEwn8X2x7ra9irXRXHUwMDA0ZVx1MDAxN5SSXHUwMDA0SnxS2ebFZttBh1mMXHUwMDE3JatCUayMKlm1KXvT7Gml7Zr6Nn9bl3XTm/zLzc1aY1x1MDAxY63+mq1uN029r9Ynna7JqnaXNfDQqHdTlOXH7lA++TZbbffN2d2fTvl8vIO/WD/ta2tEYtyFYzfbKm/bicX1LltcdTAwMTXd4clcdTAwMTen1d7G3fv1XHUwMDEwsi+jVU12l7/vY1bty/K0XFxU67xcdTAwMGbH8mtrJ8dV6+NxP1x1MDAwMj5Gk44rj6Pxed4jO++sXHUwMDBilml088g65vBs+UNdXHJcdTAwMTQki3h7XHUwMDA0UUfD2nfgXjfg3mRlm49x6I37/YyX4yX3u3X2tMUlL15EQVx1MDAwMDcyXHUwMDBiNLy99EBZr25/csquLs5p3z/j22JcZsLwcXr/8uqn2qyG1FF0njVEq+58969cdTAwMWFNhLlcdTAwMTZcdTAwMTKI4Ig5OC/GeVx1MDAxYlx1MDAwM1x1MDAwNVx1MDAwZkhNXHUwMDFhJnguOSPqI1tkiCRcdTAwMTKeXHUwMDAzRNhcZnFUVSchsnqeXHUwMDAyijc24jRKSfDj5vDIsWFHgrSLXHUwMDAyU3Vcblx1MDAxN8WosGWnkkBcdTAwMTlJs/6zbGKMQlx1MDAxNn5KLHRxYVx1MDAxN4xPmqJLluBcdTAwMTidxVx1MDAxMzXqhcVbTkphel3vXGbH6PCIT4l49ro+qnFsI+pcdTAwMGI452DGXHUwMDE0L5mA69rQXHUwMDE3s6Czt1xyPlx1MDAxOOGg3jqxzFx1MDAxN2xJYlxiLmVcIlx1MDAwZt+iMs7BRW/Br1x1MDAxZVx1MDAwN1x1MDAwZVJYMfVdXGIos1x0skDMqCNhXHUwMDBlXHUwMDBmjjYsnPDPgtJ9yVx1MDAxNYRcdTAwMWWhwEGeXGLVIM7hwSlcdTAwMDY8XHUwMDEwgVx1MDAwMy05iVM88ib5YDXAXHUwMDFiXCKo9vNkfqkvXHUwMDFjXHI0IVx1MDAwNvbguUdrIZ1cdTAwMDVU5Fx1MDAxM3JMvEI5RZrgQYZMXHUwMDFiksO7yE5m0ZBrjqw4TfC5XHUwMDBi/lx1MDAxY81RXHUwMDFmjeA4kERcdTAwMWK9zsKl1LdJxU3gIVx1MDAwNZsncMFcdTAwMWJPyJxke7Y7muVcbim46ixcdTAwMWPu1emUyLDagFwiwatSRGhnmVx1MDAxN6xcdTAwMThGXHUwMDBiV2tcdTAwMDWpxDyBw1Wt9eCxcz5cIm/TLFx1MDAxZYtFYCNGXHUwMDA2jpwoTJhCYCVcdTAwMDIr5LVPQkn/o6pE1KHQ08BxsjyBw1GMnMZcXMJ90fGzxlx1MDAxMZNcdTAwMDFcdTAwMDHgPcRcdTAwMDFcdTAwMTOLlanvxERcdTAwMTCFXHUwMDA10VxiKMyzRVx1MDAwNamKKpCswDiUeLSPczz0XGZkWCRcdTAwMWNcdTAwMTRQV2Q+K1x1MDAxY6pcdTAwMDCqXHUwMDBmKZhcdTAwMDVr4iRcdTAwMTZ9iVx1MDAxOK1z81x1MDAxZOOl/nd1sWtZZm33tr67Kzo05r/6pnrZgNsua7prXGZcIkW1uZTl1fpcdTAwMDXJsOu3pqnvt3n2bKzBvlx1MDAxN2W7ujxshpGka/b5sPp4dTR5me12XHUwMDFmO8xcdTAwMTCnwWf5rcjvr5+Pflx1MDAxOFx1MDAwZvtneXWcg/qxL1x1MDAxZualx6vH/1x1MDAwMIt/SH0ifQ==

Cancellation

POST-BOOKING

CRUISING

Feature Change

Remediation

breaks logic in

Architectural Tension

Frequent
Breaking Changes

Every model evolution breaks collaborating bounded-contexts.

Architectural Tension

Frequent
Breaking Changes

Investigative Case

Architectural Tensions

Business Logic leaks

Fragmented Lifecycle

Distributed States

Frequent
Breaking Changes

noDepartureInThePast()

noDepartureInThePast()

noScheduleOverlap()

noScheduleOverlap()

eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nI1WwXLbNlx1MDAxML37KzTqNUWw2Fx1MDAwNbDIrU56yKXTiafTznRyoCVaYkyTXHUwMDFhkorjZvzvfaRcdTAwMTRRVO1hdbAlLPbh7e7bXHUwMDA1vl8tXHUwMDE2y+5ply/fLZb5t1VWXHUwMDE26yZ7XFy+6de/5k1b1Fx1MDAxNUxu+N3W+2Y17Nx23a599/bt6GFW9cPBKy/zh7zqWuz7XHUwMDFiv1x1MDAxN4vvw19YinXv++U6v/3rhp++fGhcdTAwMWWLrdebT9lcdTAwMWafXHUwMDA212HTXHUwMDBmMmVR5ePqNyxcdKlcdTAwMDajkb2N1obAJ+tcdTAwMTOs5JWcIbXsOJKLdLI+XHUwMDE2627b74CT8YnJJ1x1MDAxN9W7OFx1MDAwMmzzYrPtsIdZjWhyNqlcdTAwMGJqddySVZuyJ2ZPK23X1Pf5+7qsm57wT7llYlx1MDAxYTnfZqv7TVPvq/Xre+6KsrzpnspDVrPVdt+cRX044c8jf3exfvJra9Rg9MKRm22Vt+2Ebb3LVkX3dMjDabXnt/u4XHUwMDFlivV5ZNVkXHUwMDBm+ce+WtW+LE/LRbXO+0Isb5t/JsdV6+NxP0o91tFcdTAwMWRXnkfyed4jqziHMvrT+qg2ZuHL5d/qapBcdTAwMWVFXHUwMDE3nNiY4kir/Vx1MDAwMM11XHUwMDAz6l1WtvlYgZ7ar2d6XHUwMDFjQ9zv1tnBhaKoaFRmXHUwMDEyPdkhv/vL+Mt6df/CKbu6OJd7/1x1MDAxOb8txlx1MDAxMlxmP07fP795cTcn41x1MDAxMrlAwslcdTAwMDeb6Nz751x1MDAxNExcdTAwMDBdXHUwMDBiXHUwMDBiTEFkXHUwMDBlTtSQ2OCdXHUwMDE3QKaY/Fx1MDAwNI9cIlx1MDAxOU1cdTAwMTLYojc0OuU5QLJkXHUwMDFjh5RcdTAwMTKpXHUwMDBmnMZKXHUwMDFkXHUwMDAwVYxccjjNxYhcbkeaw3PEhskpXHUwMDFhLiiopilcXFCTlNE0SaOQ1TibP8smhKDOXCJPkdVdXHUwMDA0TN5cYsRcdTAwMTMoWsgopFk8TSaJsorlmJyfhitkOFx1MDAwNMJHJUbHs+FKSIbYXHUwMDA2TFx1MDAxNlEl0JjiReNcdTAwMTGu9ZpQsjRcdTAwMWKtXHUwMDE3b5R9XHUwMDEy21x1MDAwZj6+UEtU45BSdk6QW/WzxVxyYqGvXHUwMDFlXHUwMDA3XHRKYDHNnfeGbITNOzRcdTAwMGJYzuEh0YaVI/6z+kiXWkHpUVxuXHUwMDFjhFlA3oY5PCRcdTAwMDXzXHUwMDFmiUNcdTAwMDKtI1xyUzwnJoq3ySNcdTAwMWKqmPPzYn7tRjhcdTAwMTI0PnhcdTAwMTboXFyciEuzgFx0/YRcdTAwMWVTSdhcdTAwMWODm+DBhk5cdTAwMWKaQygw6SxcdTAwMWF6jZxVSlx1MDAxMTknL+do5PpqeGLvNNggaVx1MDAxNi7GXGKPhEiQoVx1MDAwNDVP4LxcdTAwMThx6Jxoe7WTm9WKS9AqWSRcXFx1MDAxMqWpkMHaQFwiXlLCuKZ55Xmrhq2mZK2ilZgncFxi1VqBjokkoG/jLFx1MDAxZatFYYODUFx1MDAwM0fnJ0pxUCVcbqtOUt+EXHUwMDFh/8dUXHSYQ76XXHUwMDAxcbQ8gcNRuNQtQSr90JFZco7xUFx0jOyhXHUwMDBlooh9mjs1XHUwMDAxQmFFNTxcdTAwMDbz7FBBq2JcbkSrIIdcdTAwMTGP6+NcdTAwMWNcdTAwMGZ3XHUwMDA2Olxml6Z6j7mi811BmFx1MDAwMpg+LkFZYFx1MDAxMya16EfEyI7mb4zX7r+rXHUwMDBir2WZtd37+uGh6HAx/95fqpdcdTAwMTdw22VNd41nSFFtLm15tX7FMnj90jT14zbP/vOogd+rtl1dPm2GJ0nX7PNh9fnqSHmZ7XY3XHUwMDFk3lx1MDAxMKdnz/JrkT9ev/Dou1x1MDAxYj7Lq+MrqH/05cNr6fnq+V/8q0SQIn0=

Extrinsic Coupling

Model fragmentation (extrinsic coupling):
the insidious builder of distributed BBOMs

Text

Sclerosed
Model

Cruising

works around

Outgrowth
Model

Post-Booking

Sclerosed
Model

Outgrowth
Model

works around

Model
Fragmentation

becomes a fragment of

is a fragment of

causes

Extrinsic
Coupling

Cruising

Post-Booking

Business
Logic Leak

favorises

induces

exacerbates

is a form of

Extrinsic
Coupling

Outgrowth
Model

Model
Fragmentation

Synced
Evolutions

Model
Fragmentation

Extrinsic
Coupling

is a form of

contrains

systems to

Synced
Evolution

results in

Synced
Failures

leads to

System
Entropy

raises

binds the fragments into

Distributed
BBOM

entangles


into

crystallizes


into

Fragmented
Model
Rigidity

causes

Fragmented
Model
Fragility

Governing Constraint

Synced Evolutions

Governing Constraint

Compensations
System

Pursued Lead

Investigative Case

Our processes and organization are constrained to compensate for the synchronized evolution of the fragmented model

POST-BOOKING

CRUISING

Booking

Release 463

Release 52

POST-BOOKING

CRUISING

ignores

Release 464

Release 52

Booking

Insurance
Policy

Insurance
Policy

Cancellation

POST-BOOKING

CRUISING

ignores

Release 464

Release 52

Booking

Insurance
Policy

Insurance
Policy

Incompatible

Cancellation

POST-BOOKING

CRUISING

Insurance
Policy

Release 464

Release 53

Deploy Together

Booking

Insurance
Policy

Insurance
Policy

Cancellation

Process Tension

Synchronized Releases

Necessity to synchronize heavily around releases and model evolutions across systems

Process Tension

Synchronized Releases

Organizational Tension

Inter-Team

Work Coupling

Teams need to constantly synchronize their plans and priorities despite their scope of autonomy

Organizational Tension

Inter-Team Work Coupling

Investigative Case

Synchronized

Evolutions

noDepartureInThePast()

noDepartureInThePast()

noScheduleOverlap()

noScheduleOverlap()

eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nI1WwXLbNlx1MDAxML37KzTqNUWw2Fx1MDAwNbDIrU56yKXTiafTznRyoCVaYkyTXHUwMDFhkorjZvzvfaRcdTAwMTRRVO1hdbAlLPbh7e7bXHUwMDA1vl8tXHUwMDE2y+5ply/fLZb5t1VWXHUwMDE26yZ7XFy+6de/5k1b1Fx1MDAxNUxu+N3W+2Y17Nx23a599/bt6GFW9cPBKy/zh7zqWuz7XHUwMDFiv1x1MDAxN4vvw19YinXv++U6v/3rhp++fGhcdTAwMWWLrdebT9lcdTAwMWafXHUwMDA212HTXHUwMDBmMmVR5ePqNyxcdKlcdTAwMDajkb2N1obAJ+tcdTAwMTOs5JWcIbXsOJKLdLI+XHUwMDE2627b74CT8YnJJ1x1MDAxN9W7OFx1MDAwMmzzYrPtsIdZjWhyNqlcdTAwMGJqddySVZuyJ2ZPK23X1Pf5+7qsm57wT7llYlx1MDAxYTnfZqv7TVPvq/Xre+6KsrzpnspDVrPVdt+cRX044c8jf3exfvJra9Rg9MKRm22Vt+2Ebb3LVkX3dMjDabXnt/u4XHUwMDFlivV5ZNVkXHUwMDBm+ce+WtW+LE/LRbXO+0Isb5t/JsdV6+NxP0o91tFcdTAwMWRXnkfyed4jqziHMvrT+qg2ZuHL5d/qapBcdTAwMWVFXHUwMDE3nNiY4kir/Vx1MDAwMM11XHUwMDAz6l1WtvlYgZ7ar2d6XHUwMDFjQ9zv1tnBhaKoaFRmXHUwMDEyPdkhv/vL+Mt6df/CKbu6OJd7/1x1MDAxOb8txlx1MDAxMlxmP07fP795cTcn41x1MDAxMrlAwslcdTAwMDeb6Nz751x1MDAxNExcdTAwMDBdXHUwMDBiXHUwMDBiTEFkXHUwMDBlTtSQ2OCdXHUwMDE3QKaY/Fx1MDAwNI9cIlx1MDAxOU1cdTAwMTLYojc0OuU5QLJkXHUwMDFjh5RcdTAwMTKpXHUwMDBmnMZKXHUwMDFkXHUwMDAwVYxccjjNxYhcbkeaw3PEhskpXHUwMDFhLiiopilcXFCTlNE0SaOQ1TibP8smhKDOXCJPkdVdXHUwMDA0TN5cYsRcdTAwMTMoWsgopFk8TSaJsorlmJyfhitkOFx1MDAwNMJHJUbHs+FKSIbYXHUwMDA2TFx1MDAxNlEl0JjiReNcdTAwMTGu9ZpQsjRcdTAwMWKtXHUwMDE3b5R9XHUwMDEy21x1MDAwZj6+UEtU45BSdk6QW/WzxVxyYqGvXHUwMDFlXHUwMDA3XHRKYDHNnfeGbITNOzRcdTAwMGJYzuEh0YaVI/6z+kiXWkHpUVxuXHUwMDFjhFlA3oY5PCRcdTAwMDXzXHUwMDFmiUNcdTAwMDKtI1xyUzwnJoq3ySNcdTAwMWKqmPPzYn7tRjhcdTAwMTI0PnhcdTAwMTboXFyciEuzgFx0/YRcdTAwMWVTSdhcdTAwMWODm+DBhk5cdTAwMWKaQygw6SxcdTAwMWF6jZxVSlx1MDAxMTknL+do5PpqeGLvNNggaVx1MDAxNi7GXGKPhEiQoVx1MDAwNDVP4LxcdTAwMThx6Jxoe7WTm9WKS9AqWSRcXFx1MDAxMqWpkMHaQFwiXlLCuKZ55Xmrhq2mZK2ilZgncFxi1VqBjokkoG/jLFx1MDAxZatFYYODUFx1MDAwM0fnJ0pxUCVcbqtOUt+EXHUwMDFh/8dUXHSYQ76XXHUwMDAxcbQ8gcNRuNQtQSr90JFZco7xUFx0jOyhXHUwMDBlooh9mjs1XHUwMDAxQmFFNTxcdTAwMDbz7FBBq2JcbkSrIIdcdTAwMTGP6+NcdTAwMWNcdTAwMGZ3XHUwMDA2Olxml6Z6j7mi811BmFx1MDAwMpg+LkFZYFx1MDAxMya16EfEyI7mb4zX7r+rXHUwMDBir2WZtd37+uGh6HAx/95fqpdcdTAwMTdw22VNd41nSFFtLm15tX7FMnj90jT14zbP/vOogd+rtl1dPm2GJ0nX7PNh9fnqSHmZ7XY3XHUwMDFk3lx1MDAxMKdnz/JrkT9ev/Dou1x1MDAxYj7Lq+MrqH/05cNr6fnq+V/8q0SQIn0=

Model Fragmentation

Process Tension

Synchronized
Releases

Org. Tension

InterTeam
Work
Coupling

Governing

Constraint

POST-BOOKING

CRUISING

Release 465

Release 57

Incompatible

Special Meal

POST-BOOKING

CRUISING

Release 465

Release 57

Compatible

Special Meal

Toggle: OFF

POST-BOOKING

CRUISING

Release 465

Release 58

Compatible

Toggle: OFF

Toggle: OFF

Special Meal

Special Meal

POST-BOOKING

CRUISING

Release 465

Release 58

Toggle: ON

Toggle: ON

Special Meal

Special Meal

Compatible

Process Tension

Band-aid Processes

Unresolved design problems are compensated by processes such as multi-versioning, double run, feature flags to limit impact on another team

Process Tension

Band-aid Processes

POST-BOOKING

CRUISING

Special Meal

Special Meal

Interface

Toggle: OFF

Toggle: OFF

R

T

E

POST-BOOKING

CRUISING

Special Meal

ready?

Special Meal

Interface

ready?

Toggle: OFF

Toggle: OFF

R

T

E

POST-BOOKING

CRUISING

Special Meal

ready?

Special Meal

Interface

ready?

Toggle: OFF

Toggle: OFF

R

T

E

POST-BOOKING

CRUISING

Special Meal

ready?

Special Meal

Interface

ready?

Toggle: OFF

Toggle: OFF

Readiness

Toggle

Engineer

Organizational Tension

Palliative Roles

When the growing complexity of band-aid processes and ceremonies requires a full-time job

Organizational Tension

Palliative Roles

Extrinsic
Coupling

leads to

Synchronized
Releases

leads to

InterTeam
Work Coupling

Extrinsic
Coupling

Synchronized
Releases

InterTeam
Work Coupling

leads to

leads to

buffered by

buffered by

Palliative Roles

handled by

Band-aid processes

Extrinsic
Coupling

leads to

leads to

buffered by

buffered by

offset

offset

Synchronized
Releases

InterTeam
Work Coupling

Palliative Roles

handled by

Compensatory
Counter Measures

Band-aid processes

Extrinsic
Coupling

Tests Envs Proliferations

Synced
plannings
& backlogs

Feature Flags
Overuse

Multi
Versionning

Shared & Distributed
DataSets

leads to

leads to

buffered by

buffered by

offset

offset

never address

Compensatory
Counter Measures

Synchronized
Releases

InterTeam
Work Coupling

Extrinsic
Coupling

Tests Envs Proliferations

Synced
plannings
& backlogs

Feature Flags
Overuse

Multi
Versionning

Shared & Distributed
DataSets

leads to

leads to

buffered by

buffered by

offset

offset

never address

Compensatory
Counter Measures

Synchronized
Releases

InterTeam
Work Coupling

Tension Crystallization

Tension Crystallization

Tests Envs Proliferations

Synced
plannings
& backlogs

Feature Flags
Overuse

Multi
Versionning

Shared & Distributed
DataSets

leads to

leads to

buffered by

buffered by

offset

offset

never address

Compensatory
Counter Measures

Compensations
System

Tension Crystallization

Tension Crystallization

Extrinsic
Coupling

Synchronized
Releases

InterTeam
Work Coupling

Investigative Case

eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nI1WwXLbNlx1MDAxML37KzTqNUWw2Fx1MDAwNbDIrU56yKXTiafTznRyoCVaYkyTXHUwMDFhkorjZvzvfaRcdTAwMTRRVO1hdbAlLPbh7e7bXHUwMDA1vl8tXHUwMDE2y+5ply/fLZb5t1VWXHUwMDE26yZ7XFy+6de/5k1b1Fx1MDAxNUxu+N3W+2Y17Nx23a599/bt6GFW9cPBKy/zh7zqWuz7XHUwMDFiv1x1MDAxN4vvw19YinXv++U6v/3rhp++fGhcdTAwMWWLrdebT9lcdTAwMWafXHUwMDA212HTXHUwMDBmMmVR5ePqNyxcdKlcdTAwMDajkb2N1obAJ+tcdTAwMTOs5JWcIbXsOJKLdLI+XHUwMDE2627b74CT8YnJJ1x1MDAxN9W7OFx1MDAwMmzzYrPtsIdZjWhyNqlcdTAwMGJqddySVZuyJ2ZPK23X1Pf5+7qsm57wT7llYlx1MDAxYTnfZqv7TVPvq/Xre+6KsrzpnspDVrPVdt+cRX044c8jf3exfvJra9Rg9MKRm22Vt+2Ebb3LVkX3dMjDabXnt/u4XHUwMDFlivV5ZNVkXHUwMDBm+ce+WtW+LE/LRbXO+0Isb5t/JsdV6+NxP0o91tFcdTAwMWRXnkfyed4jqziHMvrT+qg2ZuHL5d/qapBcdTAwMWVFXHUwMDE3nNiY4kir/Vx1MDAwMM11XHUwMDAz6l1WtvlYgZ7ar2d6XHUwMDFjQ9zv1tnBhaKoaFRmXHUwMDEyPdkhv/vL+Mt6df/CKbu6OJd7/1x1MDAxOb8txlx1MDAxMlxmP07fP795cTcn41x1MDAxMrlAwslcdTAwMDeb6Nz751x1MDAxNExcdTAwMDBdXHUwMDBiXHUwMDBiTEFkXHUwMDBlTtSQ2OCdXHUwMDE3QKaY/Fx1MDAwNI9cIlx1MDAxOU1cdTAwMTLYojc0OuU5QLJkXHUwMDFjh5RcdTAwMTKpXHUwMDBmnMZKXHUwMDFkXHUwMDAwVYxccjjNxYhcbkeaw3PEhskpXHUwMDFhLiiopilcXFCTlNE0SaOQ1TibP8smhKDOXCJPkdVdXHUwMDA0TN5cYsRcdTAwMTMoWsgopFk8TSaJsorlmJyfhitkOFx1MDAwNMJHJUbHs+FKSIbYXHUwMDA2TFx1MDAxNlEl0JjiReNcdTAwMTGu9ZpQsjRcdTAwMWKtXHUwMDE3b5R9XHUwMDEy21x1MDAwZj6+UEtU45BSdk6QW/WzxVxyYqGvXHUwMDFlXHUwMDA3XHRKYDHNnfeGbITNOzRcdTAwMGJYzuEh0YaVI/6z+kiXWkHpUVxuXHUwMDFjhFlA3oY5PCRcdTAwMDXzXHUwMDFmiUNcdTAwMDKtI1xyUzwnJoq3ySNcdTAwMWKqmPPzYn7tRjhcdTAwMTI0PnhcdTAwMTboXFyciEuzgFx0/YRcdTAwMWVTSdhcdTAwMWODm+DBhk5cdTAwMWKaQygw6SxcdTAwMWF6jZxVSlx1MDAxMTknL+do5PpqeGLvNNggaVx1MDAxNi7GXGKPhEiQoVx1MDAwNDVP4LxcdTAwMThx6Jxoe7WTm9WKS9AqWSRcXFx1MDAxMqWpkMHaQFwiXlLCuKZ55Xmrhq2mZK2ilZgncFxi1VqBjokkoG/jLFx1MDAxZatFYYODUFx1MDAwM0fnJ0pxUCVcbqtOUt+EXHUwMDFh/8dUXHSYQ76XXHUwMDAxcbQ8gcNRuNQtQSr90JFZco7xUFx0jOyhXHUwMDBlooh9mjs1XHUwMDAxQmFFNTxcdTAwMDbz7FBBq2JcbkSrIIdcdTAwMTGP6+NcdTAwMWNcdTAwMGZ3XHUwMDA2Olxml6Z6j7mi811BmFx1MDAwMpg+LkFZYFx1MDAxMya16EfEyI7mb4zX7r+rXHUwMDBir2WZtd37+uGh6HAx/95fqpdcdTAwMTdw22VNd41nSFFtLm15tX7FMnj90jT14zbP/vOogd+rtl1dPm2GJ0nX7PNh9fnqSHmZ7XY3XHUwMDFk3lx1MDAxMKdnz/JrkT9ev/Dou1x1MDAxYj7Lq+MrqH/05cNr6fnq+V/8q0SQIn0=

noDepartureInThePast()

noDepartureInThePast()

noScheduleOverlap()

noScheduleOverlap()

Model Fragmentation

Process Tension

Compensatory Countermeasures

Compensations

System

Org. Tension

Band-Aid
Processes

Palliative
Roles

Synced

Evolutions

GoverningConstraint

Crystallized

Extrinsic Model Tensions

Socio-Technical
Entropy

Pursued Lead

Investigative Case

Our extrinsic coupling manifests as organizational dysfunction

Booking

Exchange

POST-BOOKING

CRUISING

Cancellation

Seat Preferences

Seat Preferences

Update Booking?

Create Exchange?

Organizational Tension

Unclear

Ownership

Organizational Tension

Unclear Ownership

When a need for feature debugging or development arises, debates often break out to determinate which team should be in charge

Bug

Ships departing in the past are bookable

ToDo

Bug

ToDo

Cruising BackLog

Ships departing in the past are bookable

Post-Booking BackLog

Bug

Ships departing in the past are bookable

Cruising BackLog

ToDo

Bug

Ships departing in the past are bookable

In Progress

Organizational Tension

Backlog Takeover

When the work of a stream-aligned team is systematically on the critical path of another team

Organizational Tension

Backlog Takeover

Investigative

Model Fragmentation

GoverningConstraint

Synced

Evolutions

Synchronized
Releases

InterTeam
Work Coupling

Crystallized Model Tensions

Compensatory
Countermeasures

Compensations
Systems

Band-Aid
Processes & ORg

Case

eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nI1WwXLbNlx1MDAxML37KzTqNUWw2Fx1MDAwNbDIrU56yKXTiafTznRyoCVaYkyTXHUwMDFhkorjZvzvfaRcdTAwMTRRVO1hdbAlLPbh7e7bXHUwMDA1vl8tXHUwMDE2y+5ply/fLZb5t1VWXHUwMDE26yZ7XFy+6de/5k1b1Fx1MDAxNUxu+N3W+2Y17Nx23a599/bt6GFW9cPBKy/zh7zqWuz7XHUwMDFiv1x1MDAxN4vvw19YinXv++U6v/3rhp++fGhcdTAwMWWLrdebT9lcdTAwMWafXHUwMDA212HTXHUwMDBmMmVR5ePqNyxcdKlcdTAwMDajkb2N1obAJ+tcdTAwMTOs5JWcIbXsOJKLdLI+XHUwMDE2627b74CT8YnJJ1x1MDAxN9W7OFx1MDAwMmzzYrPtsIdZjWhyNqlcdTAwMGJqddySVZuyJ2ZPK23X1Pf5+7qsm57wT7llYlx1MDAxYTnfZqv7TVPvq/Xre+6KsrzpnspDVrPVdt+cRX044c8jf3exfvJra9Rg9MKRm22Vt+2Ebb3LVkX3dMjDabXnt/u4XHUwMDFlivV5ZNVkXHUwMDBm+ce+WtW+LE/LRbXO+0Isb5t/JsdV6+NxP0o91tFcdTAwMWRXnkfyed4jqziHMvrT+qg2ZuHL5d/qapBcdTAwMWVFXHUwMDE3nNiY4kir/Vx1MDAwMM11XHUwMDAz6l1WtvlYgZ7ar2d6XHUwMDFjQ9zv1tnBhaKoaFRmXHUwMDEyPdkhv/vL+Mt6df/CKbu6OJd7/1x1MDAxOb8txlx1MDAxMlxmP07fP795cTcn41x1MDAxMrlAwslcdTAwMDeb6Nz751x1MDAxNExcdTAwMDBdXHUwMDBiXHUwMDBiTEFkXHUwMDBlTtSQ2OCdXHUwMDE3QKaY/Fx1MDAwNI9cIlx1MDAxOU1cdTAwMTLYojc0OuU5QLJkXHUwMDFjh5RcdTAwMTKpXHUwMDBmnMZKXHUwMDFkXHUwMDAwVYxccjjNxYhcbkeaw3PEhskpXHUwMDFhLiiopilcXFCTlNE0SaOQ1TibP8smhKDOXCJPkdVdXHUwMDA0TN5cYsRcdTAwMTMoWsgopFk8TSaJsorlmJyfhitkOFx1MDAwNMJHJUbHs+FKSIbYXHUwMDA2TFx1MDAxNlEl0JjiReNcdTAwMTGu9ZpQsjRcdTAwMWKtXHUwMDE3b5R9XHUwMDEy21x1MDAwZj6+UEtU45BSdk6QW/WzxVxyYqGvXHUwMDFlXHUwMDA3XHRKYDHNnfeGbITNOzRcdTAwMGJYzuEh0YaVI/6z+kiXWkHpUVxuXHUwMDFjhFlA3oY5PCRcdTAwMDXzXHUwMDFmiUNcdTAwMDKtI1xyUzwnJoq3ySNcdTAwMWKqmPPzYn7tRjhcdTAwMTI0PnhcdTAwMTboXFyciEuzgFx0/YRcdTAwMWVTSdhcdTAwMWODm+DBhk5cdTAwMWKaQygw6SxcdTAwMWF6jZxVSlx1MDAxMTknL+do5PpqeGLvNNggaVx1MDAxNi7GXGKPhEiQoVx1MDAwNDVP4LxcdTAwMThx6Jxoe7WTm9WKS9AqWSRcXFx1MDAxMqWpkMHaQFwiXlLCuKZ55Xmrhq2mZK2ilZgncFxi1VqBjokkoG/jLFx1MDAxZatFYYODUFx1MDAwM0fnJ0pxUCVcbqtOUt+EXHUwMDFh/8dUXHSYQ76XXHUwMDAxcbQ8gcNRuNQtQSr90JFZco7xUFx0jOyhXHUwMDBlooh9mjs1XHUwMDAxQmFFNTxcdTAwMDbz7FBBq2JcbkSrIIdcdTAwMTGP6+NcdTAwMWNcdTAwMGZ3XHUwMDA2Olxml6Z6j7mi811BmFx1MDAwMpg+LkFZYFx1MDAxMya16EfEyI7mb4zX7r+rXHUwMDBir2WZtd37+uGh6HAx/95fqpdcdTAwMTdw22VNd41nSFFtLm15tX7FMnj90jT14zbP/vOogd+rtl1dPm2GJ0nX7PNh9fnqSHmZ7XY3XHUwMDFk3lx1MDAxMKdnz/JrkT9ev/Dou1x1MDAxYj7Lq+MrqH/05cNr6fnq+V/8q0SQIn0=

noDepartureInThePast()

noDepartureInThePast()

noScheduleOverlap()

noScheduleOverlap()

Organizational
Fragmentation

Unclear
Ownership

Org. Tension

Backlog
TakeOver

Org. Tension

Catalyst

Model
Fragmentation

Organizational
Fragmentation

Synced
Evolution

Process
overhead

Socio-technical system entropy

Results

???

Business Tension

Business Capability Discrepancy

Business Tension

Business Capability Discrepancy

A capability varies in scope, maturity, or behavior across the system, causing gaps and inconsistencies.

Business
Impact

Socio-technical system entropy

Model
Fragmentation

Organizational
Fragmentation

Synced
Evolution

Process
overhead

Interpretation

Sclerosed
Model

Outgrowth
Model

Sclerosed
Model

works around

Outgrowth
Model

Historical
Team

New Team

offloads the
 


work of 

Historical
Team

Sclerosed
Model

works around

Outgrowth
Model

offloads the
 


work of 

New Team

Sclerosed
Model

works around

Outgrowth
Model

Organizational
Fragmentation

Historical
Team

New Team

Sclerosed
Model

Organizational
Fragmentation

Historical
Team

New Team

Model
Fragmentation

Conway's Law

Outgrowth
Model

Conway's Law

Organizations produce systems that mirror their communication structure.

Management unconciously design the architecture of the system via organizational decision

Organizational Shadow Design

Organizational Tension

Sclerosed
Model

Organizational
Fragmentation

Historical
Team

New Team

Model
Fragmentation

Conway's Law

Outgrowth
Model

Historical
Team

Sclerosed
Model

works around

Outgrowth
Model

offloads the
 


work of 

New Team

The organization will charge you interest on your design debt!

Extrinsic coupling signals are mainly socio-technical

Structure eats Strategy

Jan Bosch - 2017

B.A.P.O Model

Organizational Tensions

produce

Architectural
Tensions

structure

Process
Tensions

compensate

Business

Tensions

reflects as

Extrinsic coupling Signals are mainly socio-technical

Intrinsic Coupling

Model Tension
Heuristics

Model
Tension

spot

prevents

Model
Entropy

Extrinsic Coupling

Model
Tension

Model Tension
Heuristics

spot

Socio-Technical
Entropy

prevents

Conclusion

Build a Case!

Why ???

How !?!

Detect signals

across
the sociotech system

Highlight
Extrinsic Coupling

eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nI1WwXLbNlx1MDAxML37KzTqNUWw2Fx1MDAwNbDIrU56yKXTiafTznRyoCVaYkyTXHUwMDFhkorjZvzvfaRcdTAwMTRRVO1hdbAlLPbh7e7bXHUwMDA1vl8tXHUwMDE2y+5ply/fLZb5t1VWXHUwMDE26yZ7XFy+6de/5k1b1Fx1MDAxNUxu+N3W+2Y17Nx23a599/bt6GFW9cPBKy/zh7zqWuz7XHUwMDFiv1x1MDAxN4vvw19YinXv++U6v/3rhp++fGhcdTAwMWWLrdebT9lcdTAwMWafXHUwMDA212HTXHUwMDBmMmVR5ePqNyxcdKlcdTAwMDajkb2N1obAJ+tcdTAwMTOs5JWcIbXsOJKLdLI+XHUwMDE2627b74CT8YnJJ1x1MDAxN9W7OFx1MDAwMmzzYrPtsIdZjWhyNqlcdTAwMGJqddySVZuyJ2ZPK23X1Pf5+7qsm57wT7llYlx1MDAxYTnfZqv7TVPvq/Xre+6KsrzpnspDVrPVdt+cRX044c8jf3exfvJra9Rg9MKRm22Vt+2Ebb3LVkX3dMjDabXnt/u4XHUwMDFlivV5ZNVkXHUwMDBm+ce+WtW+LE/LRbXO+0Isb5t/JsdV6+NxP0o91tFcdTAwMWRXnkfyed4jqziHMvrT+qg2ZuHL5d/qapBcdTAwMWVFXHUwMDE3nNiY4kir/Vx1MDAwMM11XHUwMDAz6l1WtvlYgZ7ar2d6XHUwMDFjQ9zv1tnBhaKoaFRmXHUwMDEyPdkhv/vL+Mt6df/CKbu6OJd7/1x1MDAxOb8txlx1MDAxMlxmP07fP795cTcn41x1MDAxMrlAwslcdTAwMDeb6Nz751x1MDAxNExcdTAwMDBdXHUwMDBiXHUwMDBiTEFkXHUwMDBlTtSQ2OCdXHUwMDE3QKaY/Fx1MDAwNI9cIlx1MDAxOU1cdTAwMTLYojc0OuU5QLJkXHUwMDFjh5RcdTAwMTKpXHUwMDBmnMZKXHUwMDFkXHUwMDAwVYxccjjNxYhcbkeaw3PEhskpXHUwMDFhLiiopilcXFCTlNE0SaOQ1TibP8smhKDOXCJPkdVdXHUwMDA0TN5cYsRcdTAwMTMoWsgopFk8TSaJsorlmJyfhitkOFx1MDAwNMJHJUbHs+FKSIbYXHUwMDA2TFx1MDAxNlEl0JjiReNcdTAwMTGu9ZpQsjRcdTAwMWKtXHUwMDE3b5R9XHUwMDEy21x1MDAwZj6+UEtU45BSdk6QW/WzxVxyYqGvXHUwMDFlXHUwMDA3XHRKYDHNnfeGbITNOzRcdTAwMGJYzuEh0YaVI/6z+kiXWkHpUVxuXHUwMDFjhFlA3oY5PCRcdTAwMDXzXHUwMDFmiUNcdTAwMDKtI1xyUzwnJoq3ySNcdTAwMWKqmPPzYn7tRjhcdTAwMTI0PnhcdTAwMTboXFyciEuzgFx0/YRcdTAwMWVTSdhcdTAwMWODm+DBhk5cdTAwMWKaQygw6SxcdTAwMWF6jZxVSlx1MDAxMTknL+do5PpqeGLvNNggaVx1MDAxNi7GXGKPhEiQoVx1MDAwNDVP4LxcdTAwMThx6Jxoe7WTm9WKS9AqWSRcXFx1MDAxMqWpkMHaQFwiXlLCuKZ55Xmrhq2mZK2ilZgncFxi1VqBjokkoG/jLFx1MDAxZatFYYODUFx1MDAwM0fnJ0pxUCVcbqtOUt+EXHUwMDFh/8dUXHSYQ76XXHUwMDAxcbQ8gcNRuNQtQSr90JFZco7xUFx0jOyhXHUwMDBlooh9mjs1XHUwMDAxQmFFNTxcdTAwMDbz7FBBq2JcbkSrIIdcdTAwMTGP6+NcdTAwMWNcdTAwMGZ3XHUwMDA2Olxml6Z6j7mi811BmFx1MDAwMpg+LkFZYFx1MDAxMya16EfEyI7mb4zX7r+rXHUwMDBir2WZtd37+uGh6HAx/95fqpdcdTAwMTdw22VNd41nSFFtLm15tX7FMnj90jT14zbP/vOogd+rtl1dPm2GJ0nX7PNh9fnqSHmZ7XY3XHUwMDFk3lx1MDAxMKdnz/JrkT9ev/Dou1x1MDAxYj7Lq+MrqH/05cNr6fnq+V/8q0SQIn0=

noDepartureInThePast()

noScheduleOverlap()

noDepartureInThePast()

noScheduleOverlap()

Use heuristics
to find symptoms

Collect a body of evidence to explore possible correlations

Assess its location, depth & Spread

... but are only heuristics. Not surefire rules.

Model Tension Heuristics

prevent accidental design debt

Signals

Cart

SHOPPING

Order

ORDER

Parcel

DELIVERY

...do not always reflect tensions.

This is not a fragmented lifecyle!

Experiment on the system

Once you have a body of evidences, act on the signals by running limited, safe to fail experiments to test your heuristics

POST-BOOKING

CRUISING

Exchange

Selection

Booking

Search

Cancellation

Search

Booking

SHODO

Model Tension
Heuristics

Preventing Accidental Design Debt

Julien Topçu

Josian Chevalier

Tech Coach

CTO / Coach

@julientopcu.com

‪@josianchevalier.bsky.social‬

TODo

Current Quest

Done

JIRA

???

Add a

Konami Code

Bug

Bug

Special meals

cancellation

Bug

Handle cancellation insurance

Overlapping ships can be selected

Deprecated seat preference shown during exchange

Bug

Feature

Feature

[Paid Option] Wireless pidgin connexion

TODo

Current Quest

Done

JIRA

Bug

Overlapping ships can be selected

Deprecated seat preference shown during exchange

Bug

Feature

Feature

[Paid Option] Wireless pidgin connexion

Handle cancellation insurance

Special meals

cancellation

Bug

???

TODo

Current Quest

Done

Inconsistent
special meal

orders

Bug

???

JIRA

POST-BOOKING

CRUISING

Exchange

Selection

Booking

Search

Cancellation

Search

Booking

POST-BOOKING

CRUISING

Booking

Exchange

Selection

Booking

Search

Cancellation

Search

Shared
Kernel

Model Mitosis

POST-BOOKING

CRUISING

Booking

Exchange

Selection

Booking

Search

Cancellation

Search

SK

Model Mitosis

POST-BOOKING

CRUISING

Booking

Exchange

Selection

Booking

Search

Cancellation

Search

Model Mitosis

BOOKING

CRUISING

Booking

Exchange

Selection

Booking

Search

Cancellation

Search

noDepartureInThePast()

noDepartureInThePast()

noScheduleOverlap()

noScheduleOverlap()

Booking

Exchange

Cancellation

eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nI1WwXLbNlx1MDAxML37KzTqNUWw2Fx1MDAwNbDIrU56yKXTiafTznRyoCVaYkyTXHUwMDFhkorjZvzvfaRcdTAwMTRRVO1hdbAlLPbh7e7bXHUwMDA1vl8tXHUwMDE2y+5ply/fLZb5t1VWXHUwMDE26yZ7XFy+6de/5k1b1Fx1MDAxNUxu+N3W+2Y17Nx23a599/bt6GFW9cPBKy/zh7zqWuz7XHUwMDFiv1x1MDAxN4vvw19YinXv++U6v/3rhp++fGhcdTAwMWWLrdebT9lcdTAwMWafXHUwMDA212HTXHUwMDBmMmVR5ePqNyxcdKlcdTAwMDajkb2N1obAJ+tcdTAwMTOs5JWcIbXsOJKLdLI+XHUwMDE2627b74CT8YnJJ1x1MDAxN9W7OFx1MDAwMmzzYrPtsIdZjWhyNqlcdTAwMGJqddySVZuyJ2ZPK23X1Pf5+7qsm57wT7llYlx1MDAxYTnfZqv7TVPvq/Xre+6KsrzpnspDVrPVdt+cRX044c8jf3exfvJra9Rg9MKRm22Vt+2Ebb3LVkX3dMjDabXnt/u4XHUwMDFlivV5ZNVkXHUwMDBm+ce+WtW+LE/LRbXO+0Isb5t/JsdV6+NxP0o91tFcdTAwMWRXnkfyed4jqziHMvrT+qg2ZuHL5d/qapBcdTAwMWVFXHUwMDE3nNiY4kir/Vx1MDAwMM11XHUwMDAz6l1WtvlYgZ7ar2d6XHUwMDFjQ9zv1tnBhaKoaFRmXHUwMDEyPdkhv/vL+Mt6df/CKbu6OJd7/1x1MDAxOb8txlx1MDAxMlxmP07fP795cTcn41x1MDAxMrlAwslcdTAwMDeb6Nz751x1MDAxNExcdTAwMDBdXHUwMDBiXHUwMDBiTEFkXHUwMDBlTtSQ2OCdXHUwMDE3QKaY/Fx1MDAwNI9cIlx1MDAxOU1cdTAwMTLYojc0OuU5QLJkXHUwMDFjh5RcdTAwMTKpXHUwMDBmnMZKXHUwMDFkXHUwMDAwVYxccjjNxYhcbkeaw3PEhskpXHUwMDFhLiiopilcXFCTlNE0SaOQ1TibP8smhKDOXCJPkdVdXHUwMDA0TN5cYsRcdTAwMTMoWsgopFk8TSaJsorlmJyfhitkOFx1MDAwNMJHJUbHs+FKSIbYXHUwMDA2TFx1MDAxNlEl0JjiReNcdTAwMTGu9ZpQsjRcdTAwMWKtXHUwMDE3b5R9XHUwMDEy21x1MDAwZj6+UEtU45BSdk6QW/WzxVxyYqGvXHUwMDFlXHUwMDA3XHRKYDHNnfeGbITNOzRcdTAwMGJYzuEh0YaVI/6z+kiXWkHpUVxuXHUwMDFjhFlA3oY5PCRcdTAwMDXzXHUwMDFmiUNcdTAwMDKtI1xyUzwnJoq3ySNcdTAwMWKqmPPzYn7tRjhcdTAwMTI0PnhcdTAwMTboXFyciEuzgFx0/YRcdTAwMWVTSdhcdTAwMWODm+DBhk5cdTAwMWKaQygw6SxcdTAwMWF6jZxVSlx1MDAxMTknL+do5PpqeGLvNNggaVx1MDAxNi7GXGKPhEiQoVx1MDAwNDVP4LxcdTAwMThx6Jxoe7WTm9WKS9AqWSRcXFx1MDAxMqWpkMHaQFwiXlLCuKZ55Xmrhq2mZK2ilZgncFxi1VqBjokkoG/jLFx1MDAxZatFYYODUFx1MDAwM0fnJ0pxUCVcbqtOUt+EXHUwMDFh/8dUXHSYQ76XXHUwMDAxcbQ8gcNRuNQtQSr90JFZco7xUFx0jOyhXHUwMDBlooh9mjs1XHUwMDAxQmFFNTxcdTAwMDbz7FBBq2JcbkSrIIdcdTAwMTGP6+NcdTAwMWNcdTAwMGZ3XHUwMDA2Olxml6Z6j7mi811BmFx1MDAwMpg+LkFZYFx1MDAxMya16EfEyI7mb4zX7r+rXHUwMDBir2WZtd37+uGh6HAx/95fqpdcdTAwMTdw22VNd41nSFFtLm15tX7FMnj90jT14zbP/vOogd+rtl1dPm2GJ0nX7PNh9fnqSHmZ7XY3XHUwMDFk3lx1MDAxMKdnz/JrkT9ev/Dou1x1MDAxYj7Lq+MrqH/05cNr6fnq+V/8q0SQIn0=

POST-BOOKING

CRUISING

Fragmented Model

drives

Exploration

&

Experimentation

Business Need

shape

Model

needs to account for new

Selecting

drives

Exploration

&

Experimentation

Business Need

shape

Model

needs to account for new

Selecting

drives

Exploration

&

Experimentation

Business Need

shape

Model

needs to account for new

Booking

Model

Accidental
Design Debt

Model
Entropy

produces through

accumulation

Features taking longer to develop?

More bugs in unrelated parts of the model?

Simple change causing widespread model updates?

generates through


misguided decisions

manifests

as complexity in

{
  "search": {
    "id": "XXXX",
    "criteria": {
      "outBoundDate": "2025-10-06T12:00",
      "inBoundDate": "2025-10-16T11:00"
    },
    "selectionComplete" : true,
    "totalPrice" : "230€",
    "paymentMean": {
      "type": "CREDIT_CARD",
      "number": "***********"
    },
    "travelInsurance" : "40€",
    "ships": [
      {
        "number": "A",
        "bound": "outbound",
        "departureDate": "2025-10-06T13:30",
        "fares": [
          {
            "comfortClass" : "FIRST",
            "price": "100€",
            "seatOptions": [ "ANY", "..." ],
            "deckOptions": [ "ANY", "..." ],
            "preferences": {
              "seat": "LOUNGE",
              "deck" : "UPPER_DECK"
            },
            "selected": true,
            "booked" : true

Intrinsic
Coupling

Accidental
Design Debt

Responsibilities
Coupling

may induce

Booking

Search

manifests as
strong

{
  "search": {
    "id": "XXXX",
    "criteria": {
      "outBoundDate": "2025-10-06T12:00",
      "inBoundDate": "2025-10-16T11:00"
    },
    "selectionComplete" : true,
    "totalPrice" : "230€",
    "paymentMean": {
      "type": "CREDIT_CARD",
      "number": "***********"
    },
    "travelInsurance" : "40€",
    "ships": [
      {
        "number": "A",
        "bound": "outbound",
        "departureDate": "2025-10-06T13:30",
        "fares": [
          {
            "comfortClass" : "FIRST",
            "price": "100€",
            "seatOptions": [ "ANY", "..." ],
            "deckOptions": [ "ANY", "..." ],
            "preferences": {
              "seat": "LOUNGE",
              "deck" : "UPPER_DECK"
            },
            "selected": true,
            "booked" : true

Intrinsic
Coupling

Accidental
Design Debt

Responsibilities
Coupling

may induce

Search

Booking

manifests as
strong

"Spork Effect"

Intrinsic
Coupling

{}

Refactoring
Habits

fosters

Sunk Cost
Fallacies

fosters

Deadlines
Pressure

KISS
DRY
YAGNI

is the path to

BBOM

"Spork Effect"

Intrinsic
Coupling

{}

BBOM

leads to

Model
Entropy

dissolves the model into a

"Spork Effect"

Intrinsic
Coupling

{}

BBOM

Model
Entropy

dissolves the model into a

leads to

locking the
 

model into

hardens into

Model
Sclerosis

Suffering...

Suffering...

Suffering...

Entropy

Tensions
Resolution

Accidental
Design
Debt

Model Rigidity

Entropy

Accidental
Design
Debt