Three Types of Engineering Questions


Background

Several years ago I was discussing some aspects around tooling and standardization with my manager at the time and framed my thoughts with the notion that software engineers face two types of questions: those that need an answer and those that need a right answer. We were working for an organization with a fairly healthy engineering culture so I omitted the third category of those that should have an answer, but subsequent exposure to their being underserved led to the recognition of the additional category.

Questions that Need an Answer

In many organizations the majority of the time may be spent solving what are largely incidental questions where the specific solution itself may not be particularly valuable, but rather that just a solution exists. A standard example and that which was the impetus for the original conversation is getting code deployed for use. As a developer once you have confidence in your code and want it to start being active in production how that happens is typically just noise; if someone where to offer you some form of trusted and reliable blackbox where a simple command of one form or another got your code safely running it seems unlikely there would be a reason to care about what is inside of that box.

Such decisions have been historically plentiful and virtually anything that stands in the way of delivering business logic is likely to qualify. This fairly closely parallels the concept of accidental complexity in that the solution space is likely to bring a lot of pesky questions such as how your code is structured, how someone can interact with your system and how your data is persisted. Some of these may warrant the right answer but you typically need an answer for all of them, and therefore the remainder simply need any answer that gets the question out of your way.

Much of this is also likely to amount to boilerplate that can be reduced through adoption of some technologies, and advancements such as no-code/low-code frameworks and AI-generated code can allow for further focus on delivery of proposed value, but regardless of technologies it is likely worth seeking ways to reduce such drag while also guaranteeing that any solution offered doesn’t itself get in the way.

Unfortunately some of these questions also tend to get far too much attention, likely due to some combination of visibility, proximity to the shiny thngs that many engineers like to fiddle with, and sunken technical costs. None of that is to say that such efforts should be widely hampered or discouraged, but more that the practical outcomes should be kept in sight.

Questions that Need a Right Answer

Of course there is rarely if ever the right answer, and so a right answer speaks more to the pursuit of an appropriately optimized answer. Complementarily to too much time being spent on those questions that need an answer, too little time is often spent on those questions that need a right answer. These are typically the parts of your system that are most clearly tied to the reason for its existence, which should in turn be tied back in some way or another to value which helps differentiate the business.

Which questions require the right answer are very dependent on what is being built, but are the sticky questions for which there was no evident off-the-shelf offerings and which likely inspire some initial decisions with identified tradeoffs. Such decisions could be driven by the domain model or by significant technical considerations and adoption of an inappropriate design could compromise the viability of the solution. As such decisions are important but their selection is fallible it may be highly desirable to work towards a system that fosters a supple design, but in all cases the ability to efficiently deliver such crucial designs is paramount.

Questions that Should Have an Answer

The last category are those questions that should have answers, but systems can hobble along indefinitely without such answers. A glaring example of such concerns is telemetry and similar operability along with a raft of other runtime considerations such as fault tolerance. This translates to a wide range of non-functional requirements and transcends software itself into supporting considerations such as capturing and distributing knowledge (and seeking ways to reduce the need to do so). Many of these pursuits seem to align with the new world perspective of making things go right rather than the old world perspective of trying to prevent them from going wrong and is covered extensively in different books (Release It! comes to mind but the topics are touched on in countless others). It is alarmingly common for teams to only pay attention to such concerns when things go wrong, and for the reaction at that time to amount to a one-off fix thrown wherever seems most convenient.

Such a mentality certainly seems to be begging for trouble as complexity or scale increases (as spoken to by the aforementioned books and plentiful solutions in the space), but I think for the time being it is also a concern similar to security that can’t be an afterthought and instead needs to inform either the selected solutions or engineer practices (or both).