本文我将分享作为一名专业程序员多年来学到的、能切实提高代码质量与整体工作效率的 10 条经验。

1. 永远不要复制代码

不惜一切代价避免代码重复。如果一个常用的代码片段出现在程序中的多个不同地方,请重构它,将其封装到独立的函数中。重复的代码会让同事在阅读你的代码时产生困惑。更严重的是,如果在一处修改了重复代码却忘记修改其他地方,会导致 Bug 遍布各处,还会使代码体积变得臃肿。

现代编程语言提供了很好的机制来解决这些问题。例如,以下问题在过去较难处理,而如今使用 Lambda 表达式却能轻松实现:

/// <summary>
/// 一些函数含有部分重复代码
/// </summary>
void OriginalA()
{
    DoThingsA();

    // unique code

    DoThingsB();
}

/// <summary>
/// 另外一个含有部分重复代码的函数
/// </summary>
void OriginalB()
{
    DoThingsA();

    // 没有重复的代码

    DoThingsB();
}

现在我们可以重构含有相同代码部分的函数,使用 Delegate 模式重写它们:

/// <summary>
/// Encapsulate shared functionality
/// </summary>
/// <param name="action">User defined action</param>
void UniqueWrapper(Action action)
{
    DoThingsA();

    action();

    DoThingsB();
}

/// <summary>
/// New implmentation of A
/// </summary>
void NewA()
{
    UniqueWrapper(() =>
    {
        // unique code
    });
}

/// <summary>
/// New implementation of B
/// </summary>
void NewB()
{
    UniqueWrapper(() =>
    {
        // unique code
    });
}

2. 留意你开始分心的时候

当你发现自己在浏览 Facebook 或微博,而不是在解决问题时,这通常是一个信号:你需要短暂休息了。离开办公桌,去喝一杯咖啡,或跟同事聊五分钟。尽管这样做看起来有点反直觉,但从长远来看,它会提高你的工作效率。

3. 不要因匆忙赶任务而放弃原则

当带着压力去解决问题或修复 Bug 时,你很容易失去自制,变得匆匆忙忙,甚至完全忘掉一直坚持的重要测试流程。这通常会导致更多的问题,也会让你在老板或同事眼里显得很不专业。

4. 测试你完成的代码

你知道你的代码能做什么,而且试了一下确实好用,但你实际上需要充分地验证它。分析所有可能的边界情况,测试在所有可能的条件下它都能如期工作。如果有参数,传递一些预期范围外的值,传递一个 null 值。如果可能,让同事看看你的代码,问他们能否弄坏它。单元测试 是达到这种目的的常规方法。

5. 代码审查

提交代码之前,找个同事一起坐下来,向他解释你做了哪些修改。通常,在这样的过程中你就能发现代码中的错误,甚至不需要同事说一句话。这比自己审查自己的代码要有效得多。

6. 让代码更少

如果你发现写了大量的代码来解决一个简单的问题,你很可能做错了。下面的 Boolean 用法就是一个很好的例子:

if (numMines > 0)
{
   enabled = true;
}
else
{
   enabled = false;
}

这时你应该写成这样:

enabled = numMines > 0;

代码越少越好。这会使 Bug 更少,重构的可能性更小,出错的几率更低。但要适度,可读性同等重要,你不能为了精简代码而牺牲可读性。

7. 为优雅的代码而努力

优雅的代码非常易读,只用手边很少的代码、让机器做很少的运算就能解决问题。在各种环境中都做到代码优雅是很难的,但经过一段时间的编程,你会对“优雅的代码是什么样”有个初步的感觉。优雅的代码不会通过重构来获得,当你看到优雅的代码时会很高兴,你会为它自豪。

例如,下面就是一个我认为是优雅的计算多边形面积的方法:

static public double GetConvexPolygonArea(Vector2[] vertices)
{
    double area = 0;
    for (int i = 0; i < vertices.Length; i++)
    {
        Vector2 P0 = vertices[i];
        Vector2 P1 = vertices[(i + 1) % vertices.Length];

        area += P0.Wedge(P1);
    }

    return area / 2;
}

8. 编写不言自明的代码

毋庸置疑,注释是编程中很重要的一部分,但能够不言自明的代码更胜一筹,因为它能让你在看代码时就能理解它。函数名、变量名要慎重选择,好的变量或方法名字放到语言语义环境中时,甚至不懂编程的人都能看懂。例如:

void DamagePlayer(Player player, int damageAmount)
{
    if (!player.m_IsInvincible && !player.m_IsDead)
    {
        player.InflictDamage(damageAmount);
    }
}

能自我说明的代码不能代替注释。注释是用来解释“为什么”的,而自我说明的代码是用来描述“是什么”的。

9. 不要使用纯数字

直接把数字嵌入代码中是一种恶习,因为无法说明它们代表什么。当有重复时更糟糕——相同的数字在代码的多个地方出现。如果只修改了一个而忘记了其它的,就会导致 Bug。一定要用一个命名常量来代表你要表达的数字,即使它在代码里只出现一次。

10. 不要做手工劳动

当做一系列动作时,人类总是喜欢犯错误。如果你在做部署工作,并且不是一步能完成的,那你就是在做错事。尽量让工作能自动化完成,减少人为错误。当做工作量很大的任务时,这尤其重要。

11. 避免过早优化

当你要去优化一个已经好用的功能代码时,你很有可能会改坏它。优化只能发生在有性能分析报告指示需要优化的时候,通常是在一个项目开发的最后阶段。性能分析之前的优化活动纯属浪费时间,并且会导致 Bug 出现。

好吧,我说是 10 个,但你却得到了额外赠送的一个!

这些就是我要说的,我希望它们能帮助你改进编程开发过程。

下次再见!祝快乐!

Cheers, Paul.

[英文原文:10 steps to becoming a better programmer ]

说明:本文核心观点源自 2012 年发表的技术文章,所述编程原则(如 DRY、单元测试、代码审查等)至今仍具有广泛的适用性。