Seven Deadly Sins of a Software Project

The following text is a partial translation of the original English article, performed by ChatGPT (gpt-3.5-turbo) and this Jekyll plugin:

可维护性是现代软件开发最有价值的美德。可维护性基本上可以衡量为新开发人员在能够开始对软件进行重大更改之前需要学习的工作时间。时间越长,可维护性越低。在某些项目中,这个时间要求几乎是无限的,这意味着它实际上是不可维护的。我相信有七个基本且致命的“罪恶”使我们的软件变得不可维护。以下是它们。

很不幸,我们正在使用的编程语言过于“灵活”。它们允许太多的事情,并对太少的事情进行限制。例如,Java并不反对你将整个应用程序放在一个名为“类”的容器中,其中包含几千个方法。从技术上讲,这个应用程序会编译和运行。但这是一个众所周知的反模式,被称为“上帝对象”。

因此,反模式是一种在技术上是可以接受的设计方式,但普遍认为是错误的。每种语言都有许多反模式。它们存在于你的产品中,就像活体组织中的肿瘤一样。一旦开始生长,很难停止。最终,整个体系将死亡。最终,整个软件将变得无法维护,必须重新编写。

一旦你容许了一些反模式的存在,你最终会得到更多反模式,而“肿瘤”只会不断增长。

这对于面向对象的语言(如Java、C++、Ruby和Python)尤其如此,主要是因为它们从过程化语言(如C、Fortran和COBOL)继承了很多东西。而且面向对象的开发者往往以过程化和命令式的方式思考。很不幸。

顺便说一下,在现有的众所周知的反模式清单之外,我还认为以下几个事情是相当糟糕的编码方法。

在这里,我唯一的实用建议是阅读和学习。也许这些书会对你有所帮助,或者我的书《优雅的对象》也行。始终对你的软件质量持怀疑态度,不要在它“只是工作”的时候放松。就像癌症一样,越早诊断,生存的机会就越大。

当我查看提交历史时,我应该能够知道每个更改的是什么做出了更改,以及更改的原因。而且,获取这三个答案所需的时间必须以秒为单位衡量。在大多数项目中,情况并非如此。以下是一些建议:

始终使用票据。无论项目有多小或团队有多少人,即使只有你自己,也要为解决的每个问题创建票据(GitHub问题)。在票据中简要说明问题,并在那里记录您的思考。使用票据作为与问题相关的所有信息的临时存储。发布一切在将来可能有意义的东西,当其他人试图理解那些”几个奇怪的提交”时。

在提交中引用票据。不用说,每个提交必须有一条消息。没有消息的提交是一种非常糟糕的做法;我甚至不想讨论为什么。但仅仅有一条消息是不够的。每个消息必须以您正在处理的票据号码开头。GitHub(我相信您正在使用它)将自动链接提交和票据,增加更改的可追溯性

不要删除任何内容。Git允许我们进行”强制”推送,覆盖之前存在于服务器上的整个分支。这只是一个例子,说明您如何破坏开发历史。我经常看到人们在GitHub讨论中删除他们的评论,以使票据看起来更”干净”。这是错误的。永远不要删除任何内容;让您的历史与您一起保留,无论它现在看起来多么糟糕(或杂乱)。

每个软件在交付给最终用户之前都必须进行打包。如果是Java库,它必须被打包为一个.jar文件并发布到某个存储库;如果是Web应用程序,则必须部署到某个平台等等。无论产品大小如何,总有一个标准的流程来进行测试、打包和部署。

一个理想的解决方案是自动化这个流程,使得可以通过单个命令从命令行执行它。

大多数项目都远离此种情况。它们的发布过程总是涉及一些神奇的操作,负责此项任务的人(也被称为DevOp)需要在各个地方点击一些按钮,登录某个地方,检查一些指标等等。这种特定情况下的发布过程仍然是整个软件工程行业的一个典型罪恶。

在这里,我只能给出一个实用的建议:自动化它。我使用rultor.com进行自动化,但你可以使用任何你喜欢的工具。重要的是整个过程是完全自动化的,并且可以从命令行执行。

静态分析使我们的代码看起来更好。通过让它看起来更好,我们不可避免地使它工作得更好。但这只有在整个团队被强制(!)遵循静态分析器规则的情况下才会发生。我在《严格控制Java代码质量》一文中谈到了这一点。我在Java项目中使用qulice.com,在Ruby中使用rubocop,但几乎每种语言都有许多类似的工具。

你可以使用其中任何一个,但一定要强制使用!在大多数使用静态分析的项目中,开发人员只是生成漂亮的报告,然后继续以前的编码方式编写代码。这种“志愿”方法对项目没有任何好处。而且,它会产生一种质量的错觉。

我所说的是,静态分析必须成为您部署流程中的强制步骤。如果违反任何静态分析规则,构建将无法通过。

简而言之,测试覆盖率是软件通过单元测试或集成测试的程度。覆盖率越高,代码在运行测试时被执行的”数量”就越多。显然,覆盖率越高越好。

然而,许多项目开发者根本不知道他们的覆盖率。他们只是不测量这个指标。他们可能有一些测试,但没有人知道它们对软件的深入程度以及哪些部分根本没有经过测试。这种情况比已测量并向所有人报告的低测试覆盖率要糟糕得多。

高覆盖率并不能保证高质量。这是显而易见的。但未知的覆盖率是可维护性问题的明确指标。当新的开发者加入项目时,他或她应该能够进行一些更改并查看这些更改对覆盖率的影响。理想情况下,测试覆盖率应该与静态分析一样进行检查,如果覆盖率低于某个预定义的阈值(通常在80%左右),则构建应该失败。

我所指的无间断是指没有里程碑和发布。无论你正在编写什么样的软件,你都必须经常发布和版本化。一个没有明确发布历史的项目是一个难以维护的混乱。

这主要是因为可维护性是基于我通过阅读你的代码来理解你。

当我查看源代码及其提交和发布历史时,我必须能够知道其作者的意图,项目一年前正在做什么,现在正在走向何方,以及其路线图等等。所有这些信息必须在源代码中,并且更重要的是在Git历史中。

Git标签和GitHub的发布说明是两个提供这些信息的强大工具。充分利用它们。此外,不要忘记每个产品的二进制版本必须能够立即下载。即使项目目前正在进行3.4版本的开发,我也必须能够下载版本0.1.3并立即测试。

每个软件都有其应该使用的接口。如果是一个Ruby gem,我将以最终用户的身份使用其中的类和方法。如果是一个网络应用程序,最终用户将看到和控制一些网页以使用该应用程序。每个软件项目都有接口,并且必须仔细记录。

与上述所有内容一样,这也与可维护性有关。作为项目上的新程序员,我将从其接口开始学习。我应该能够理解它的功能并尝试自己使用它。

我在这里谈论的是用户文档,而不是开发者文档。一般来说,我反对将文档放在软件内部。在这一点上,我完全同意敏捷宣言—可工作的软件比全面的文档更重要。但这并不指的是“外部”文档,它应该被用户而不是开发者阅读。

因此,必须清楚地记录最终用户与软件的交互。

如果您的软件是一个库,那么它的最终用户是将使用它的软件开发人员—不是为其做贡献,而只是将其作为“黑盒子”使用。

这些是用于评估我们奖项竞赛中参赛的开源项目的标准。

Translated by ChatGPT gpt-3.5-turbo/42 on 2023-12-15 at 06:41

sixnines availability badge   GitHub stars