创建高质量的代码_3(读书笔记)

高质量的子程序

在讨论高质量的子程序的细节之前,明确下面这两个基本术语会很有帮助。首先,什么是“子程序(routine)”? 子程序是为实现一个特定的目的而编写的一个可被调用的方法(method)或过程(procedure)。

抛开计算机本身,子程序也算得上是计算机科学中一项最重大的发明了。子程序的使用使得程序变得更加易读,更易于理解,比在任何编程语言的任何功能特性都更容易。

子程序也是迄今为止发明出来的用以节约空间和提高性能的最重要手段。

3.1  创建子程序的正当理由

下面概况了创建子程序的一些理由

-  降低复杂度;

-  引入中间的、易懂从抽象;

-  避免代码代码重复;

-  支持子类化;

-  隐藏顺序;

-  隐藏指针操作;

-  提高可移植性;

-  简化复杂的逻辑判断;

-  改善性能;

除此之外,创建类的很多理由也是创建子程序的理由:

-  隔离复杂度;

-  隐藏实现细节;

-  限制变化所带来的影响;

-  隐藏全局数据;

-  形成中央控制点;

-  促成可重用的代码;

-  达到特定的重构目的;


3.2  在子程序层上设计

首先来理解一个概念,内聚性。对子程序而言,内聚性是指子程序中各种操作之间联系的紧密程度。我们的目标是让每一个子程序只把一件事情做好,不再做任何其他事情。这样做的好处是得到更高的可靠性。

关于内聚性的讨论一般会涉及到内聚性的几个层次。理解一些概念要比记住一些特定的术语更重要。这些概念可以帮助你思考如何让子程序尽可能地内聚。

功能的内聚性:是最强也是最好的一种内聚性,也就是说让一个子程序仅执行一项操作。

当然,以这种方式来评估内聚性,前提是子程序所执行的操作与其名字相符——如果它还做了其他的操作,那么它就不够内聚,同时其命名也有问题。

除此之外,还有其他一些种类的内聚性人们却通常认为是不够理想的。比如:顺序上的内聚性、通信上的内聚性、临时的内聚性。

为了得到更好的内聚性,可以把不同的操作纳入各自的子程序中。让调用方的子程序具有单一而完整的功能。为了让所有的子程序都具有功能上的内聚性,对两个或更多的原有子程序进行修改是很常见的。

这些术语中没有哪个是神秘的或者圣神不可侵犯的。需要理解的是其中的想法,而不是那些术语。编写具有功能上的内聚性的子程序几乎总是可能的,因此把注意力集中于功能上的内聚性,从而得到最大的收获。


3.3  好的子程序名字

好的子程序名字能清晰地描述子程序所做的一切。这里是有效地给子程序命名的一些指导原则。

- 描述子程序所做的所有事情;

- 避免使用无意义的、模糊或表述不清的动词;

- 不要仅通过数字来形成不同的子程序名字;

- 根据需要确定子程序名字的长度;

-  给函数命名时要返回值有所描述

- 给过程起名时使用语气强烈的动词加宾语的形式;

- 准确使用对仗词;

- 为常用操作确立命名规则。

3.4  如何使用子程序参数

-  按照输入-修改-输出的顺序排列参数。不要随机地或按字母顺序排列参数,而应该先列出仅作为输入用途的参数,然后是既作为输入又作为输出用途的参数,最后才是仅作为输出用途的参数。这种排列方法暗含了子程序的内部操作所发生的顺序——先是输入数据,然后修改数据,最后输出结果。

- 如果几个子程序都用了类似的一些参数,应该让这些参数的排列顺序保持一致。

- 使用所有的参数。

- 把状态或出错变量放在最后。按照习惯做法,状态变量和那些用于指示发生错误的变量应该放在参数表的最后。它们只是附属于程序的主要功能,而且它们是仅用于输出的参数,因此这是一种很有道理的规则。

- 不要把子程序的参数用做工作变量。把传入子程序的参数用做工作变量是很危险的。应该使用局部变量。

- 在接口中对参数的假定加以说明。如果你假定了传递给子程序的参数具有某种特征,那就要对这种假定加以说明。在子程序内部和调用子程序的地方同时对所做的假定进行说是值得的。不要等到把子程序写完了之后再回过头去写注释——你是不会记住所有这些假定的。一种比用注释还好的方法,是在代码中使用断言(assertions)。

应该对这些接口参数的假定进行说明:参数是仅用于输入的、要被修改的、还是仅用于输出的;表示数量的参数的单位;如果没有枚举类型的话,应该说明状态代码和错误值的含义;所能接受的数值的范围;不该出现的特定数值。

- 把子程序的参数个数限制在大约7个以内。在实践中,子程序中参数的个数到底应该限制在多少,取决于你所使用的编程语言如何支持复杂的数据类型。如果你使用的是一种支持结构化数据的现代编程语言,你就可以传递一个含有13个成员的合成数据类型,并将它看作一个大数据块。如果你使用的是一种更为原始的编程语言,那你可能需要分别传递全部13个成员。

如果你发现自己一直需要传递很多参数,这就说明子程序之间的耦合太过紧密了。应该重新设计这个或这组子程序,降低其间的耦合度。如果你向很多不同的子程序传递相同的数据,就请把这些子程序组成一个类,并把那些经常使用的数据用作类的内部数据。

- 考虑对参数采用某种表示输入、修改、输出的命名规则。

- 为子程序传递用以维持其接口抽象的变量或对象。

- 确保实际参数与形式参数相匹配。



核对表:  高质量的子程序

大局事项

-  创建子程序的理由充分吗?

-  一个子程序中所有适于单独提出的部分是不是已经被提出到单独的子程序中了?

-  过程的名字中是否用了强烈、清晰的“动词+宾语”词组?函数的名字是否描述了其返回值?

-  子程序的名字是否描述了它所做的全部事情?

-  是否给常用的操作建立了命名规则?

-  子程序是否具有强烈的功能上的内聚性?即它是否做且只做一件事情,并且把它做得很好?

-  子程序之间是否有较松的耦合?子程序与其他子程序之间的连接是否是小的、明确的、可见的和灵活的?

-  子程序的长度是否是由其功能和逻辑自热确定,而非遵循任何人为的编码标准?

参数传递适宜

-  整体来看,子程序的参数表是否表现出一种具有整体性且一致的接口抽象?

-  子程序参数的排列顺序是否合理?是否与类似的子程序的参数排列顺序相符?

-  接口假定是否已在文档中说明?

-  子程序的参数个数是否没超过7个?

-  是否用到了每一个输入参数?是否用到了每一个输出参数?

-  子程序是否避免了把输入参数用做工作变量?

-  如果子程序是一个函数,那么它是否在所有可能的情况下都能返回一个合法的值?

要点

-  创建子程序最主要的目的是提高程序的可管理性,当然也有其他一些好的理由。其中,节省代码空间只是一个次要的原因;提高可读性、可靠性和可修改性等原因都更重一些。

-  有时候,把一些简单的操作写成独立的子程序也非常有价值。

-  子程序可以按照其内聚性分为很多类,而你应该让大多数子程序具有功能上的内聚性,这是最佳的一种内聚性。

-  子程序的名字是它的质量的指示器。如果名字糟糕但恰如其分,那就说明这个子程序设计得很差劲。如果名字糟糕且又不准确,那么它就反映不出程序是干什么的。不管怎样,糟糕的名字都意味着程序需要修改。

-  只有在某个子程序的主要目的是返回有其名字所描述的特定结果时,才应该使用函数。

-  细心的程序员会非常谨慎地使用宏,而且只在万不得已时才用。

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

推荐阅读更多精彩内容

  • 第一部分 打好基础 Laying the Foundation 第一章 欢迎进入软件构建的世界 Welcome t...
    白桦叶阅读 4,519评论 0 17
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,111评论 18 139
  • 本文将从变量,语句,代码块,子程序,到类以及框架设计,详细描述了如何编写高质量的程序。尽管大部分原则你可能都知道了...
    动感小前端阅读 2,029评论 6 28
  • 软件构件中的设计 设计中的挑战 “软件设计”一词意味着去构思、创造或者发明一套方案,把一份计算机软件的规格说...
    9d710097e616阅读 513评论 0 0
  • 心有所系时,梦中犹在;望穿秋水兮,白黑如一,奈何心有万千结。结不解,心难脱,何日卧石环翠墨?半杯茶香半杯醉,竹门半...
    腰间盘突出阅读 218评论 0 2