编程原则(Programming Principles)

        我们如何可以写出更易于维护的,更易于扩展的,更稳定的,更整洁的、复杂度更低的、生命周期更长的代码呢?我相信这个应该是每个优秀coder的梦想;当然每个coder对于实现写出更优秀的代码可能会有自己独到的见解,但是对于大家都公认的一些比较好的代码设计原则应该都会比较认同,本文将简单介绍一些代码编程原则。如果仅仅有了解了编程原则是不足够写出优秀的代码,还需要我们不断的实践和在适合的场景中应用,进行不同的原则的抉择。

本文受The Principles of Good Programming启发。我觉得这份列表已经足够了,但这并不完全符合我个人的想法。此外,我还需要更多的论证、细节以及其他资料的链接。

通用

  • [KISS (Keep It Simple Stupid)]
  • [YAGNI]
  • [做最简单的事情]
  • [关注点分离]
  • [保持事情不再重复]
  • [为维护者写代码]
  • [避免过早优化]
  • [童子军军规]

模块间/类

  • [最小化耦合]
  • [迪米特法则]
  • [组合优于继承]
  • [正交性]
  • [稳健性原则]
  • [控制反转]

模块/类

  • [最大化聚合]
  • [里氏代换原则]
  • [开放/封闭原则]
  • [单一职责原则]
  • [隐藏实现细节]
  • [科里定律]
  • [封装经常修改的代码]
  • [接口隔离原则]
  • [命令查询分离]
编程规则Programing Principles.png

KISS

大多数系统如果保持简单而不是复杂,效果最好。

为什么?

  • 更少的代码可以花更少的时间去写,Bug更少,并且更容易修改。
  • 简单是复杂的最高境界。
  • 完美境地,非冗杂,而不遗。

相关资料

YAGNI

YAGNI的意思是“你不需要它”:在必要之前不要做多余的事情。

为什么

  • 去做任何仅在未来需要的特性,意味着从当前迭代需要完成的功能中分出精力。
  • 它使代码膨胀;软件变得更大和更复杂。

怎么做

  • 在当你真正需要它们的时候,才实现它们,而不是在你预见到你需要它们的时候。

相关资料

做最简单的事情

为什么

  • 仅有当我们只解决问题本身时,才能最大化地解决实际问题。

怎么做

  • 扪心自问:“最简单的事情是什么?”。

相关资料

关注点分离

关注点分离是一种将计算机程序分离成不同部分的设计原则,以便每个部分专注于单个关注点。例如,应用程序的业务逻辑是一个关注点而用户界面是另一个关注点。更改用户界面不应要求更改业务逻辑,反之亦然。

引用Edsger W. Dijkstra (1974)所说:

我有时将其称为“关注点分离”,即使这不可能完全做到,但它也是我所知道的唯一有效的思维整理技巧。这就是我所说的“将注意力集中在某个方面”的意思:这并不意味着忽略其他方面,只是对于从某一方面的视角公正地来看,另一方面是不相关的事情。

为什么

  • 简化软件应用程序的开发与维护。
  • 当关注点很好地分开时,各个部分可以被重用,并且可以独立开发和更新。

怎么做

  • 将程序功能分成联系部分尽可能少的模块。

相关资料

保持事情不再重复

在一个系统内,每一项认识都必须有一个单一的、明确的、权威的表示。

程序中的每一项重要功能都应该只在源代码中的一个地方实现。相似的函数由不同的代码块执行的情况下,抽象出不同的部分,将它们组合为一个函数通常是有益的。

为什么

  • 重复(无意或有意的重复)会造成噩梦般的维护,保养不良和逻辑矛盾。
  • 对系统中任意单个元素的修改不需要改变其他逻辑上无关的元素。
  • 此外,相关逻辑的元素的变化都是可预测的和均匀的,因此是保持同步的。

怎么做

  • 只在一个处编写业务规则、长表达式、if语句、数学公式、元数据等。
  • 确定系统中使用的每一项认识的唯一来源,然后使用该源来生成该认识的适用实例(代码、文档、测试等)。
  • 使用三法则(Rule of three).

相关资料

相似资料

为维护者写代码

为什么

  • 到目前为止,维护是任何项目中最昂贵的阶段。

怎么做

相关资料

避免过早优化

引用Donald Knuth所说:

程序员浪费大量的时间来思考或担心程序的非关键部分的速度,而考验尝试这些优化实际上在调试和维护时有很强的负面影响。比如说在97%的开发时间,我们应该忽略低效率:过早的优化是万恶之源。然而,我们不应该在关键的3%中放弃我们的机会。

当然,需要理解什么是“过早”什么不是“过早”。

为什么

  • 瓶颈在哪是未知的。
  • 优化后,阅读和维护可能会更困难。

怎么做

相关资料

最小化耦合

模块/组件之间的耦合是它们互相依赖的程度,较低的耦合更好。换句话说,耦合是代码单元“B”在未知的代码单元“A”更改后“被破坏”的几率。

为什么

  • 一个模块的更改通常会导致其他模块的更改,产生涟漪效益。
  • 由于模块间的依赖性增加,模块装配可能需要更多的工作和/或时间。
  • 特定的模块可能难以重用和/或测试,因为必须包含相关模块。
  • 开发人员可能害怕更改代码,因为他们不确定什么会收到影响。

怎么做

  • 消除,最小化和降低必要关联的复杂性。
  • 通过隐藏实现细节,减少耦合。
  • 使用[迪米特法则]。

相关资料

迪米特法则【Law of Demeter or Least Knowledge Principle(LoD or LKP)】

迪米特法则或最少知道原则。它讲的是“一个对象就尽可能少的去了解其它对象”,从而实现松耦合。如果一个类的职责过多,由于多个职责耦合在了一起,任何一个职责的变更都可能引起其它职责的问题,严重影响了代码的可维护性和可重用性。

为什么

  • 这通常会导致更紧密的耦合。
  • 可能会暴露过多的实现细节。

怎么做

对象的方法只能调用以下方法:

  1. 对象自身的方法。
  2. 方法参数中的方法。
  3. 方法中创建的任何对象的方法。
  4. 对象的任何直接属性或字段的方法。

相关资料

组合优于继承

为什么

  • 类之间的耦合减少。
  • 使用继承,子类很容易做出假设,并破坏里氏代换原则(LSP)。

怎么做

  • 测试LSP(可替换性)以决定何时继承。
  • 当存在“有”(或“使用”)的关系时使用组合,当存在“是”的关系时使用继承。

相关资料

正交性

正交性的基本概念是,概念上不相关的东西在系统中不应该相关。

来源:Be Orthogonal

它越简单,设计越正交,异常就越少。这使得用编程语言学习、读写程序变得更容易。正交特征的含义是独立于环境;关键参数是对称性与一致性。

来源:Orthogonality

稳健性原则

坚持保守自己的作为,自由接受他人的作为。

合作的服务依赖于彼此的接口。通常,接口需要提升,导致另一端接收未指定的数据。如果接收到的数据没有严格遵守规范,那么简单的实现将仅拒绝合作。更复杂的实现却可以忽略它无法识别的数据。

为什么

  • 为了能够提高服务,你需要确保提供者可以进行更改以支持新的需求,同时对现有客户端造成最小的破坏。

怎么做

  • 向其他机器(或同一机器上的其他程序)发送指令或数据的代码应该完全符合规范,但接受输入的代码应接受不一致的输入,只要其意义明确。

相关资料

控制反转

控制反转又被称为好莱坞原则,“不要打电话给我们,我们会打电话给你”。它是一种设计原则,计算机程序的自定义编写部分从通用框架接收控制流。控制反转具有强烈的含义,即可重用代码和特定于问题的代码是独立开发的,即使它们在应用程序中一同工作。

为什么

  • 控制反转用于提高程序的模块性,使其具有可扩展性。
  • 将任务的执行与实现分离。
  • 将模块集中在其设计任务上。
  • 使模块不受关于其他系统如何执行其任务的假设约束,而是依赖于约定。
  • 以防止模块更换时出现副作用。

怎么做

  • 使用工厂模式
  • 使用服务定位器模式
  • 使用依赖注入
  • 使用依赖查找
  • 使用模板方法模式
  • 使用策略模式

相关资料

最大化聚合

单个模块/组件的聚合性是其职责形成有意义的单元的程度,越高的聚合性越好。

为什么

  • 增加了理解模块的难度。
  • 增加了维护系统的难度,因为域中逻辑的更改会影响多个模块,并且一个模块的更改需要相关模块的更改。
  • 由于大多数应用程序不需要模块提供的随机操作集,因此重用模块的难度增加。

怎么做

  • 与组相关的功能共享一项职责(例如在一个类中)。

相关资料

里氏替换原则【Liskov Substitution Principle(LSP)】

里氏替换原则(LSP)完全是关于对象的预期行为:

程序中的对象应该可以替换为其子类型的实例,而不会改变该程序的正确性。

相关资源

开-闭原则【Open-Close Principle(OCP)】

软件实体(例如类)应对扩展是开放的,但对修改是封闭的。也就是说,这样的实体可以允许在不改变其源代码的情况下修改其行为。

为什么

  • 通过最小化对现有代码的修改来提高可维护性和稳定性

怎么做

  • 编写可以扩展的类(而不是可以修改的类)
  • 只暴露需要更换的活动部分,隐藏其他所有部分。

相关资源

单一职责原则【Single Responsibility Principle(SRP)】

一个类不应该有多个修改的原因。

长话版:每个类都应该有一个单独的职责,并且该职责应该完全由该类封装。职责可以定义为修改的原因,一次类或模块应该有且仅有一个修改的原因。

为什么

  • 可维护性:仅有一个模块或类中需要修改。

怎么做

  • 使用 [科里定律]

相关资料

隐藏实现细节

软件模块通过提供接口来隐藏信息(即实现细节),而不泄露任何不必要的信息。

为什么

  • 当实现更改时,客户端使用的接口不必更改。

怎么做

  • 最小化类和成员的可访问性。
  • 不要公开成员数据。
  • 避免将私有实现细节放入类的接口中。
  • 减少耦合以隐藏更多实现细节。

相关资料

科里定律

科里定律是关于为任何特定代码选择一个明确定义的目标:仅做一件事。

封装经常修改的代码

一个好的设计可以辨别出最有可能改变的热点,并将它们封装在API之后。当预期的修改发生时,修改会保持在局部。

为什么

  • 在发生更改时,最小化所需的修改。

怎么做

  • 封装API背后不同的概念。
  • 将可能不同的概念分到各自的模块。

相关资料

接口隔离原则

将臃肿的接口减少到多个更小更具体的客户端特定接口中。接口应该比实现它的代码更依赖于调用它的代码。

为什么

  • 如果类实现了不需要的方法,则调用方需要了解该类的方法实现。例如,如果一个类实现了一个方法,但只是简单的抛出异常,那么调用方将需要知道实际上不应该调用这个方法。

怎么做

  • 避免臃肿的接口。类不应该实现任何违反[单一职责原则]的方法。

相关资料

童子军军规

美国童子军有一条简单的军规,我们可以使用到我们的职业中:“离开营地时比你到达时更干净”。根据童子军军规,我们应该至终保持代码比我们看到时更干净。

为什么

  • 当对现有代码库进行更改时,代码质量往往会降低,从而积累技术债务。根据童子军军规,我们应该注意每一个提交(Commit)的质量。无论规模有多小,技术债务都会受到不断重构的抵制。

怎么做

  • 每次提交都要确保它不会降低代码库的质量。
  • 任何时候,如果有人看到一些代码不够清楚,他们就应该抓住机会在那里修复它。

相关资料

命令查询分离

命令查询分离原则规定,每个方法都应该是执行操作的命令,或者是向调用者返回数据但不能同时做两件事的查询。提问不应该改变答案。

利用这个原则,程序员可以更加自信地进行编码。查询方法可以在任何地方以任何顺序使用,因为它们不会改变状态。而使用命令,你必须更加小心。

为什么

  • 通过将方法清晰地分为查询和命令,程序员可以在不了解每个方法的实现细节的情况下,更加自信地编码。

怎么做

  • 将每个方法实现为查询或命令。
  • 对方法名使用命名约定,该方法名表示该方法是查询还是命令。

相关资料

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容

  • 面向对象的七大设计原则文章目录面向对象的七大设计原则简述七大原则之间的关系一、开闭原则(The Open-Clos...
    LittleBear_6c91阅读 656评论 0 1
  • 闲言碎语 虽然几年前懵懵懂懂看完设计模式神书,可惜功力不够,无法透彻理解,也没有留下啥。现如今重拾神书,简述学习摘...
    双鱼子曰1987阅读 790评论 0 2
  • CSDN博客地址:https://blog.csdn.net/wf96390/article/details/89...
    o慢慢o阅读 602评论 0 0
  • Python6大设计原则 阅读目录 内容总览 六大设计原则都有哪些 一、单一职责原则 二、里氏替换原则 三、依赖倒...
    tomtiddler阅读 1,468评论 0 0
  • 在讲设计原则之前,我先强制灌输大家一波鸡汤,提倡面向接口编程,代码的设计更重要的是考虑以后的扩展和可维护性大家带着...
    DoneWillianm阅读 526评论 0 3