代码大全 code complete阅读笔记-3 第十四章 代码的结构(顺序与无序)

组织直线型代码

我对这句话的理解是:要让你的代码符合人的阅读习惯——由上到下。
代码不应该只是纯粹为了通过编译而写,更重要的是要让人更容易读懂,这也是编程的艺术,如果所有代码的目的都仅仅是通过编译可以运行就行,那编程还有什么艺术感美感可言,这里粗略的将代码分为以下两类:

  1. 必须有明确顺序的语句
  2. 顺序无关的语句

1.必须有明确顺序的语句

当语句之间有依赖关系时,后一语句的执行必须依赖前一语句的结果
(下面所提的子程序可以理解为方法或者某一可执行模块)

data = ReadData();
results = CalculateResultsFromData();
PrintResults(result);

这段代码就能看出前后之间的依赖性,也就是它们非按这个顺序运行不可。
如果语句之间存在这样的关系,那么就一定要尽可能将它们这种关系明显清晰地表达出来,这样更有利程序的可读性,接下来是相应的一些组织代码的原则:

  1. 使依赖关系变得明显
    要点在于使语句的功能尽量精简而明确,每一个子程序应该有自己明确的处理任务,比如计算方法就不应该让它承担变量初始化的工作,并且这样做更有利于为子程序起名,因为ComputeXxxxAndInitiatialXxxxx() 终归是太长了,不如分为两行ComputeXxxx()InitatialXxxxx()
    这样做虽然更麻烦,但是却更灵活更清晰,你不仅一眼可以看出两个动作的先后顺序,更可以自由的在两个动作之间再加入新的动作。

  2. 使子程序名能凸显依赖关系
    如之前所说,一个子程序不应该做它自己名字内容以外的事,否则它就是一个糟糕的子程序。

  3. 使子程序参数明确显示依赖关系
    上面的代码就是一个很好的例子。

4.使用状态变量或者错误处理码

它还有一个更高大上的名字——内务管理变量 (housekeeping variables)
这里加粗是因为这对我来说是一个新事物,当然这也是十分重量的做法,一般用于十分重要的类或者方法中,当然不建议到处滥用。
例如:

class DataOperation{
	boolean isDataPrepared;
	//准备就绪
	void getPrepared(){
		isDataprepared = true;
	};
	void addData(){
		if(this.isDataPrepared==true){
			//如果为true,方可执行
		}else{
		return;
		}
	}
}

在一个类中添加一个布尔成员变量isDataPrepared,并在构造器中将其初始化为false,j假设增删改查方法在执行前必须检查isDataPrepared变量,若为true方可执行,如此必然可以得出getPrepare()方法必须优先得到执行,否则后续无法操作。

当然这样做的是有风险的,因为它引入了更多的变量,修改了构造器,并且你必须要为其编写出错代码,所以我们需要在它的利弊之间权衡。

  1. 使用注释来对不清晰的依赖关系进行说明
    这就是最下策了,当你的程序不允许你对它进行结构上的调整时,那你就只能用注释加以说明了。我们更应该依赖上面的方法而不是依赖于注释。

2.顺序无关的语句

就近原则(Principle of Proximity):把相关操作放在一起。

十分好理解了,相关操作指同一个对象的方法,同一个类的方法等应该放在一起,而不是不同的方法穿插在一起。
这里画一个图来生动表示:
代码大全 code complete阅读笔记-3 第十四章 代码的结构(顺序与无序)_第1张图片

这样做的好处是:

  1. 尽可能缩小对象的存活(alive)行数。
    明明两个方法可以连续执行完后就不需要引用方法的对象了,那就没必要在两个方法之间掺杂其他操作。尽量减少对象闲置无操作的代码行数,这样的好处是使程序更加清爽,一定程度提高了程序的性能。
  2. 使代码易于自上而下的阅读。

要点 key point

  • 组织线性代码的最主要原则是按照依赖关系进行排列
  • 可以用好的子程序名、参数列表、注释,以及——如果代码足够重要——内务管理变量可以让依赖关系表现的更加明显
  • 如果代码之间没有顺序依赖关系,那就设法使相关的语句尽可能接近

你可能感兴趣的:(阅读笔记)