这是用户在 2024-12-31 11:32 为 https://berthub.eu/articles/posts/on-long-term-software-development/ 保存的双语快照页面,由 沉浸式翻译 提供双语支持。了解如何保存?

On Long Term Software Development
关于长期软件开发

Recently the Dutch Electoral Board (where I am also a very part time advisor) invited me to do a talk reflecting on their open source Abacus vote tabulation software.
最近,荷兰选举委员会(我也是该委员会的兼职顾问)邀请我做一次演讲,介绍他们的开源 Abacus 投票列表软件。

Much software is now provided as a service, and is typically deployed continuously (CD, continuous deployment), surrounded by enough automated testing (CI, continuous integration) that we can be reasonably sure that a new revision is likely to at least work to some extent.
现在,许多软件都是以服务的形式提供的,而且通常都是持续部署(CD,持续部署),并有足够多的自动测试(CI,持续集成),这样我们就可以合理地确定,新的修订版至少在某种程度上是可行的。

In contrast, there is also still a huge world where people don’t appreciate such continuous changes combined with only a pretty good likelihood of things working. Software that controls (nuclear) power plants, elections, pacemakers, airplanes, bridges, heavy machinery. In general, stuff that can kill you if it does the wrong thing, or perhaps simply by not working.
与此形成鲜明对比的是,还有一个巨大的世界,在那里,人们并不欣赏这种持续不断的变化,而只是对事物运行的可能性抱有相当大的期望。控制(核)发电厂、选举、心脏起搏器、飞机、桥梁、重型机械的软件。总之,这些东西一旦做错了事,或者干脆不工作,就会要了你的命。

These fields appreciate your software sticking around for decades, with well described and pre-announced changes. Release notes that go beyond “various bug fixes and improvements”. Software that might not see any changes for a few years, after which a new major release gets planned, and stuff still needs to build from source.
这些领域希望你的软件能坚持数十年,并对变更进行详细描述和预先公布。发布说明要超越 "各种错误修复和改进 "的范畴。软件可能在几年内不会有任何改动,之后会计划发布新的重大版本,但仍需要从源代码构建。

Crazy talk of course, but some of us like it this way!
当然是疯话,但我们中的一些人喜欢这样!

On long term software development: caring (enough) about the future
关于长期软件开发:(足够)关心未来

The presentation consisted of a generic part on long term software development, and a specific critique of their software development so far.
演讲内容包括关于长期软件开发的通用部分,以及对他们迄今为止软件开发的具体评论。

For the generic part, I asked my friends on Mastodon to weigh in:
对于通用部分,我请我在 Mastodon 上的朋友们发表意见:

Mastodon delivered in spades, and most of this post is derived from input from kind Mastodonians.
Mastodon 交出了一份满意的答卷,这篇文章的大部分内容都来自于好心的 Mastodon 人。

Now, nothing what follows is particularly earth shattering. However, the strength of certain recommendations is noteworthy, and might give you some pause.
下面的内容并不特别惊世骇俗。不过,某些建议的力度值得注意,可能会让你有些犹豫。

Dependencies  依赖关系

At an extremely high level, we can think about software like this. There is an outside world that we don’t control, for example client software (like browsers). Realities we have to deal with. Within our own software, we have certain very fundamental base choices, like which programming languages to use. Switching programming languages effectively requires a rewrite of the whole stack, so you don’t do that lightly.
从更高层次上讲,我们可以这样看待软件。有一个我们无法控制的外部世界,例如客户端软件(如浏览器)。我们必须面对现实。在我们自己的软件中,我们有一些非常基本的基础选择,比如使用哪种编程语言。转换编程语言实际上需要重写整个堆栈,因此我们不会轻易改变。

Somewhat above that we often find frameworks which couple tightly with our codebase. Think of web/JavaScript frameworks, object relational mappers (ORMs), stuff like Spring Framework, Ruby on Rails, React, Rust Axum etc. While you could switch out such a dependency, it is (very) heavy lifting. It touches lots of your code.
在此之上,我们经常会发现与我们的代码库紧密结合的框架。例如 Web/JavaScript 框架、对象关系映射器(ORM)、Spring Framework、Ruby on Rails、React、Rust Axum 等。虽然您可以将这样的依赖关系换掉,但这是一项(非常)繁重的工作。它会触及大量代码。

Next up, almost everything will depend on some kind of database. There are many databases around, but most of them work more or less the same. If you built on MySQL and you come to your senses and shift to something else, you’ll have real work to do, but it is mostly in the details and specifics.
接下来,几乎一切都将依赖于某种数据库。目前有许多数据库,但它们的工作原理大都差不多。如果你使用的是 MySQL 数据库,而后来你醒悟了,转而使用其他数据库,那么你就有真正的工作要做了,但这主要是在细节和具体方面。

Finally, there are mostly interchangeable “helpers”. Libraries that perform some function for you here and there, but are mostly “point” solutions. You could rip and replace such a dependency likely without even having to tell your users.
最后,还有很多可以互换的 "助手"。这些库在这里或那里为你执行一些功能,但大多是 "点 "式解决方案。你甚至无需告诉你的用户,就可以撕掉并替换这样的依赖关系。

Now, from the above it is clear that if you are thinking long term, dependencies are extremely important. You depend on them. However, since we can’t devote maximum attention to everything, we should think far harder about the bottom of the pyramid than the top. And such thinking is necessary since on multi-year timescales, your dependencies and the outside world do not sit still:
从上文可以看出,如果从长远考虑,依赖性是非常重要的。你依赖它们。然而,由于我们不可能对所有事情都投入最大的关注,因此我们对金字塔底部的思考应该比对顶部的思考更多。这种思考是必要的,因为在多年的时间尺度上,你的依赖关系和外部世界都不会静止不动:

One overwhelming bit of feedback after my Mastodon post was to severely limit your dependencies, because all of them might over time:
在我发表了 Mastodon 之后,有一个压倒性的反馈就是要严格限制你的依赖关系,因为随着时间的推移,所有的依赖关系都有可能发生变化:

  • Drift away, leading to adjustments in your code or, worse, silent changes in behaviour
    漂移,导致代码调整,或者更糟糕的是,行为发生无声的变化
  • Shift to new major versions with semantic changes, requiring rewrites on your part
    转向新的主要版本,语义发生变化,需要您重新编写
  • Get abandoned or simply disappear, or start to decay
    被遗弃、消失或开始腐烂
  • Get hijacked by (nation state) actors (think npm, pypi etc)
    被(民族国家)行为者劫持(如 npm、pypi 等)
  • Start to get monetized by the new VC owner
    开始被新的风险投资公司所有者货币化
  • Develop conflicting dependency requirements of their own
    自己提出相互矛盾的依赖性要求

(I’ve personally been burned on Python by the last bullet point where one of the dependencies required version 3.14 or less of module such and such, and another dependency needed 3.15 or higher)
(我个人曾在 Python 上遇到过最后一个问题,其中一个依赖项需要 3.14 或更低版本的模块,而另一个依赖项则需要 3.15 或更高版本)。

Now this is not a call for doing without dependencies of course! They are inevitable for getting stuff done. But when extrapolated over a 10 year time frame, we must take an extremely critical look at what code we are going to rely on:
当然,这并不是在呼吁不要依赖他人!要完成任务,依赖性是不可避免的。但是,如果以 10 年的时间框架来推断,我们就必须对我们将要依赖的代码进行极其严格的审查:

  • Does the tech look good if you look at the source code? And can you?
    如果查看源代码,技术是否看起来不错?你能看吗?
  • Who else uses this dependency?
    还有谁使用这种依赖性?
  • Who writes it? Why?
    谁写的?为什么?
  • What are their goals?
    他们的目标是什么?
  • Are they funded? By whom?
    他们有资金吗?由谁资助?
  • Is maintenance happening? Do you see security releases?
    是否正在进行维护?你看到安全发布了吗?
    • Is there a community that could take over maintenance?
      是否有社区可以接管维护工作?
    • Could I take over maintenance if need be?
      如果需要,我能接手维护工作吗?
  • Should I fund/support them to make sure they stay around?
    我是否应该资助/支持它们,以确保它们继续存在?
  • And what about their dependencies?
    它们的依赖关系如何?
    • What is the security track record there?
      那里的安全记录如何?

If this looks like big work, you’d be right. This easily takes hours/days per dependency to figure out. Incidentally, this is why I think adding dependencies to a project should be somewhat hard work technically. That gives you some natural pause to think if it is a good idea!
如果这看起来像个大工程,那你就对了。每个依赖项都要花费数小时或数天的时间才能弄明白。顺便提一下,这就是为什么我认为在项目中添加依赖关系在技术上应该是一项艰巨的工作。这样你就会自然而然地停下来思考这是否是个好主意!

What might not be a great idea is to have 1600 dependencies in 2024, dependencies which already change at such a rapid clip your code base is effectively a moving target. To be honest, you don’t know what you are shipping if your code draws from over a thousand dependencies, mostly ones you have no direct knowledge of.
在 2024 年拥有 1600 个依赖项可能不是一个好主意,因为这些依赖项的变化速度非常快,你的代码库实际上就是一个移动的目标。老实说,如果你的代码来自上千个依赖项,而其中大部分依赖项你并不直接了解,那么你根本不知道自己在运什么。

Runtime dependencies  运行时依赖

So far we’ve been talking about build/compile-time dependencies. Many projects these days however also have runtime dependencies, like perhaps S3, or Google Firebase. Some of these things are informally pretty well standardised (like S3), but other things are effectively a lock-in. In short, if you plan on a 10 year horizon, you need to have an extremely short or empty list of third party services you rely on. It is going to be extremely expensive in 2034 to find an exact workalike of what you are based on now.
到目前为止,我们一直在讨论构建/编译时依赖关系。不过,如今许多项目也有运行时依赖关系,比如 S3 或 Google Firebase。其中有些东西已经非正式地实现了很好的标准化(如 S3),但其他一些东西实际上是一种锁定。简而言之,如果你计划使用 10 年的时间,那么你所依赖的第三方服务列表就必须非常简短或空白。如果要在 2034 年找到与现在完全相同的服务,成本将会非常高昂。

This is especially relevant for ‘cloud native’ software development that uses many intricate or higher level third party services.
这对于使用许多错综复杂或更高级第三方服务的 "云本地 "软件开发尤为重要。

Of special note also are build-time service dependencies. If ’npm install’ (or equivalent) no longer works for some reason, can you even build your software?
值得特别注意的还有构建时的服务依赖性。如果 "npm install"(或类似软件)由于某种原因不再工作,你还能构建你的软件吗?

TESTING TESTING TESTING  测试 测试

Did I say testing? Everyone was clear on this front. Have as many tests as possible. There was some argument that not all tests are equally valuable, and this is of course true. But you’ll almost never regret a test. Tests are always a good idea, especially if you have many dependencies which shift and drift all the time. Tests will not prevent this from happening, but they will help you get started earlier to adjust to the changed situation.
我说测试了吗?大家在这方面都很清楚。尽可能多地进行测试。有人认为,并非所有测试都同样有价值,这当然没错。但你几乎永远不会为一次测试而后悔。测试永远是个好主意,尤其是当你有很多依赖关系,而这些依赖关系会不断变化和漂移的时候。测试并不能防止这种情况的发生,但它们能帮助你更早地开始工作,以适应变化了的情况。

Tests will also give you (mental) support while refactoring, or removing dependencies. In addition, after a 3 year hiatus in development, tests are a great way to reestablish that you still have a functioning system, even when using newer compilers, runtimes, operating systems etc. Write more tests.
在重构或删除依赖关系时,测试也会给你(精神)支持。此外,在开发中断 3 年后,即使使用更新的编译器、运行时和操作系统等,测试也是重新确定系统是否仍能正常运行的好方法。编写更多测试

Complexity  复杂性

Now, this is not new ground, but it bears reiterating: complexity is the end-boss of software development. Complexity can slay the best programmer and even the best team. It is the ultimate enemy. Yet, because of entropy and human behaviour, complexity will always increase unless you act upon it consciously.
现在,这已经不是什么新鲜事了,但仍需重申:复杂性是软件开发的终结者。复杂性可以杀死最好的程序员,甚至最好的团队。它是终极敌人。然而,由于熵和人类行为,除非你有意识地采取行动,否则复杂性总是会增加。

Although this is well-trodden material, I think this graph is somewhat of a novelty. But in all honesty, I’m probably channeling something I read earlier:
虽然这些都是老生常谈的话题,但我觉得这张图还是有点新意的。不过说实话,我可能是在模仿之前读过的一些东西:

If you have a limited amount of code to deal with, this code could be quite complex in nature. As the amount of code increases, it needs to be ever simpler if you still want to have a handle on it. As long as your code is in the green triangle, and your team stays competent, you are good. But you can’t arbitrarily reshape the green area:
如果要处理的代码数量有限,那么这些代码的性质可能会相当复杂。随着代码量的增加,如果您还想掌控代码,就需要让代码变得越来越简单。只要您的代码处于绿色三角形内,您的团队也能胜任工作,您就没有问题。但是,你不能任意重塑绿色区域:

Even if you hire more people and/or people with bigger brains, there is a hard limit to how much complexity we can deal with. On a good day, even. And once your code has escaped the green area, you are hosed. And as the arrow shows, the natural movement of your code is ‘up and to the right’. People demand more features, programmers like to optimize stuff even when there is no need, and even required bug fixes often add a lot of new code (instead of doing the scarier work to undo the underlying complexity that likely led to the bug).
即使你雇佣了更多的人和/或更聪明的人,我们所能处理的复杂性也是有限的。甚至在好的时候也是如此。一旦你的代码超出了绿色区域,你就完蛋了。正如箭头所示,代码的自然移动方向是 "向上和向右"。人们需要更多的功能,程序员喜欢在没有必要的情况下优化代码,即使是必要的错误修复也往往会增加大量新代码(而不是做更可怕的工作来消除可能导致错误的潜在复杂性)。

Over time, complexity only adds up. There is cognitive load involved in dealing with a function called CreateFile that does not actually create a file most of the time. Paring back such misnamed functions or counter-intuitive APIs is of utmost importance. Oddly behaving calls and methods offer fresh opportunities to trip you up every day.
随着时间的推移,复杂性会不断增加。在处理名为 CreateFile 的函数时会产生认知负荷,因为该函数在大多数情况下实际上并不创建文件。减少这类命名错误的函数或违反直觉的应用程序接口至关重要。行为怪异的调用和方法每天都会提供新的机会来绊倒你。

So the message from the field was unequivocal: refactor early and often, remove unneeded or duplicate code, take time to simplify. Or you will inevitably end up in an unmaintainable swamp in the course of your 10+ year software project. And note that this will be easier to do if you invested in tons of tests.
因此,来自现场的信息非常明确:尽早并经常重构,删除不需要或重复的代码,花时间简化。否则,在 10 多年的软件项目过程中,你将不可避免地陷入无法维护的沼泽。需要注意的是,如果你在测试方面投入了大量精力,这一点就会更容易做到。

Write boring simple code. Even more simple than that. Even more boring.
编写无聊的简单代码。比这更简单。更无聊

“Everyone knows that debugging is twice as hard as writing a program in the first place. So if you’re as clever as you can be when you write it, how will you ever debug it?” - Brian Kernighan
"每个人都知道,调试程序的难度是编写程序的两倍。因此,如果你在编写程序时就已经尽可能地聪明,你又怎么会去调试它呢?- 布莱恩-克尼根

Write super boring code. Write naive but obvious code. “Premature optimization is the root of all evil”. If it was too simple, you can always make it more complex later. And that moment might never arrive. Don’t write clever code until you simply have to. You will not ever regret writing code that was simple.
编写超级无聊的代码。编写幼稚但显而易见的代码。"过早优化是万恶之源"。如果太简单,以后可以再做得复杂些。而那一刻可能永远不会到来。不到万不得已,不要编写聪明的代码。你永远不会后悔编写了简单的代码。

Especially be aware of high performance code/functionality that only works if you “hold it just right”. I’m a great fan of LMDB for example, but PowerDNS went through quite some pain before we were able to reliably benefit from its awesome speed and capabilities. Similarly, I’ve used RapidJSON, a SIMD-accelerated JSON library, but eventually found the edges too sharp. Too much juggling of chainsaws.
尤其要注意只有在 "恰到好处 "的情况下才能运行的高性能代码/功能。例如,我是 LMDB 的忠实粉丝,但 PowerDNS 在我们能够可靠地受益于其超强速度和功能之前,也经历了不少痛苦。同样,我也使用过 RapidJSON 这个 SIMD 加速 JSON 库,但最终发现它的边缘太锋利了。太多的电锯杂耍。

The scary thing is however that such technologies might appeal to you - “I can deal with these constraints, and reap the awesome performance rewards”. This may be true on a good day this year. But you, or your replacement, might struggle 5 years from now. This also goes for complex programming languages by the way.
然而,可怕的是,这些技术可能会吸引你--"我可以应对这些限制,并获得令人惊叹的性能回报"。在今年的好日子里,这可能是对的。但 5 年后,你或你的接班人可能会陷入困境。顺便说一句,复杂的编程语言也是如此。

But seriously, keep it simple. Even simpler than that. Really.
但说真的,还是简单点好。甚至比这更简单。真的

LinkedIn-based software development
基于 LinkedIn 的软件开发

So what technology are we going to use? In theory we should follow our dependency checklist from above to determine that. In reality, this is often an almost subconscious decision where someone tries something that looks attractive, and if it works, we run with it.
那么,我们要使用什么技术呢?理论上,我们应该按照上面的依赖性清单来决定。在现实中,这往往是一个几乎下意识的决定,有人会尝试一些看起来很吸引人的东西,如果可行,我们就采用它。

Such attractiveness can come from LinkedIn posts by esteemed thought leaders and influencers. It could also come from Hacker News users raving over the latest glorious framework to end all frameworks.
这种吸引力可能来自 LinkedIn 上受人尊敬的思想领袖和有影响力人士的帖子。它也可能来自 Hacker News 用户对最新的辉煌框架的赞美。

Now, it might be that such hyped technologies are worth the hype. But it is probably best to recognize that new stuff has yet to prove its longevity. Best use it in experimental places and keep it away from the 10-year software project for now. According to the Lindy effect for many things, their longevity is proportional to their current age.
现在,这些被炒作的技术可能值得炒作。但最好的办法可能是认识到,新东西还有待证明其寿命。最好在实验场所使用它,暂时不要让它参与十年软件项目。根据许多事物的林迪效应,它们的寿命与当前的年龄成正比。

Logging, telemetry, performance
记录、遥测、性能

One issue with software that is not updated/deployed continuously to millions of users is that you do not get that instant feedback moments after you broke the website. Although oddly enough, even there it can take quite some time before the message reaches the people that can fix it.
如果软件没有持续更新/部署到数以百万计的用户中,就会出现一个问题,那就是在你弄坏网站后,无法立即得到反馈。但奇怪的是,即使在这种情况下,也可能需要相当长的时间才能将信息传达给能够修复问题的人。

Feedback from Mastodon was to make sure that your software somehow logs its performance, failure and activities very well. Starting from your earliest releases. Over the years, having such data will prove invaluable in solving uncommon bugs from deployments that may run your software once every few months.
来自 Mastodon 的反馈意见是要确保你们的软件能以某种方式很好地记录其性能、故障和活动。从最早的版本开始。多年来,拥有这些数据将被证明在解决部署过程中出现的不常见错误时非常有价值,这些部署可能每隔几个月就会运行一次您的软件。

I once accidentally deployed a UI to customers meant to list only a few things. What the user never told me was that they created 3000 folders, but they did tell me that nothing worked anymore. Better (performance) logging/telemetry would’ve saved me months of pain there.
有一次,我不小心向客户部署了一个用户界面,目的只是列出一些东西。用户从来没有告诉我他们创建了 3000 个文件夹,但他们告诉我什么都不能用了。如果有更好的(性能)日志记录/遥测功能,我就可以省去几个月的痛苦了。

Documentation  文件

We all know we should document more, no news there. But the feedback I got was quite clear that there are specific things we need to document. You can these days quite easily churn out very attractive looking API documentation. This does not tell you however WHY things are like this. What is the idea behind how the system works? Is there a philosophy? Is there a specific reason why we do these non-obvious things? Why is the solution split up the way it is?
我们都知道我们应该记录更多,这并不是什么新闻。但我得到的反馈非常明确,我们需要记录一些特定的内容。如今,你可以很容易地编写出看起来非常吸引人的 API 文档。但是,这并不能告诉你事情为什么会这样。系统运行背后的理念是什么?有什么理念吗?我们做这些非显而易见的事情有什么具体原因吗?为什么要以这种方式拆分解决方案?

This stuff goes beyond writing architecture documents, although you should definitely also write those. But you could also think about (internal) blog posts by developers, or interviews with teams. Shoot the breeze on why it all came out like that.
这不仅仅是撰写架构文档的问题,虽然你也应该撰写架构文档。但你也可以考虑由开发人员撰写(内部)博客文章,或与团队进行访谈。说说为什么会这样。

7 years from now with a mostly new team, the knowledge in such documents is priceless. “Yeah the system is single threaded, and let me tell you why”.
7 年后的今天,我们的团队大部分都是新人,这些文件中的知识将是无价之宝。"是的,系统是单线程的,我来告诉你为什么。

Specifically, I got feedback that despite the craze that good code needs no comments, code definitely needs comments. Especially why a function is like that. Other feedback was to work on commit messages, which is something I’d like to support, but then also make sure that people can easily see those commit messages.
具体来说,我得到的反馈是,尽管人们热衷于认为好代码不需要注释,但代码绝对需要注释。尤其是函数为什么会这样。其他的反馈意见还包括要在提交信息上下功夫,这也是我希望支持的,但同时也要确保人们能很容易地看到这些提交信息。

Personally, I have days where my brain isn’t well setup for writing more code, but I could definitely spend that day writing useful comments and notes. It might be a great idea to schedule time for that for teams as well.
就我个人而言,有些时候我的大脑并不适合编写更多的代码,但我绝对可以用这一天来编写有用的注释和笔记。为团队安排这样的时间也不失为一个好主意。

The team  团队

Some of the feedback came from people with software that supports an 80-year mission (!). It is quite common for teams to turn over quite quickly these days. In many places, 3 years is quite the tenure. Although you can counteract such turnover with good documentation and great tests, it is hard work. One of the easiest hacks for successful software longevity is keeping people around for a decade. This means actually hiring them as employees and taking good care of your programmers. Crazy right?
其中一些反馈来自那些拥有支持 80 年使命(!)的软件的人。如今,团队快速更替是很常见的现象。在许多地方,3 年就是相当长的任期。虽然可以通过良好的文档和出色的测试来抵消这种流动,但这是一项艰苦的工作。成功延长软件寿命的最简单方法之一就是让员工在公司工作十年。这意味着要真正把他们当作员工来雇用,并好好照顾你的程序员。很疯狂吧?

In some places, software development is performed by consultants, who leave after dropping their code in your systems. This is roundly seen as a very bad idea under most circumstances if you are aiming for decade-long sustained software quality.
在某些地方,软件开发是由顾问完成的,他们在系统中留下代码后就离开了。在大多数情况下,如果你的目标是获得长达十年的持续软件质量,那么这种做法被普遍认为是非常糟糕的。

Be open source  开放源代码

Now, this is not always or even often something you can do. But having your code exposed to outside eyes is a great way of keeping yourself honest. One fun anecdote is that companies or governments will often say they need months or years to prepare (CLEAN UP) code for open sourcing. Because on the inside, people allow themselves far worse code than they’d prefer to share with the outside world. Open source code often has higher standards, and it is a great mechanism of keeping you on track.
现在,这并不总是甚至经常是你能做到的事情。但是,让自己的代码暴露在外界面前是让自己保持诚实的好办法。一个有趣的轶事是,公司或政府经常会说,他们需要几个月或几年的时间来准备(清理)代码以便开源。因为在内部,人们允许自己的代码比他们更愿意与外界分享的代码糟糕得多。开源代码通常有更高的标准,它是一种让你保持正轨的绝佳机制。

If you can get away with it of course.
当然,如果你能做到的话。

Dependency (wellness) check
依赖性(健康)检查

I wrote above how dependencies can evolve to drift or shift away from where we expect them to be. If you do nothing, you discover this because of bugs, build failures or other disappointments. One recommendation from Mastodon was to periodically schedule a wellness check on your dependencies. This could also bring positive surprises. It is well possible that one of your dependencies has grown new capabilities for example, which might make it possible to simplify your code. Or scrap another dependency.
我在上文写到,依赖关系是如何发展到偏离或转移到我们期望的位置的。如果你什么都不做,你就会因为错误、构建失败或其他失望而发现这一点。Mastodon 提出的一项建议是定期对依赖关系进行健康检查。这也会带来积极的惊喜。例如,很有可能你的某个依赖项已经增加了新的功能,这就有可能简化你的代码。或者取消另一个依赖项。

If you spend time on this maintenance, you discover issues at a moment of your choosing. Or as mechanics say, schedule time for maintenance, or your equipment will schedule it for you.
如果您花时间进行维护,就能在您选择的时间发现问题。或者像机械师说的那样,安排时间进行维护,或者你的设备会为你安排时间。

Some books  一些书籍

As noted this is all well trodden ground, and here are some books that have done the trodding:
如前所述,这些都是老生常谈的话题,这里有几本书已经做了这方面的介绍:

  • The Practice of Programming, Brian W. Kernighan, Rob Pike. Full of stuff that should be obvious, but in practice is not yet obvious enough. Even though this is mostly about C, the lessons are universal.
    《编程的实践》,布莱恩-W-克尼根、罗布-派克。书中的内容本应显而易见,但在实践中却不够明显。尽管这本书主要讲述的是 C 语言,但其中的经验却是通用的。
  • The mythical man-month, Fred Brooks. Called “The Bible of Software Engineering”, because “everybody quotes it, some people read it, and a few people go by it”.
    神话般的人月,弗雷德-布鲁克斯。被称为 "软件工程圣经",因为 "每个人都引用它,有些人阅读它,还有一些人遵循它"。
  • A philosophy of software design, John Ousterhout - a modern take by a seasoned professional.
    《软件设计哲学》,约翰-奥斯特豪特(John Ousterhout)--一位经验丰富的专业人士的现代观点。
  • Large Scale C++ Software Design, John Lakos - I would not specifically recommend buying this book since much of what it describes is quite specific to old-style C++. However, if you chance on this work, its stories on very large scale software development are illustrative of the art. Has valuable words on how circular dependencies crop up, and how much they suck.
    《大型 C++ 软件设计》,约翰-拉科斯(John Lakos)--我并不特别推荐购买这本书,因为书中描述的很多内容都是旧式 C++ 所特有的。不过,如果你碰巧看到这本书,其中关于超大规模软件开发的故事很能说明问题。书中关于循环依赖是如何产生的,以及它们有多糟糕,都有很有价值的论述。

Hacker News users cpeterso, rramadass and cratermoon have also suggested the following (thanks!):
Hacker News 用户 cpeterso、rramadass 和 cratermoon 也提出了以下建议(谢谢!):

  • Kill It with Fire: Manage Aging Computer Systems (and Future Proof Modern Ones), by Marianne Bellotti, who managed the maintenance and modernization of large legacy systems at the United States Digital Service
    《火中取栗:管理老化的计算机系统(以及面向未来的现代系统)》,作者 Marianne Bellotti 曾在美国数字服务部负责大型遗留系统的维护和现代化工作。
  • Lehman’s Laws of Software Evolution
    雷曼软件进化法则
  • “Laws of Software Evolution Revisited.”, Lehman, M. M. In Software Process Technology, edited by Carlo Montangero, 108–24. Berlin, Heidelberg: Springer Berlin Heidelberg, 1996.
    "重新审视软件进化法则》,Lehman, M. M. 著,《软件过程技术》,Carlo Montangero 编辑,108-24 页。柏林,海德堡:Springer Berlin Heidelberg, 1996.
  • “On Understanding Laws, Evolution, and Conservation in the Large-Program Life Cycle.”, Lehman, M.M. Journal of Systems and Software 1 (1979): 213–21. https://doi.org/10.1016/0164-1212(79)90022-0.
    "论理解大型程序生命周期中的规律、进化和守恒》,Lehman, M.M. 《系统与软件期刊》1(1979 年):213–21. https://doi.org/10.1016/0164-1212(79)90022-0.
  • “Programs, Life Cycles, and Laws of Software Evolution.” Proceedings of the IEEE 68, no. 9 (September 1980): 1060–76. https://doi.org/10.1109/PROC.1980.11805.
    "程序、生命周期和软件进化法则"。电气和电子工程师学会论文集》第 68 卷第 9 期(1980 年 9 月):1060–76. https://doi.org/10.1109/PROC.1980.11805.
  • “Metrics and Laws of Software Evolution-the Nineties View.”, Lehman, M.M., J.F. Ramil, P.D. Wernick, D.E. Perry, and W.M. Turski. In Proceedings Fourth International Software Metrics Symposium, 20–32, 1997. https://doi.org/10.1109/METRIC.1997.637156.
    "软件进化的度量和法则--九十年代的观点",Lehman、M.M.、J.F. Ramil、P.D. Wernick、D.E. Perry 和 W.M. Turski。In Proceedings Fourth International Software Metrics Symposium, 20-32, 1997. https://doi.org/10.1109/METRIC.1997.637156.
  • Studying the laws of software evolution in a long-lived FLOSS project, Jesus M Gonzalez-Barahona, Gregorio Robles, Israel Herraiz, Felipe Ortega
    研究长期自由和开放源码软件项目中的软件进化规律,Jesus M Gonzalez-Barahona、Gregorio Robles、Israel Herraiz、Felipe Ortega

Finally  最后

Overwhelmingly, these are the recommendations for long-term software development:
绝大多数情况下,这些都是对长期软件开发的建议:

  • Keep it simple. Simpler than that. Yes, even simpler. You can always add the complexity later if needed!
    保持简单。比这更简单。是的,甚至更简单。如果需要,以后还可以增加复杂性!
    • Keeping it simple requires periodic refactoring / code deletion
      保持简单需要定期重构/删除代码
  • Think real real hard about your dependencies. Fewer is likely better. Scrutinize and audit. And if you find you can’t audit 1600 dependencies, rethink your plan. Don’t go for LinkedIn-based development choices.
    认真思考你的依赖关系。越少越好。仔细检查和审核。如果你发现自己无法审核 1600 个依赖关系,请重新考虑你的计划。不要选择基于 LinkedIn 的开发方案。
    • Re-visit your dependencies periodically to see how they are doing
      定期重新查看您的依赖关系,了解它们的运行情况
  • Testing, testing, testing! Will help you spot shifting dependencies in time, will give you confidence to do the refactoring you need to keep things simple
    测试、测试、测试!这将帮助你及时发现依赖关系的变化,让你有信心进行必要的重构,使事情保持简单
  • Document all the things, not just the code, but also the philosophy, the idea, the “why”
    记录所有内容,不仅是代码,还有理念、想法和 "为什么"
  • Aim for a steady team. Get actual employees with a long-time investment in your project
    争取建立一支稳定的团队。聘用对项目有长期投入的实际员工
  • If you can get away with it, ponder being open source
    如果你能做到这一点,不妨考虑开放源代码
  • Logging, (performance) telemetry will save your bacon over the years
    多年来,日志记录和(性能)遥测将为您省下不少麻烦

None of these things are novel, but the vehemence with which veteran developers exhort us to think hard about these recommendations should give us pause.
这些都不是什么新鲜事,但资深开发人员强烈要求我们认真思考这些建议,这应该引起我们的警惕。

Finally, I want to thank the large cast of Mastodon users who weighed in with their decade long experiences. Your help was most appreciated! In addition, the material was improved significantly by the great questions & reflections from my colleagues at the Dutch Electoral Board.
最后,我要感谢广大的 Mastodon 用户,他们用自己长达十年的经验为我们提供了宝贵的意见。非常感谢你们的帮助!此外,我在荷兰选举委员会的同事们提出的问题和反思也极大地改进了我的材料。

If you have any further feedback, or disagreement, do let me know on bert@hubertnet.nl!
如果您有任何进一步的反馈或不同意见,请通过 bert@hubertnet.nl 告诉我!