OurDotNetLogo

.NET学习,.NET平台,OurDotNet,.NET学习,.NET平台,OurDotNet

什么是好代码
作者:CreateLight  |   2017/12/19 22:17:55   |  阅读:641

1,定义

  让我们来谈谈代码。

  代码重要吗?当然,代码就是设计(Jack W.Reeves, 1992);代码是最有价值的交付物。

  我们需要好代码吗?在给好代码下个定义之前,这个问题无法回答。

  那么,究竟什么是好代码?

  闻到硝烟味了吗?哦不,战争从来不是好东西。

  对我而言,好代码就是整洁可用的代码。

  好代码首先必须是可用的代码,可用是指代码做了它应该做的事情,而且做得不错。 如果让你写求绝对值的代码,你就不能写成求平方根的;如果让你做一个文本编辑器,OK,你做出来了,它不是一个图片编辑器,它确确实实就是一个文本编辑器。但是用户输入一个字要一分钟,这也不能称之为可用,因为它没达到不错的标准,当然,如果这个文本编辑器是给慢星人用的,你有理由认为它是不错的。那么,究竟怎样才叫应该做,怎样才叫不错呢?也许客户(用户)的反应(评价)是唯一的标准答案。

  其次它需要整洁。

  整洁是一个相对的词,在我看来,它唯一的作用就是令维护简单。如果你写的代码不需维护(没有BUG、完成之后永远不会做功能改动、没有任何其它代码基于这些代码编写等等,显然,如果满足了这些条件,没人有必要来阅读你的代码),比如用完即抛的很简单的一次性用品,那么只要可用就行了,不需要整洁。值得注意的是, 这里隐含了一个假设的前提条件:不保持代码整洁的情况下,你能够写出可用的代码。

  现实生活中相当一部分(也许我可以说大部分)代码是需要维护的,也就意味着它们如果想成为好代码,必须要整洁。

在继续探讨整洁话题之前,也许有必要先谈谈复杂度

2,复杂度

  什么是复杂度?在本文中,我们所谈及的复杂度是指软件开发中的复杂度,很难给出精确的数学定义,虽然业界已经有了各种相对严格的测量方法,但根据本文需要,这里只简单的给出自己的定义:复杂度是事物复杂程度的量化描述,其大概等价于使软件达到可用所需耗费的劳动(智力+体力)的总和。

  当然,上述定义又引出了对劳动的量化需求,本文更多的只需要对复杂度做相对的评估,不需要绝对的量化,所以这里简单地用通用的行业描述:劳动 = 人月。

  无疑,(现有事实证明)软件开发是复杂度很高的活动,我们有各种方法论、工具、最佳实践等等等,其本质都是为了降低软件开发的复杂度,也就是:第一,使软件达到可用的标准;第二,尽可能地减少所需劳动。

  那么,软件开发为什么这么复杂呢?《没有银弹》给出了它的回答:所有软件活动包括根本任务——打造由抽象软件实体构成的复杂(现实)概念结构,次要任务——使用编程语言表达这些抽象实体,在时间和空间限制内将它们映射成机器语言。相应的,软件开发的复杂度由两部分构成:

  1) 来自根本任务:根本困难——对复杂现实情况的抽象,这是软件开发中固有的困难。

  2) 来自次要任务:次要困难——通过特定表达方式让计算机理解。这是受限于目前生产(方法、工具)的并非与生俱来的困难。

  更具体一些,软件的复杂度来自这些:

  1) 规模:软件实体可能比人类有史以来创造的其他任何实体都要复杂,计算机本身就比人类建造的大多数东西复杂,它拥有大量状态,这使得构思、描述和测试都很困难,而软件系统状态又比计算机状态多几个数量级。同时,软件没有两个部分是相同的,至少在语句级别上,如果有,我们会将它合并成一个子函数,在这个方面,软件系统和建筑、汽车大不相同,后者存在大量重复的部分。另外它不仅仅导致技术上的困难,还引发了许多管理上的问题,它使全面理解变得很困难,从而妨碍了概念上的完整性;它使所有离散出口难以寻找和控制;它引发了大量学习和理解上的负担,使开发慢慢地演变成一场灾难。

  2)(容易)变化:软件天生就是易变的,第一,因为人们的想法本身容易产生变化;第二,人们可能有这样的错觉:软件很容易变化——不需要太高的代价,相对其他产品来说;第三,软件必须演变才能成功。软件实体的扩展不是简单元素的重复添加,而必须是不同元素实体的添加,大多数情况下,这些元素以非线性递增的方式交互,因此整个软件的复杂度以更大的非线性级数增长。

  3)(缺乏)一致性:物理学家和数学家都坚信本源的存在,所有复杂的表象之下都必有简单的一致的本源存在,如基本粒子,如通用原理。软件工程师可能缺乏这种信念,他必须处理不同用户习惯以及随时间推移而变化的接口,这些变化是无规律的,仅仅由于不同的人——而不是上帝——设计的结果;另外他们还需要处理各种历史遗留系统的兼容性所带来的问题,这往往需要保持接口和历史接口的一致性。从本质上来说,这些都是不必要的,但软件工程师必须处理它们——以及它们带来的复杂度。

  4) 不可见性:几何抽象是强大的工具,建筑平面图、机械制图、分子模型都帮助相关工作人员更好的理解及工作,软件的客观存在不具有空间的形体特性,因此没有已有的表达方式能恰如其分的描述软件。当我们试图用图形描述软件结构时,我们发现它不止包含一个,而是很多相互关联、重叠在一起的图形,现有的描述方式都是强制将关联分割,直到可以层次化一个或多个图形(形成某种扁平结构)。这种缺憾限制了个人的设计过程,同时也严重阻碍了相互之间的交流。

  3,整洁

  日常生活中我们谈起整洁,头脑中大概会浮现出这样的场景:每样物品都有序地摆放在它应该在的地方,一目了然,并且一尘不染,非常干净,令人愉快;同时,不那么明显的,整洁往往暗示着没有多余的东西,东西越少,越容易保持整洁。

  整洁的代码有同样的特征:

1) 有序,各得其所,模块的归模块,接口的归接口,实现的归实现。

  处理对于人脑来说过于复杂的东西,自古以来有效的办法就是分解,将大的分解成小的,使人脑在某一时刻只需要思考小的部分。要做到这点,除了分解,还需要保持模块和模块之间联系尽可能少,只有这样你才能专注思考眼前这一块,而不必过于担心它和其它模块的相互影响。同样,只有这样,当软件发生变动的时候,你才不至于陷入焦油坑。

  相关术语:结构化、分层、抽象、解耦、正交、降低依赖、大量原则(SRPOCPLSP…)

  2) 一目了然。

  流畅,没有障碍,它应该就是这个样子,而不是别的样子。任何维护工作的第一件事是什么?读代码。

  相关术语:可读、文字化编程(Kunth)、自解释。

  3) 一尘不染。

  重点是保持。如果一直保持干净,一旦出现污点,将会显得非常刺眼,自然会被清除。相反,一扇窗户破了,若无人关心,最终整条街道都会腐化。

  相关术语:重构、温水煮青蛙。

  4) 只做必要的事,保持简单。

  从奥卡姆开始,到建筑,到飞机制造。完成不是指不能再往里塞东西,而是指不能再往外拿任何东西。

  相关术语:KISS、敏捷。

  5) 令人愉快。

  成功永远令人愉快,美永远令人愉快。

  相关术语:诗歌

  4,其它

  也许你已经发现了,如果保持代码整洁,似乎就可以应对多种复杂度(但不是所有),这也是为什么好代码除了可用,还需要整洁。

  本文只是描述我心目中的好代码,并不打算说明如何编写好代码,那需要太多的篇幅(和太多的争议)。所以,至此为止。


评论:

发表评论

最新评论:


圈内热点

  • 怎么轻松学习JavaScript

    js给初学者的印象总是那么的“杂而乱”,相信很多初学者都在找轻松学习js的途径。我试着总结自己学习多年js的经验,希望能给后来的学习者探索出一条“轻松学习js之路”。

  • 我心目中的ASP.NET核心对象

    在我的眼里,Asp.net有三大核心对象:HttpContext, HttpRequest, HttpResponse。除此之外,还有二个对象虽然称不上核心,但仍然比较重要:HttpRuntime,HttpServerUtility

  • IIS内部运行机制

    这篇文章的资料收集整理自各种微软公开的文档,通过比较 IIS5、IIS6、IIS7 这三代 IIS 对请求的处理过程, 让我们熟悉 ASP.NET的底层机制并对请求(request)是怎么从Web服务器传送到ASP.NET运行时有所了解

  • 改善程序员生活质量的3+10习惯

    2017年的一天,代码伴随着手指极具节奏感地输出在IDE上,突然某Chrome插件弹出一封邮件提示:“今天是我在ThoughtWorks的最后一天”。

  • 编程的一些伟大真理

    编程学习中的一些伟大真理,初级程序员都知道吗?

回到顶部