如何使得代码单元足够短小?

一个代码单元(方法或函数)应该足够小,这样的代码可维护性好。

一般一个代码单元应不超过15行。

那么如何使得代码单元足够小呢?

当代码单元过长时,可以对代码单元进行重构,通过“提取方法”的技巧来缩短代码单元。

下面以一个近似贪吃蛇的小程序的重构为例,演示下如何缩短代码单元的大小。

public void Start()
{
    if (inProgress)
    {
    return;
    }
    inProgress = true;
    // 如果玩家死亡则更新观察者:
    if(!IsAnyPlayerAlive())
    {
        for (LevelObserver o:observers) 
        {
        o.LevelLost();
        }
    }
    // 如果所有的豆都被吃光则更新观察者:
    if (RemainingPellets() == 0)
    {
        for (LevelObserver o :observers) 
        {
        o.LevelWon();
        }
    }
}

这个start代码单元共有21行(从第一个{开始计算,不算空行和注释),它已经超出了短小代码单元所要求的15行。下面我们就通过提取方法把它进行重构。

public void Start()
{
    if (inProgress)
    {
    return;
    }
    inProgress = true;
    Update0bservers();
}
private void UpdateObservers()
{
    // 如果玩家死亡则更新观察者:
    if (!IsAnyPlayerAlive())
    {
    for (LevelObserver o:observers) 
        {
            o.LevelLost();
        }
    }
    
    // 如果所有的豆都被吃光则更新观察者
    if(RemainingPellets() == 0)
    {
        for(LevelObserver o : observers)  
        {
            o.Levelwon();
        }
    }
)

上面的代码段中,start方法被缩短到8行。但是新提取出的UpdateObservers方法却有16行,这个方法中仍然包含两个职责,我们可以进一步来重构这段代码,再提取出两个方法:

public void UpdateObservers()
{
    Update0bserversPlayerDied();
    Update0bserversPelletsEaten();    
}

private void UpdateObserversPlayerDied() 
{
    if (!IsAnyPlayerAlive())
    {
        foreach (LevelObserver o in observers) 
        {
            o.LevelLost();
        }
    }
}

private void UpdateObserversPelletsEaten() 
{
    if (RemainingPellets() == 0)
    {
        foreach (LevelObserver o in observers) 
        {
            o.LevelWon();
        }
    }
}

重构后最终把一个start方法转换成了三个方法,虽然代码的总行数增加了,但每个单元的行数都小于15行,满足短小代码单元的要求。而且,使用短小代码单元之后,方法名就起到了注释的作用,不再需要增加注释。

这正是:

单元短小好处多,简单易测好维护

行数不超十五行,提取方法可保证

参考书目:代码不朽:编写可维护软件的十大要则,作者:(荷兰)约斯特·维瑟,译者:张若飞,出版社:电子工业出版社


作者简介:王小双,长期从事GJB5000推广、实施、评价、改进的工作,创建《软件工程之思》微信公众号,一直在《软件工程之思》分享GJB5000、CMMI、软件工程的知识和感悟。现致力于GJB5000咨询以及软件过程改进、软件工程能力提升的研究工作。

发表评论

登录后才能评论
服务中心
服务中心
联系客服
联系客服
返回顶部