【.com快译】最近我们公司一直在讨论如何写干净代码相关的研讨会。他们认为干净的代码可以为团队开发、后期维护和重构打下良好的基础,其质量也值得信赖。因此,各个团体就如何建立和监督编码标准进行了大量讨论。虽然我同意这种做法有一定的效果,但我不认为这是清洁代码的核心关键。因此,以下是我个人对干净代码的理解和看法。(免责声明:以下内容并非本人独创,均出自众多伟大程序员的指导思想。但我认为重要的几点值得再次强调。)首先,我个人认为干净代码这个词并不准确。这个名词很容易让人误以为它只是为了让代码看起来更干净,这显然是非常肤浅的。相反,我认为称其为“宜居代码”更为合适,正如RichardGabriel所说:宜居代码是源代码的一种属性,它允许程序员、编码人员、错误修复人员和其他人在***阅读代码可以清楚地了解这里在做什么,不晦涩难懂,可以快速调整。宜居的代码让人有宾至如归的感觉,只有这样开发人员才能快速投入工作,而无需深入思考。虽然好的代码格式会让我们更容易阅读和更快地找到它,但其本质的宜居性才是关键。在我看来,代码宜居就是代码可以随着业务的需要任意改动。因此,当小规模业务需要调整代码时,只需低成本投入即可实现,而当大规模业务需要调整代码时,则需要投入更多的开发成本才能实现——因为新的需求与现有代码库不匹配,因此遗留代码无法共享。考虑到这个定义,我认为宜居代码的关键是整体结构。只有顶层设计(建筑)才能让宜居的特性成为现实。实现它的最佳方法包括以下几项:应用程序应该分成多个(不应该太多)模块。每个模块代表其领域内的特定含义,其命名应一目了然,不得有歧义,同时要保证阅读代码的人能够快速理解其作用。每个模块都应该有一个定义良好的接口,并且还应该有一个特定且唯一的名称来命名它。每个模块的生命周期和模块之间的关系在应用程序的入口点以声明方式表达。具体来说,应用程序入口点必须明确声明这些模块是如何连接的,并提供必要的商业价值。模块之间的共生关系应该在所有级别的代码中清楚地表达出来。(这部分其实是对结构化编程方式的重述,如前所述,我并没有创造任何新的概念。)在我看来,这些模块属于形式和功能的结合——命名是为了区分应用领域,而行为描述业务。声明不同模块之间的关系,不能有任何隐瞒和歧义,直接说明关系。我还认为这个定义也适用于递归。查看任何顶层模块,其中每个模块都应表现出与整个应用程序相同的特征:拆分为多个(不要太多)子模块。每个子模块都应该有一个定义明确的接口。每个子模块的关系和生命周期应该在模块的入口点声明。子模块之间的共生应该在代码中明确表达。这些嵌套模块可以作为应用程序、微服务、包、命名空间、绑定上下文、聚合、模块、对象甚至函数存在——所有这些都可以被视为“封装单元”或“对象”。这个原则和Page-Jones重构算法可以相互印证:把应用分成多个(不要太多)模块。删除了模块之间的所有高阶共生。递归直到没有意义。任何模块的任何子模块拆分都可以代表另一组实现。并且希望每个模块都可以看作是一个黑盒,黑盒的边界可以在没有冲突的情况下进行重构。这需要模块有定义良好的接口(例如,通过自动化测试),模块和子模块之间的共生关系清晰易懂。在我看来,使用该算法的价值随着层次结构的减少而降低。也就是说,厘清顶层模块之间的关系比厘清底层子模块之间的关系更有价值。这样的应用程序更容易更改,特别是考虑到顶级代码的简单表示。虽然简洁的低级模块也可以提供好处,但使应用程序宜居的总体好处相对较低。作为实现手段之一,我认为面向消息编程在各种规模上都能取得不错的效果。我之所以将应用程序分成多个模块,只是为了让模块之间的通信简单而有意义。模块的存在只是为了隐藏消息以及层实际上是如何“实时”变化的。MichaelFeathers提出的NakedCRC技术也可以实现适合本地模块的通信。不幸的是,我见过的大多数代码库都严重违反了上述每个实现模式。它通常由数百个非结构化类组成,所有类都位于同一抽象和可访问层中。这样的代码库一点也不令人愉快,并且很难向其中添加新类或概括现有类的功能。此类应用程序也很难重构,因为大多数“单元测试”机制都关注实现选择而不是业务需求。并且由于顶层封装中没有单元,我们也很难理解它的整体设计思路。原标题:什么是干净的代码?原作者:凯文卢瑟福
