Getting software to work is just the beginning
Everything will work In application development, and probably in every IT field, almost any tool will get you to a working result. Any tool, any combination of frameworks and technologies can be strung together and made to work. If the bar is 'does it run and do what was asked', nearly every approach clears it. That is exactly why it cannot be the goal. A criterion that every approach passes…
In software development, achieving a functional product is merely the starting point. Virtually any combination of frameworks and technologies can be assembled to produce a working result. However, this is insufficient, as the real work begins once the basic functionality is established. The critical aspects to consider are the code's flexibility, ease of adaptation to domain changes, and the speed at which those changes take effect.
The market often prioritizes minimal coding efforts, but this is measured by the number of lines written. Nonetheless, underneath the seemingly streamlined structure, stacked frameworks result in an explosion of additional code, configurations, and behaviors that must be understood later on. Requirements are often incomplete, akin to describing a toe rather than an entire elephant. Building software involves continually discovering and refining the underlying system.
There are two primary approaches to development: the contract model and the search model. The contract model involves directly translating requirements into code, treating the requirement as a description of a toe and the implementation as a delivery problem. This approach is neither the most efficient nor the most productive. In contrast, the search model involves iteratively refining a structure that better fits the domain as requirements emerge.
Each new requirement refines the existing structure, progressively bringing it closer to a complete understanding of the domain.
Architects and engineers may not possess domain expertise, leading to suboptimal solutions. The optimal choice is to create a lean architecture with minimal boilerplate code, enabling easy adaptation to evolving requirements. Boilerplate code refers to unnecessary, repetitive tasks generated by tools or AI, such as getters, setters, and builders.
These elements are considered accidental complexity, which arises from the implementation rather than the problem itself. Essential complexity, on the other hand, is inherent to the problem domain.
Frameworks and libraries introduce an additional layer of complexity, often requiring migration and adaptation when updated. This accidental complexity can obscure the essential complexity of the domain. When architectural machinery separates behavior from domain concepts, the code becomes harder to understand. The context that provides meaning to the code becomes obscured, making it more challenging to discern the domain's true nature.
To make informed decisions, developers must engage in early conversations with domain experts. These discussions evolve as the domain becomes clearer through UI interactions. The process of refining the model based on domain knowledge never truly ends, as understanding grows and the software increasingly fits the domain. Boilerplate code and overly complex frameworks should be avoided, as they obscure the true essence of the domain and hinder the development process.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.