(图侵删 玩笑脸)
子程序定义:为实现一个特定的目的而编写的一个可被调用的方法或过程。
创建子程序的正当理由
- 降低复杂度
- 引入中间、易懂的抽象
- 隐藏内部的实现细节
- 缩小代码规模
- 改善可维护性
- 提高正确性
改善性能
如果你的程序中有一个长长的函数,那么意味上面的你可能一条都不沾
低质量的子程序
差劲的子程序名字
没有文档
代码布局不好
子程序没有一个单一的目的
没有错误处理
使用神秘数据(没有意义的单纯数字)
参数过多
参数顺序混乱且未经注释
如何优化子程序
引入中间抽象: 子程序内部的逻辑抽象出来一个新的函数, 在原来的子程序中调用
public void doSometihing(){
// 将本来在函数内实现的逻辑抽象到别的函数中去
String name = getName();
...
}
支持子类化: 将原有的函数放到父类中, 使用继承就能使用父类中除私有外的函数,这样意外着子类中要构建的函数更少
// 在子类对象使用父类的方法, 这样你不用去构造一个一样的方法
public Class SonClass extends FatherClass{
}
public Class OrderClass{
public static final main(String [] arge){
SonClass son = new SonClass();
son.doSomething();
}
}
避免代码重复(这个不用说)
隐藏操作顺序: 将一个过程的操作顺序抽象出来,私有,只保留出入口, 让逻辑函数能将注意力放在目前要进行的业务处理上
// 原来的程序
public void doSometihing(){
...
InputStream inputStream=socket.getInputStream();
InputStreamReader inputStreamReader=new InputStreamReader(inputStream);
BufferedReader bufReader=new BufferedReader(inputStreamReader);
...
}
// 修改之后, 你完全在io 流程中 不用关心io流的写入, 专心做自己的逻辑控制
public void doSometihing(){
...
InputStream inputStream=socket.getInputStream();
BufferedReader bufReader = getBufferedReader (inputStream);
...
}
public BufferedReader getBufferedReader (InputStream inputStream){
InputStreamReader inReader = new InputStreamReader(inputStream);
return new BufferedReader(inReader);
}
提高可移植性
可以使用子程序来隔离不可移植的部分。 让自己的代码适应在不同的环境(语言提供的非标准特型、对硬件和操作系统的依赖)下工作 。
简化控制流程判断
1 将判断抽象到别的函数中
2 使用一个具象的命名来表达
改善性能:
这样方便查出运行效率低下的代码,更容易给多个函数分别优化性能
隔离复杂度,限制变化带来的影响
隐藏全局数据
初始化返回值
在函数开头用一个默认值来初始化返回值,能够在未正确返回值时提供一张保护网
// 原来的代码
public void doSomeThing(){
String strCode = "";
strCode = getCode() == null ? strCode : getCode();
return strCode ;
}
// 修改初始值之后
public String getCode(){
String strCode = "FA0001";
strCode = getCode() == null ? strCode : getCode();
strCode = getCode
}
在子程序层上设计
目的
通过开头给出的子程序的定义,我们可以知道,子程序为了实现单一目的而生
内聚性:
指的是子程序中各个操作的紧密程度, 虽然在面向对象发展很多年的今天,更多人在编程时更讲究的是抽象和封装,但是内聚还是一直存在
- 功能内聚
- 最高级的内聚, 让子程序只执行一个操作
- 顺序上的内聚
- 比较次级的内聚, 需要按照特定的顺序进行操作,这些操作步骤需要共享数据,而且只有在全部执行完毕之后,才算完成一项完整的功能
- 通讯上的内聚
- 指的是子程序在不同的操作中使用了同种数据,但子程序之间没有联系
- 临时内聚
- 不同的功能需要同时执行才放到一起
- 过程上的内聚
- 指的是子程序中的操作是按特定的顺序执行
- 逻辑上的内聚
- 他们之间没有关联,只是在判断逻辑的时候放到一起
- 巧合内聚性
- 无内聚性,混乱内聚性
- 子程序的长度
- 60行之内 之前有做过说明,这里不做复述
如何使用子程序参数
按照输入-修改-输出的顺序排列参数
反例:随机、按字母顺序
正例:仅作为输入参数 à 既是输入又是输出的参数 à 仅作为输出的参数
考虑自己创建IN和OUT关键字
- 预处理定义IN和OUT(起说明性作用)
- 注释内描述
- 注意:
1、确保一致的使用该定义方法。
2、不要混淆IN和const的作用。
如果几个子程序都用了类似的一些参数,应该让这些参数的排列顺序保持一致
例:fprintf()/printf、fputs/puts、strncpy/memcpy。使用所有的参数
往一个子程序中传递一个参数,就一定要使用这个参数。如果你不要它,请尽快把它从接口中删除。把状态和出错变量放在参数表最后
它们只是附属于程序的主要功能,而且它们是仅用于输出的变量。应该对哪些接口参数的假定说明(注释):
参数是仅用于输入的、要被修改的、还是仅用于输出的。
表示数量的参数的单位(英寸、英尺、米等)。
状态代码和错误值的含义。
接受的数值的范围。
不该出现的特定数值。把子程序的参数个数限制在3个以内, 3个参数以上,考虑创建一个类来包裹参数
- 考虑对参数采用某种表示输入、修改、输出的命名规则
认为区分输入、修改、输出参数很重要的话,就建立一种命名规则来进行区分。 使用具名参数
确保实际参数和形式参数相匹配