DEV Community

Leon Pennings
Leon Pennings

Posted on • Originally published at leonpennings.hashnode.dev

Why Software Development Is Not Assembly-Line Work

Why Continuous Domain Modeling Is Essential

There is a persistent, damaging misconception in our industry: that software development is a form of manufacturing — a sequence of implementation steps performed after the “real thinking” (requirements) has already occurred. In this view, programmers are laborers, and programming paradigms such as Procedural and Functional Programming are production mechanisms: pipelines for turning known inputs into known outputs.

The problem is that this worldview is false.

Software is not the execution of predetermined knowledge.

Software is the construction and formalization of knowledge.

If the knowledge is not understood, the system cannot be built correctly — regardless of how elegant the functions or procedures are.


The Dutch Boat Joke

The core problem cause used throughout this blog. One Japanese boat has six rowers and a competent coxswain — efficient, coordinated, and winning the race. One Dutch boat has two rowers, a cox, multiple managers, and even a coffee machine onboard. Unsurprisingly, it loses. The team responds by hiring expensive consultants, adding a power coach for the two rowers, and installing more gadgets — yet the boat still does not win. Since the margin by which it loses is smaller, all managers receive a bonus, the rowers are fired, and a recruitment campaign is launched for two new rowers.

The joke is funny because in a race you can compare performance, iterate, and benchmark. Software development is different: it is a one-boat race. There is no external reference to measure against. In this context, reaching the finish line alone has become a benchmark of quality, but the setup and design of the boat are ignored. And the problem here is that the realization that the boat itself is of any consequence for the race is never exposed.

In software, focusing on adding more resources, more tools, or more “coaches” is misguided. The only way to approach the efficient boat is to understand the domain — to discover what the actual business domain is by continuously learning, modeling, and adapting.


Continuous Conceptual Modeling

Software development is not a linear sequence of “design first, implement later.” Unlike physical engineering — where material constraints and construction logistics allow for clear separation between design and execution — the digital domain is malleable. Requirements shift, new insights emerge, and the business domain evolves.

As a result, conceptual modeling is continuous. Developers constantly refine their understanding of entities, relationships, and rules, often while implementing code. Feedback loops occur at multiple frequencies: sometimes hours, as implementation difficulties reveal design gaps; sometimes months or years, as evolving requirements expose new facets of the domain.

This continuous approach ensures that the system evolves with understanding, rather than being rigidly forced into a predefined structure. In other words, software is never just “do after design.” It is a perpetual cycle of discover, model, implement, and refine.


Why Procedural and Functional Approaches Miss the Point

Procedural Programming and Functional Programming focus on execution — the steps to be taken or the transformations to apply. They are excellent for tasks that are well-defined, predictable, and stable: data transformations, algorithmic computations, or other “factory-style” work.

But their focus is their limitation. PP/FP assume the domain is already understood and will remain stable. They optimize for doing, not understanding. They excel at producing results from known inputs, but they are fragile in the face of change, because any shift in the domain — new rules, new concepts, or new relationships — requires reworking large parts of the implementation. They are, by design, reactive rather than adaptive.

When PP or FP systems become overcrowded or spaghetti-like, the common workaround is to split them into microservices. This is like taking the inappropriate Dutch boat and splitting it into multiple smaller boats to make it more “manageable.” The problem is not the number of boats or who rows where — it is the lack of understanding of the domain itself. Without an efficient boat — a coherent conceptual model — to guide which functionality belongs where, splitting a system into microservices is like adding more coaches, gadgets, or rowers to the Dutch boat: it may change appearances, but it does not improve performance or understanding. In most scenarios the long term effects are even worse.

Software is rarely static. Business domains evolve, rules shift, and meanings change. Procedural and Functional approaches rarely expose the underlying domain; they encode how to do things rather than what things are. As a result, they often drown in complexity as the system grows, producing brittle structures that require constant patching.


Why Rich Domain Models Are Adaptive

Object-Oriented modeling, applied as rich conceptual domain modeling, flips the focus: it starts with understanding the domain. Instead of asking “what steps do I execute?” or “how do I transform this data?”, it asks:

  • What are the entities in this domain, and what distinguishes them?

  • What rules govern their behavior?

  • What invariants must always hold?

By capturing the essence of the domain explicitly, a rich domain model creates clarity and adaptability. Changes in requirements often become simple adjustments to the model, rather than wholesale rewrites of code. OO thrives because it encapsulates behavior within meaningful concepts, providing structure that evolves with understanding rather than collapsing under it.

With every new functionality or user story, the conceptual model is evaluated first. Where should this new functionality go? Was the model correct in the first place? Every ticket becomes a challenge to the model and can refine it to better suit the business. Tickets are not just tasks — they are tests for the model. Completing the ticket is secondary; ensuring the model is correct comes first. This evaluation happens continuously during implementation. When code becomes complex, it signals that the model may be incorrect. This is the heart of continuous domain modeling.

In short: PP/FP execute; OO understands. PP/FP assume simplicity; OO discovers complexity — and then simplifies it into the model.


Software Development Is Discovery, Not Execution

Software is not an assembly-line task.

It is the act of discovering and formalizing domain knowledge.

Conceptual modeling allows teams to:

  • Identify natural boundaries in the domain.

  • Make invariants explicit and enforceable.

  • Reduce accidental complexity.

  • Build software that evolves with understanding, not chaos.

Without modeling, development is reactive, brittle, and costly. Procedural and Functional approaches may suffice for small, well-defined, transformation-heavy tasks, but they cannot capture meaning. OO as rich domain modeling thrives because it explicitly encodes understanding, allowing software to evolve gracefully.


Conclusion

Software development is fundamentally different from manufacturing: requirements are never fully known, complexity is not reducible to effort, and efficiency does not emerge from adding more resources. Just as the Dutch boat lost by assuming that power and gadgets solve performance, software teams fail when they assume coding more or applying patterns solves the underlying domain problems.

Continuous conceptual modeling — correctly applied OO — is the Japanese boat approach: understanding first, structure second, execution optimized by insight rather than raw effort. Only then does software development escape the fallacy of the assembly line.

Unlike PP/FP systems, where adapting to change is often revolutionary — requiring large-scale rewrites, disruptive redesigns, or complete refactoring — rich domain models support evolutionary, continuous change. Adjustments to the domain can be incorporated incrementally, minimizing disruption while preserving clarity and correctness. Over the long term, this approach is not only more robust and resilient but also cheaper, because it avoids the repeated crises and costly rewrites that arise from misaligned assumptions about the domain.

A PP/FP approach suits an assembly line well, because its focus is on execution. It optimizes for known inputs and predictable outputs. But software development is not an assembly line; its natural rhythm is continuous discovery. Rich domain models align with this rhythm, allowing understanding to grow and evolve as the system is built. The challenge is that, without a reference “efficient boat,” the market’s focus has drifted toward the Dutch-boat mentality: emphasizing more resources, more processes, and more superficial fixes rather than understanding the underlying domain.

Software is not built.

Software is understood into existence.

Top comments (0)