The Context: Introduction
In a world of Agile development and principles, see how a context-based approach can offer a fuller solution than one that's strictly software-first.
Join the DZone community and get the full member experience.
Join For FreeEvery software project has its own aura. That aura existed before the project was even started. It gave birth to the project and will be alive when the project will be decommissioned and/or replaced with some other project. This aura is The Full Context.
The Full Context consists of all information directly or indirectly related to the project. It's the single source of truth for every single decision related to the project, from the decision to start it to the name of every variable in the code.
The Full Context is enormously big and contains a lot of business, economic, and political information, such as company finances, the influence of persons or groups on particular decisions, or even the state of the mood of the developer that affected a particular decision.
Dealing with such huge amounts of information is possible only by layering it into a hierarchy of abstractions. Each layer of the hierarchy consists of elements — each element can be considered a word, and the whole set of elements at the same level of abstraction: the language. This language is then used by the next layer of abstraction to express words used by the layer above, and so on and so forth.
In most cases, there is no single "root" abstraction and no single hierarchy of abstractions. Instead, the context information is structured as a bunch of independent hierarchies.
It should be noted that strict layering of abstractions is essential to keep context comprehensible. Abstractions leaking to upper levels may result in uncontrolled growth of complexity and make context an incomprehensible mess.
The Context
The hierarchical context structure enables us to extract only the technical part of The Full Context, i.e., the part directly related to the project. Let's call this part The Limited Context, or simply The Context. This part of the full context is the only one usually necessary for development. To abstract out non-technical aspects, it is convenient to consider The Context as the single source of truth of all made project-related technical decisions. This abstraction removes "why" these decisions were made by removing all non-technical factors. This is a deliberate decision, necessary to limit complexity by keeping only parts essential for software development.
The Context is constantly updated and extended by new technical decisions we make every day. If some decision is not yet part of The Context, the decision is somehow made (usually using procedures specific to a particular team/company/product/etc.) and put into context. These decisions, therefore, look like a "decision map," which maps each "issue" to a particular "decision" and invokes a predefined procedure if an element is missing.
From general considerations, it makes sense to keep this "decision map" as small as possible because it directly contributes to the complexity of The Context. In other words, it is preferable to have a smaller set of more general/generic decisions that covers a wider range of similar situations.
Inside The Context
Let's take a closer look at The Context and check what else is there. Besides decision map, there are:
- the real business domain
- the business domain model
- real business processes
- the model of business processes
The word business
here is a placeholder because what is business
is up to each particular project and The Full Context which gave it birth. In the blockchain industry, at the top of the abstraction hierarchy, there will be blockchain domain and blockchain processes. In e-Commerce, it will be e-Commerce business, and so on and so forth.
Note that, when we start digging into abstractions, we'll find that the business
at each level of abstraction is different. It should be obvious: We split one of the top-level elements into subparts ("words"), where each "word" is responsible only for part of the implementation. This part of the implementation is the business
of this word. This process goes down and down through the layers of abstractions. At the bottom, there are purely technical details like calls to a standard library or even more low-level stuff. Actually, detailing can be continued in-depth as deep as necessary (perhaps infinitely) from task context switches, through specific CPU instructions and cache lanes, via signals and buses, down to logic elements and the physics inside the chip die and PCB.
Usually, there is a reasonable logical limit below which more details do not add any value. Obviously, if you are building an operating system, then system calls are your top-level language while everything below system calls is part of The Context domain or processes (again, limited to some reasonable level).
The business domain model and the model of business processes are our project code. We use programming languages to encode and represent parts of the business domain and processes. In other words, code is a formalized encoding of the business, its domain, and its processes. It means that code is at best as good as the domain and processes. If you have a fuzzy domain or bad/inefficient/inconvenient business processes, the code is at least as bad (usually worse). Also, a map is not territory, so both models are only approximations of the real business domain and processes.
It should be noted that relationships between business parts and their models are bidirectional. More often than not, the business is ready to change processes to match one proposed by software. The level of flexibility heavily depends on several factors and may vary. Usually, there is a tradeoff between price/time and the precision of modeling your processes/domain. From "buy ready to use software/subscription to service AND adjust all your processes to proposed model" (and get software up and running almost instantly for a few hundred/thousand $$) to "software should exactly reproduce our processes even if they are stupid, and we hate them" (and spend years and millions of $$), and everything in between.
But not only processes can change. The domain of the project also may change. Usually, this happens, when the project scope is reduced or extended. A decision to reduce or extend the scope might be a consequence of the technical assessment or analysis.
Nevertheless, it often is more convenient to consider these relationships as unidirectional (even if they're clearly not) and assume that real domains and processes are the sources of truth.
Note that various design documents, architecture designs, and other similar stuff are not part of The Context. They could exist and even be useful if they precisely correspond to code, but the code is the source of truth about the domain model and model of business processes.
Once we start thinking about project code with The Context in mind, we quickly discover the relevant decisions stored in The Context control code properties:
- How detailed the modeling is, compared to reality
- How precise the modeling is
- How easily real context can be restored from the code (context readability)
- How long the project will be used
- How performant it should be
Basically, everything about the project is determined by The Context. For example, if you're implementing a one-time migration tool to migrate a legacy system to a new platform, requirements to code quality, maintainability, test coverage, context readability, etc. will be significantly different from those for a backend planned to be used for at least five years. Moreover, those requirements should not necessarily be identical across the whole code base. For example, we might sacrifice some context readability in a performance-critical part of the code to achieve the necessary performance.
As one can see, a context-based approach is very business-focused, as opposed to traditional approaches, which are primarily focused on software. Of course, the connection to the business always existed, but it was usually just an input for software development. Specifications and requirements were eventually replaced/complemented by user stories and epics when the industry adopted agile methods. This significantly improved the connection with the business, but the focus on the software was left intact. A context-based view shows that it's not just a connection, but a tight coupling, where the business is a primary driver.
The Code
The main consequence of understanding of true relationships between business and software is the realization that existing approaches to software development might not be completely up to the task. Even a quick looks show significant issues with the traditional approach based on the best practices.
The first thing to note: The traditional approach tries to establish identical practices for all projects. As we know, every project is unique, and setting identical requirements does not seem like an adequate solution (this kind of resembles the famous average pilot story).
Second, but no less important: A significant part of the traditional approach relies on code readability as a justification. Overall, code readability is often considered one of the most important properties of code. The problem is that nobody knows what "code readability" is. Of course, every seasoned developer knows that it exists, but there is no reasonable definition for it. Existing ones are either self-recursive (i.e., funny but useless) or rely on other undefined terms such as "intent." This lack of definition means that every assessment of code readability is subjective, and there is no way to validate any given best practice that claims that it "improves code readability."
Even the term "code readability" is misleading. If the code compiles, it is readable, at least by the compiler. Most likely, with some effort, code is also readable by the human, too. So, "code readability" is not about reading the code at all.
Without a clear understanding of what code readability is, the whole traditional approach starts looking like a cargo cult. We're blindly repeating the same practices with the hope of getting a good result, but we have no idea why particular practices work or don't work in each particular case.
A context-based view clearly lacks the issues mentioned above. Code represents parts of the context, and The Context defines the requirements of easily real context can be restored from the code. There is much less room for ambiguity because each practice can be easily validated, whether it helps preserve a necessary part of context or not in every use case.
All of the above suggests that we need to significantly change our coding practices. But a detailed look into new coding practices is a theme for another article.
Published at DZone with permission of Sergiy Yevtushenko. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments