One of the most important properties of a software system is that you can understand what the software system does without having to run it. This concept is commonly referred to as the ability to “reason about a system.” Basically, you want to explain the structure, behavior, and results of a system without first seeing it in action.
To understand why this is important, imagine a system with 100 different parts. To make this easier, let’s assume it’s a real physical system rather than a computer. Suppose you have an automated factory that produces cars in 100 steps, from raw materials to finished cars. Each of these parts makes some modification to the input material to produce an output product. There are many ways to configure this system and its parts.
Each piece can be made to perform multiple actions, and depending on the action performed, Next The machines we chose are actually different. For example, suppose you want to convert a metal into a circular bar. The number of circular rods needed for each car is different, but our rods can be made from 5 different metals. Therefore, the machine has a program that determines which bars to make each time it gets a bar of steel. This depends on the time of day and current car demand. And depending on which rod is made, that rod is sent to one of five different next machines.
Now imagine all the machines in the entire system are like that. It takes a complex set of inputs and produces a possible complex set of outputs, which are then sent to the next complex set of machines. Not only is it impossible for humans to comment on (and thus reason about) the exact behavior of the entire system at any time, it is even difficult to reason about the behavior of individual parts.
Now imagine a different setup where each machine takes one input, provides one output, and each machine “talks” to only one other machine (i.e., its input is always It comes from one specific machine and its output is always sent to another single machine). It may be difficult to think about the whole system at once, but since we still have 100 machines, we can look at the individual parts and make inferences from them about both the individual parts and the logical behavior of the whole system. is easy.
This is a core part of simplicity and the ability to reason about such systems. When you look at individual parts of a software system, you need to be able to make statements about its behavior, warranties, structure, and potential consequences without having to run that part.It must be clear exactly how That part can interface with the rest of the system. We need to know exactly what that part is called and what to call it. Or you need to understand the structure that creates boundaries for how that part can be used. For example, this is why the concept of “private” and “public” functions in many programming languages facilitates reasoning about the system. These are boundaries that indicate what can and cannot happen.And when you look at the real thing implementation By reading the code and comments of a function or class, you should be able to easily understand the action it is performing. For example, this is why naming is so important for functions and variables. Proper naming allows the reader to make inferences about the system’s behavior and boundaries.
choice
There is another very important element To enable However, the system requires this quality. To illustrate this part, imagine that each machine in a hypothetical car factory is not automated and is operated by humans. This is similar to a software engineer typing actual code and “running” a machine such as an IDE, computer, compiler, or programming language.
In the first example, we have a complex machine making complex decisions, but imagine that all the choices that were previously made by automatons now have to be made by humans. This means that every time a piece of metal enters the machine, a human has to look at it, determine what type of metal it is, and then decide what kind of rod to make. All these need to be studied and taken care of based on the current demand for cars. time of day. In a real factory, some of that might actually be acceptable. It at least creates interesting work for a person. But even there it turns out that it will open the door to many mistakes and bad outcomes.
Compare this with the latter example. In this example, we have a simple machine with simple inputs and outputs. Perhaps it would be so easy to operate that one person could operate multiple machines, eliminating almost all chances of mistakes or bad outcomes.
Now consider that in programming, programmers often work with dozens or even hundreds of these “machines” in terms of the classes and functionality they maintain. So a better analogy for a complex car factory would be: One man does everything hundred machine. As you can see, it quickly becomes impossible to create a “car” if there are too many decisions that the operator has to make in each part of the system.Even if you did it Doing that would slow down car production so much that the people operating the machines would burn out. And surprisingly, this is exactly what happens to teams that have to maintain software systems of that level of complexity.
Now, what are the important points we introduced here when we added humans to the “factory”? We introduced the factors. decision (What humans do with their minds) and choice (choices presented to humans).
There is also a school of thought that says all developers should always be given the power to make all decisions about a software system. This sounds great. Because it sounds like it’s offering intellectual freedom to intelligent people. This is what we all want. However, if you take this principle too far, you are actually creating a complex car factory for developers. so many When faced with a choice, they are either paralyzed, certain to do the wrong thing, or develop highly contradictory systems that cannot be easily reversed by others. .
So what is the solution here? To take away all choice from everyone and turn them into mindless automatons carrying out the will of the chief designer? Well, I’m sure some software architects want that, but the truth is, That’s a bit of an extreme solution. The answer is to recognize which options are appropriate instead. important What developers can create and not important.
This depends on the members of your software team and where they are in the software lifecycle. For example, if you’ve just started a new company and you’re the first developer, it’s important to be able to choose the language you use, the frameworks, and just about everything about the underlying platform on which you run your company. But you still don’t want those frameworks and libraries to make decisions you don’t need to make. Imagine if the compiler stopped and asked you exactly how to optimize each piece of code. Is it helpful to you or does it increase productivity? Is it actually a net benefit to your company or to the goals you’re trying to achieve? I don’t think so.
And at another point in a project’s lifecycle, once you’ve standardized on the language and particular framework you’re using, you usually don’t want to force some random junior developer to pick a different language or framework. their It’s part of the codebase. This is a decision you don’t have to spend time making, and it’s more productive to just go with the flow. Even if there were better languages or frameworks they could use, rewriting the entire system just to implement this junior developer’s one feature doesn’t seem like a good use of resources.
Overall, if we can remove too many choices from developers; need In fact, it can save you significant development time across your company. Imagine if he had to spend two weeks reviewing various frameworks before all the teams in the company could start developing the system. Now imagine that you standardized a framework like this: good (i.e. it was able to meet the business needs of everyone using it) perfection, and no one had to make that decision anymore. How much engineering time did we save across the company? That’s huge, and in the long run, it outweighs almost any other productivity gain.
It’s important to keep in mind here. teeth Decisions that developers need to make. It is absolutely necessary to be able to decide how the business logic of the system works. This is the core requirement to get the job done. In the past, there were frameworks and libraries that didn’t allow users to create the systems they actually needed, a level of restriction that negatively impacted productivity. For example, imagine that your company had standardized a framework that supported HTTP, but somehow fundamentally he couldn’t support SSL (i.e. didn’t support HTTPS). This can be disastrous if you need to encrypt your connection for security purposes. So this is a very bad limitation.
This is a very difficult line to draw at times, but generally I Delete choice In fact, it will make your developers happier in the long run because they will be more productive. This is very difficult at first when you take certain choices away from people. Because people feel that you are affecting their personal freedom. And in a sense, in the short term, so are you. But the truth of the matter is that you are trying to provide more freedom. create— a freedom that its developers fundamentally actually want. The purpose of limiting choices should always be to: Improve Ability to build systems. Rather than ruin production, you remove distractions, barriers, and clutter in the form of choices that someone simply does not choose. need What you’re making.
-Max