The Gap
by Uncle Bob
The problem is most evident when we realize that most existing frameworks and design tools focus heavily on managing syntactic constructs, often overlooking deeper levels of semantic content. These frameworks may be effective in performing technical tasks, but they do not provide developers with the means to clearly express the intent and meaning behind the system’s functionality. The result is a missing link between what the program “does” and what it “means.” Developers are forced to adapt their thinking to the limitations of tools and languages, which, by nature, do not provide enough flexibility to express meanings and conceptual relationships.
Most frameworks offer developers ready-made constructs for solving typical tasks, which at first glance simplifies the programming process. However, when it comes to designing systems with more complex and changing logic, these approaches begin to reveal their limitations. Frameworks built around predefined patterns dictate syntax and architecture, leaving little room for adaptation to unique problem requirements. This forces developers to “fit” the real-world problem into existing tools, which can lead to suboptimal or incorrect solutions.
While current approaches are strong in formalizing syntactic aspects, they are weak in the realm of semantic design. To effectively address modern programming challenges, we need an approach that considers not only the formal rules of language but also the meanings that define system behavior. Such an approach should be based on a conceptual framework that bridges the gap between program syntax and its semantics, allowing developers to interact meaningfully with the entities being programmed.
In theory, we can extract a tree of modules from the code, or call a tree
command in the terminal to pull the structure from files and directories, at least on a general level. However, in practice, concepts from the domain often blend with their implementation. In other words, if we take the module tree from a project’s code and turn it into a mindmap, it will be cluttered with terms like model, repository, decorator, or serializer. Many of the terms we use when discussing the project won’t appear there. So, the structure of our code does not always reflect the domain we are working in. We may recognize a familiar framework but not always grasp the core of the project. This issue was addressed by Uncle Bob in his writings on Clean Architecture.
During software development, we face the “Babylon problem,” where team members, using different terms and concepts, stop understanding each other. We also encounter the “invisible elephant” problem when dealing with legacy projects. These issues lead to a disconnect between the code and its meaning, ultimately hindering the successful completion of a project. To overcome this, we need to create a conceptual framework based on a shared language that all team members can use. This “ubiquitous language” was introduced by Eric Evans in the context of Domain-Driven Design (DDD). Evans emphasized the importance of creating a shared vocabulary, understandable to both developers and business experts, to bridge communication gaps and clarify the domain. However, we still need a cohesive semantics and structure, which we will explore further.
gap semantics syntax elephant babylon language