写点什么

《编程的原则》读书笔记 (二): 编程理论的三个思想和六个实现原则

作者:Chares
  • 2022 年 10 月 09 日
    北京
  • 本文字数:4296 字

    阅读完需:约 14 分钟

《编程的原则》读书笔记(二): 编程理论的三个思想和六个实现原则

✏️写作:个人博客InfoQ掘金知乎CSDN

📧公众号:进击的Matrix

🚫特别声明:原创不易,未经授权不得转载或抄袭,如需转载可联系小编授权。

前言


编程的理论 :A theory of programming


编程的理论是指导编程的思想。编程中,我们最重视编写出高质量的代码,编程有一套理论专门用来指导人们实现这种高质量的代码,该理论由以下三个思想作为支撑:


  • 交流

  • 简洁

  • 灵活性


在追求高质量代码的过程中,这些思想左右着我们的每一个决定。

为什么:将编程理论展示的思想作为技术的选择基准

编程在不同的问题领域有不同的技术和模式,虽然不能否认理解和掌握技术的重要性,但单纯的学习只能帮助我们了解技术的表面,并不能帮助我们真正学会使用这项技术。编程理论所展示的思想就是使用个项技术的理由。

怎么做:通过六个原则将编程理论展示的思想应用于代码

我们要把编程理论展示的思想用作判断基准,不过,把思想直接应用于实际编程未免有些抽象,所以我们需要一个“桥梁”来连接思想与编程。这里有六个原则可以充当二者之间的桥梁。


  • 效应局部化

  • 重复最小化

  • 逻辑与数据的一体化

  • 对称性

  • 声明式表达

  • 变动率

关联信息一: 视点

视点是我们使用某项技术时应该考虑的内容。视点是一种看待事物的方式,它能让我们的思想紧贴当前正在处理的问题。以下几点内容都属于视点。


  • 解决方案应满足的需求(例如需要进程间通信等)

  • 课题中包含的限制(例如进程间通信必须符合协议标准等)

  • 解决方案需要具备的特性(例如便于添加功能、添加的功能不影响现有功能等)


视点与视点之间可能是相辅相成的,也可能是相互排斥的。我们要做的就是掌握各视点之间的平衡。掌握了各视点之间的平衡的方案就是该课题的优秀解决方案。我们在选择代码的实现方法时,要以思想为“动机”,以原则为“桥梁”来选择代码的实现方法。

关联信息二:现有的工具是如何形成的


有一句格言——形态遵从于功能。


这句话是说工具的最终形态由目的决定。在学习技术的同时,我们需要了解它的工作原理, 演化过程和设计背景。只有这样,我们才更容易达成目的。一名好的程序员,不论面对何种语言、工具、技术和问题,都会花时间充分对其进行理解,然后开展工作。


编程理论的三大思想

交流:Communication


支撑编程理论的三大思想之①: 交流 Communication


代码是交流的场所,代码也是一种给人看的文档,而文档的本质在于交流。

为什么:顺利的开发源于顺利的交流

  • 节约维护成本,就需要提高代码的可读性。这是因为程序员之间需要通过代码进行交流。

  • 读代码的时间远多于写代码的时间。

怎么做:从代码阅读者的角度出发

刚开始编写代码时,我们的思维很容易停留在如何编写出能让计算机正常处理的代码上。此时不妨改变一下视角,思考他人是如何看待这段代码的。


把思考的重点从计算机转移到代码阅读者的身上,就是所谓的换位思考。代码不仅是输入到编译器和解释器中的信息,也是写给人看的“文章”。

简洁:Simplicity


支撑编程理论的三大思想之②: 简洁 Simplicity


消除代码的复杂性

为什么:代码的复杂性是罪魁祸首

“多余的复杂性”不具有任何价值。这类复杂性会阻碍代码正常运行,提高修改代码的难度,损害软件的价值,它会给代码埋下祸根。

怎么做:分清代码中的"玉"与"石"

如何保持代码简洁?在设计时,将代码的本质部分(玉)放在显眼的位置,保证其他元素(石)不会混入其中。


简洁能给交流带来好的影响,消除多余的复杂性后,留下来的本质部分会更加显眼,代码也变得更易于理解。


不过,简洁越交流偶尔也会发生冲突,过度简洁会使代码变得难以理解,这种情况时,我们需要牺牲一部分的简洁性,把交流放在优先的位置。

灵活性:Flexibility


支撑编程理论的三大思想之③:灵活性 Flexibility


代码的灵活性是指修改代码的难易程度。“灵活”是指在添加新代码的时候,已有代码能够不受影响、不产生冲突、不出现排斥、在保证自身不遭到破坏的前提下灵活的接纳新代码。

为什么:代码必然会被修改

代码早晚会被修改,因此,易于修改、具有灵活性成了代码的必备条件。

怎么做:提高代码的可扩展性

要让代码具有灵活性,就要保证代码易于扩展且扩展时不会波及无关的元素。


灵活性也是一把双刃剑,代码易于修改自然是好事。但灵活性往往会成为将复杂的代码或设计正当化的借口。


不能以牺牲简洁性为前提来提高灵活性,因为多余的灵活性是无用的,为这种灵活性服务的代码到头来很可能成为一堆带来多余复杂性的无用代码。为了写出灵活且简洁的代码,我们需要克制住展现小技巧的欲望。


实现编程理论的六个原则

效应局部化


实现编程理论的六个原则之①:效应局部化 Local consequences


减少修改带来的影响,效应局部化是指将修改带来的影响控制在局部,是一个很重要的原则,围绕该原则产生了许多技术,模块化就是其中之一,模块化技术的目标之一就是让修改模块所带来的影响停留在该模块的内部。

为什么:更易于修改和确认

在效应非局部化的情况下,某处修改会对其他完全不相关的地方造成影响,使修改成本大幅增加。


效应局部化还有让交流更加顺畅的效果。在效应局部化的情况下,程序员只要理解当前阶段所涉及的代码即可,不需要一次性掌握所有代码。

怎么做:整合关系紧密的代码

在编写代码时,要让关系紧密的代码集中在一起,同时保证关联性较弱的代码不互相依赖,为此,我们需要将关系紧密的代码集中起来实现模块化。


从关联性角度来看,我们要格外注意相互频繁调用的模块。模块之间相互频繁调用通常表明原本应该放在一起的要素被分别放在了不同的模块中。


这种时候就需要让合适的单一模块来实现功能,或者将模块功能整合在一起,或者重新创建一个模块来实现相应的功能。总之要保证单一功能的密集性。

重复最小化


实现编程理论的六个原则之②:重复最小化 Minimize repetition


重复最小化,就是指极力消除重复,有许多技术都以实现重复最小化为目标,函数化技术就是其中之一。

为什么: 将修改带来的影响局部化

重复的代码不符合效应局部化原则,增加了修改成本。

怎么做: 对代码进行分割管理

我们要将代码分割成多个小块,将代码模块化,代码的可读性就会提高,修改的成本也会下降。

逻辑与数据的一体化


实现编程理论的六个原则之③:逻辑与数据的一体化 Logic and Data together


将数据与逻辑放在相近的位置,逻辑与数据的一体化是指把逻辑和改逻辑处理的数据放在相近的位置。所谓相近的位置,指的是在同一函数或同一模块内。距离越近,代码的质量就越高。

为什么:数据与逻辑往往需要同时修改

修改代码时往往需要同时修改逻辑与该逻辑处理的数据。从结果来看,降低了修改成本。

怎么做:将数据与逻辑放在相近的位置

要把数据与逻辑放在相近的位置编写、运行代码之后、数据与逻辑的关联性会渐渐显露出来,是让代码靠近数据,还是让数据靠近代码;


是将代码和数据取出来放到其他位置,还是不进行任何变动,对于这些问题,我们会在不断尝试的过程中逐渐了解具体的做法。

对称性


实现编程理论的六个原则之④: 对称性 Symmetry


让代码具有一贯性,对称性一般指事物中对某种变换保持不变的性质。编程中的对称性要比图形中的对称性抽象得多。编程中的对称性是指相同的思路在代码的任何地方都以相同的形式表现出来。简单来说,就是组内的等级整理。

为什么:可以类推其他部分

代码中明确表现出对称性后,代码的可读性将大幅提高。追求对称性从本质来说属于消除重复代码的准备工作。当代码中存在多个相似的部分时,如果对其进行对称化处理,相同的思路就会以相同的形式表现出来。此后只要将完全相同的部分整合到一起,就可以消除代码中重复的内容了。

怎么做:相同的东西用相同的形式表现

在编写代码的时候,同类的东西要用相同的形式表现,具体如下:


  • 如果有“添加”方法,就创建与之相对的“删除”方法

  • 同组的函数用相同的参数

  • 让同一个模块里的数据拥有相同的生存周期

  • 函数内所有的调用函数的抽象级别要相同

声明式表达


实现编程理论的六个原则之⑤:声明式编程 Declarative Expression


声明式表达是指在表达代码意图时,尽量用“声明式”的表达方式,而非“命令式”的表达方式。


命令式编程描述的是问题的解决方法,也就是数据结构与算法。二声明式编程描述的是问题的定义,也就是当前问题的性质以及解决问题的时应该满足的限制条件。

为什么:没有流程方面的限制,可读性更高

声明式的代码没有流程方面的限制,这种单纯阐述事实的表达方式能够提升代码的可读性。


另外一方面,我们要正确理解命令式的代码,就必须时常在脑中描述其状态、控制及数据流。为此,我们必须跟着代码的流程走向来进行阅读。

怎么做:采用声明式表达方式

采用声明式的表达方式,简洁地表达意图。当编程范式使用了声明式语言时,由于编写出的代码是声明式的,所以不用我们去特别注意什么。比如函数式语言就是声明式通用编程语言中的一个典型代表,另外,HTML、CSS 和 SQL 等非通用语言也都是声明式的。

变动率


实现编程理论的六个原则之⑥:变动率 Rate of Change


按修改理由进行分组,变动率体现了修改代码的时间点,变动率相同意味着代码在同一时间点被修改。同时修改的元素要放在同一个地方,在不同时间点修改的元素要放在不同的地方。

为什么:能缩小修改范围

在模块等按照某种单位分组的代码中,有多个修改理由的代码比较脆弱,因为一个模块中如果修改代码的时间不同步,那么修改带来的影响将会波及无关的部分。


相反,如果模块只存在一个修改理由,就代表该模块由关联性极强的代码集合而成,这类模块满足高内聚性,非常牢固。因为修改范围较小,影响范围也小,所以模块修改起来比较轻松。

怎么做:根据修改理由分配位置

修改时间相同的元素要放在同一个地方,修改时间不同的元素要放在不同的地方。这对逻辑和数据来说都适用。


先看逻辑:举个例子,如果税额计算包括“一般计算逻辑”和“各年固有逻辑”两种,这两种逻辑就要分别放在不同的地方,因为二者的修改时间明显不同。这样一来,每年在修改“各年固有逻辑”时,就能保证“一般计算逻辑”不受影响。


在看数据:比如,模块中的一部分数据只在执行某个特定函数时才使用,这时,就要将这部分数据移至函数中,把他们用作本地变量。


另外,即使某个模块中存在一些同时被修改的数据,如果这些数据不存在与其他变量同步修改的必然性。我们也要把这些数据移至别的(辅助)模块中。

关联信息:单一职责原则

“单一职责原则”(the Single Responsibility Principle,SRP)规定一个模块只能有一个修改理由。


有多个修改理由就意味着模块承担了多项职责,我们不可以创建这样的模块。


模块的某个部分有多个修改理由就证明改模块违反了单一职责原则,一个模块只承担一项职责,模块必须专注于某项职责。


变动率原则可以帮助我们实现这种状态。将变动率相同的代码放在一起,自然而然就能形成满足单一职责原则的。


发布于: 2022 年 10 月 09 日阅读数: 34
用户头像

Chares

关注

Stay hungry, Stay foolish 2018.08.12 加入

公众号:【进击的Matrix】 知乎:【可乐】 掘金:【Chares】

评论

发布
暂无评论
《编程的原则》读书笔记(二): 编程理论的三个思想和六个实现原则_软件工程_Chares_InfoQ写作社区