一个函数应该写多长?

最近在看公司源代码的时候,经常有一些超长函数出现,甚至超过1000多行的函数都大有存在,这大大影响我对代码的理解,所以写下此文,当然只是自己的想法,不强加于人,只为勉励自己。

 

在以往的软件开发中,对于函数我也是想写多长就写多长,从来不去想它有多长这个“无聊的问题”,因为对于一个函数应该写多长并没有一个确切的定义,这应该看具体情况决定。

 

我个人觉得,无论是类还是函数,都应该满足单一职责原则,如果出现一个函数过长或者代码块嵌套过深的情况,常常是因为没有满足这一原则,这两种情况都能够通过更好的重构来解决。

 

 

以我工作中的一个代码片段为例来看一下,函数写多长,如何拆分函数。

  


 1/// <summary>
 2/// 时实窗体类
 3/// </summary>

 4public partial class iRealTimeInfo : Form
 5{
 6    ArrayList arrRealTime = new ArrayList();
 7
 8    public iRealTimeInfo()
 9    {
10        InitializeComponent();
11    }

12
13    /// <summary>
14    /// 加载窗体事件
15    /// </summary>

16    private void iRealTimeInfo_Load(object sender, EventArgs e)
17    {
18        从XML文件中读取并获得所有曲线实时模板类型
67
68        加载数据源对象列表
76
77        绑定模板下拉框
86
87        if (ListTemplate.Count == 0)
88        {
89            this.btnSubmit.Enabled = false;
90        }

91    }

92}

这是一个窗体的加载事件,运行过程是这样,首先从系统模板配置文件中找到实时模板类型信息,然后验证该信息中指定的模板类型文件是否存在,如果存在的话把XML文件中的实时模板信息加载到对象列表中,然后通过该模板类型列表得到一个绑定下拉框的数据源对象列表,用来绑定下拉框。

 

上面函数中算很长的了,函数过长的一个原因是因为临时变量,因为临时变量只有在所属函数中才能使用,所以它会驱使你写出更长的函数,所以我们在开发过程中尽量少用或不用临时变量(可以使用一些重构准则实现)。函数过长的另一个原因是它承担了过多的职责,上面函数承担了多项职责:加载XML文件来获取模板信息对象列表;加载数据源对象列表;绑定模板下拉框等,我们首先把这三个职责抽取出来,分别用一个专职的函数来实现。

  

Code Step2

 

通过上面的重构过程,加载事件看起来容易理解一点,但是对于XML文件的处理过程还是很复杂,另外,我们在此类中处理模板下拉框并显示实时模板数据的,而处理XML的职责也写在了此类中,所以此类也可以抽取出来,放在一个单独的类中,用来专门处理XML模板信息配置文件,最后处理结果如下:

 

 

Code Step3

 

 

当我们遇到过长的函数或者需要注释才能让人理解的代码块的时候,就应该考虑可不可以使用重构提取函数,不用管函数有多长,哪声只有一句,只要可以强化代码的清晰度,那就去做。就算提取出来的函数名称比函数体还长也无所谓。

 

过长的函数和嵌套过深的代码块(比如ifforwhiletry代码块)是使函数更难于理解和维护的密不可分的两大元凶(而且经常毫无必要)。

 

我们不必担心函数拆分过多的问题,函数调用的开销可以忽略不计,使用小函数有以下几个好处:

 

1 如果每个函数的粒度都很小,那么函数之间彼此复用的机会就更大;

2 使得高层代码读起来就像是一系列注释;

3 如果函数都很小,那么函数的覆写就比较容易;

 

在命名函数的时候,每个函数都应该是顾其名而能思其义,我们应该以它“做什么”来命名,而不是以它“怎么做”命名,只有在你可以给小函数很好地命名时,它们才能真正起作用。

 

 

posted @ 2009-07-01 12:40  xiaotou745  阅读(710)  评论(0编辑  收藏  举报