Philosophy of software design: Chapter three programming tactics and Strategies


About the author:Chang Zhu, WeChat public number [Architecture future] author, more than 10 years of front-line Internet research and development experience; the first 58 city commercial member technology leader, the car driving technology director, now 58 to home business center technology leader.





One of the most important elements of good software design is the way of thinking when dealing with programming tasks. Many organizations encourage a tactical mindset that focuses on making features work as quickly as possible. However, if you want a good design, you have to take a more strategic approach and invest time to produce clean design and solve problems. This chapter discusses why a strategic approach can produce better design and is actually cheaper than a tactical approach in the long run.

3.1 tactical programming

Most programmers use a way of thinking I call tactical programming for software development. In a tactical approach, your main focus is to get something working, such as a new feature or bug fix. At first glance, this seems perfectly reasonable: what is more important than writing effective code? However, tactical planning makes it almost impossible to produce a good system design.

The problem with tactical programming is that it’s short-sighted.If you are programming tactically, you are trying to accomplish a task as soon as possible. Maybe you have a tough deadline. Therefore, planning for the future is not a priority. You don’t spend a lot of time looking for the best design; you just want to start working as soon as possible. You tell yourself that if you can make the current task complete faster, it’s OK to add a little complexity or introduce one or two small packages.

That’s why the system becomes complex. As mentioned in the previous chapter, complexity is increasing. What makes a system complex is not a specific thing, but the accumulation of dozens or hundreds of small things. If you program strategically, each programming task adds some complexity. Each of them seems to be a reasonable compromise in order to accomplish the current task quickly. However, complexity increases rapidly, especially if everyone is programming tactically.

Soon, some complex problems will begin to arise, and you will begin to regret that you didn’t take those shortcuts. However, you’ll tell yourself that it’s more important to get the next function working than to return and refactor existing code. Refactoring may help in the long run, but it certainly slows down the current task. Therefore, you need to look for quick fixes to solve any problems you encounter. This only creates more complexity, which requires more patches. Soon, the code was in a mess, but so far, it’s been very bad and it’s going to take months to clean up. It’s impossible for your schedule to tolerate such delays, and it doesn’t seem to make much difference to solve one or two problems, so you just keep programming tactically.

If you’ve been working on a large software project for a long time, I suspect you’ve seen tactical programming at work and experienced the problems it causes. Once you start on the tactical path, it’s hard to change.

Almost every software development organization has at least one developer who takes tactical programming to the extreme:Tactical whirlwind. Tactical cyclone is a prolific programmer who pumps out code much faster than others, but works in a completely tactical way.When it comes to implementing fast features, no one is faster than tactical tornado. In some organizations, management sees tactical whirlwind as a hero. However, the tactical whirlwind left a trail of destruction. They are rarely seen as heroes by engineers who will have to use their code in the future. Usually, other engineers have to clean up the mess left by the tactical whirlwind, which makes those engineers (real heroes) seem to be moving slower than the tactical whirlwind.

3.2 strategic planning

The first step to becoming a good software designer is to realize that it’s not enough to write code just to get the job done. It is unacceptable to introduce unnecessary complexity in order to complete the current task faster. The most important is the long-term structure of the system.Most of the code in any system is written by extending the existing code base, so as a developer, your most important job is to promote these future extensions. Therefore, you should not think that “working code” is your main goal, although your code must certainly work.Your main goal must be to produce a great designIt happens to work. This is strategic planning.

Strategic planning needs an investment mentality.You must invest time in improving the design of the system, rather than completing the current project in the fastest way. These investments will slow you down a bit in the short term, but will speed you up in the long term, as shown in Figure 3.1.

Some investments will be positiveFor example, it’s worth spending a little extra time finding a simple design for each new class; rather than implementing the first idea that comes to mind, try several alternative designs and choose the cleanest one. Try to imagine ways in which the system might need to change in the future and make sure your design is simple. Well written documentation is another example of proactive investment.

Other investments will be passive.No matter how much you put in advance, there will inevitably be mistakes in your design decisions. Over time, these mistakes will become obvious. When you find a design problem, don’t ignore it or fix it; take a little extra time to fix it. If you program strategically, you will continue to make small improvements in system design. This is the opposite of tactical programming, where you constantly add small complexities that can cause problems in the future.

3.3 how much is the investment?

So what’s the right amount of investment? A huge upfront investment, such as trying to design the whole system, will not work. This is the waterfall method. We know it won’t work. As you accumulate experience in the system, the ideal design often appears piecemeal. Therefore,The best way to do this is to make a lot of small investments on a continuous basis.I suggest you invest 10-20% of your total development time. This amount is small enough not to have a significant impact on your schedule, but large enough to produce significant benefits over time. As a result, your initial project will take 10-20% more time than a purely tactical approach. These extra hours will lead to better software design, and you will begin to experience these benefits in a few months. Before long, your development speed will be at least 10-20% faster than tactical programming. At this point, your investment is free: the gains from your past investment will save enough time to cover the cost of future investment. You will soon recoup the cost of your initial investment. Figure 3.1 illustrates this phenomenon.

Figure 3.1: at the beginning, a tactical approach to programming will move faster than a strategic approach. However, under the tactical approach, complexity accumulates faster, thereby reducing productivity. Over time, the strategic approach has made greater progress. Note: this number is only a qualitative description; I don’t know the exact curve shape of any empirical measurement.

On the contrary, if you program strategically, you will complete your first project at 10-20% speed, but your development speed will slow down as the complexity increases over time. Before long, your programming speed will be reduced by at least 10-20%. You will soon return all the time you saved at the beginning, and for the rest of the system life cycle, you will develop more slowly than when you adopt a strategic approach. If you have never worked in a severely degraded code base, talk to someone who has worked before; they will tell you,Poor code quality will reduce development speed by at least 20%.

3.4 entrepreneurship and investment

In some environments, there are powerful forces against the strategic approach. For example, startups in the early stages will feel great pressure to release their early versions as soon as possible. In these companies, it seems that 10-20% of the investment is unaffordable. As a result, many startups take a tactical approach, spend little effort on design and less time cleaning up when problems arise. They think it’s reasonable to do so. If they succeed, they will have enough money to hire more engineers to clean up the rubbish.

If your company is leaning in this direction, you should realize that once the code base becomes spaghetti, it’s almost impossible to fix it. You may have to pay high development costs for the product lifecycle. In addition, the rewards for good (or bad) design come quickly, so it’s likely that the tactical approach won’t even speed up your first product release.

Another thing to consider is that one of the most important factors for a company’s success is the quality of its engineers.The best way to reduce development costs is to hire good engineers: they are not much more expensive than mediocre engineers, but they are surprisingly productive.However, the best engineers are very concerned about good design. If your code base is a wreck, messages will be sent out, which will make it harder for you to recruit. As a result, you are likely to end up as a mediocre engineer. This will increase your future costs and may lead to further degradation of the system structure.

Facebook is a startup that encourages tactical programming. Over the years, the company’s motto has been “move fast, break the rules.”. “New engineers who have just graduated from university are encouraged to immediately invest in the company’s code base; it is normal for engineers to push the submission to production in the first week of work. On the positive side, Facebook has built a reputation for empowering its employees. Engineers have a lot of freedom, and there are few rules and restrictions to hinder them.

Facebook has achieved amazing success as a company, but its code base has been damaged due to the company’s tactical methods; many codes are unstable, difficult to understand, with few comments and tests, and difficult to handle. Over time, the company realized that its culture was unsustainable. Eventually, Facebook changed its motto, “grow fast with a solid infrastructure” to encourage its engineers to invest more in good design. It remains to be seen whether Facebook can successfully solve the problem of years of tactical programming accumulation.

To be fair, I should point out that Facebook’s code may not be much worse than the average of startups. Tactical programming is common in startups; Facebook is a particularly obvious example.

Fortunately, in Silicon Valley, the strategic approach is also likely to succeed. Google and VMware grew up almost at the same time as Facebook, but both companies have adopted more strategic strategies. Both companies attach great importance to high-quality code and good design, and build complex products that can solve complex problems with reliable software systems. The strong technology culture of the two companies is well known in Silicon Valley. Few companies can compete with them for top technical talents.

These examples show that a company can succeed in any way. However, working for a company that cares about software design and has a clean code base is much more interesting.

3.5 conclusion

Good design is not free. It has to be something you keep investing in so that small problems don’t accumulate into big problems.Fortunately, good design eventually pays off, and faster than you think.

Consistency in the application of strategic approaches is essential, and investment is seen as something to be done today, not tomorrow. When you’re in trouble, it’s easy to put off the cleanup until after the crisis. However, this is a slide; after the current crisis, there will almost certainly be another, and after that there will be another. Once you start delaying design improvements, delays can easily become permanent, and your culture can easily slip into tactical methods. The longer it takes to solve design problems, the bigger the problem; solutions become more daunting, which makes it easier for people to put them off. The most effective way is for every engineer to continuously make a small investment in good design.

Disclaimer: the translation of this article is for learning only. The copyright of this article belongs to the original English author or publisher. If there is any infringement, please contact to delete.

Recommended Today

[Redis5 source code learning] analysis of the randomkey part of redis command

baiyan Command syntax Command meaning: randomly return a key from the currently selected databaseCommand format: RANDOMKEY Command actual combat:> keys * 1) “kkk” 2) “key1”> randomkey “key1”> randomkey “kkk” Return value: random key; nil if database is empty Source code analysis Main process The processing function corresponding to the keys command is […]