怎样写好函数? —— 读《Clean Code》Function一章

曾经看过一种说法,写代码最难的是命名,当时不能理解。这么多年写下来,发现真的是这样,一个好的变量名或者函数名,要简短,又要反应足够的逻辑。确实很难,并不是一句玩笑话。
与此类似的是,如何写好一个函数,也不是那么简单的。曾经我们认为不管代码写成什么样,只要能做到最后的功能,它们就都是一样的。真的是这样吗?
就好比,围棋的布局阶段。你可以说,不管布局怎么下,只要最后赢棋就可以了。但如果布局阶段失败,会让你的中盘官子处处被动。败局从一开始就注定了的。
写代码也是这样,虽然函数可以想怎么写就怎么写,虽然最后的功能可以实现,但是后续的阅读,扩展,重构会越来越困难。最终积重难返,败局也是从一开始就注定了的。
那么如何真正的写好一个函数呢?Uncle Bob用他的经验,给了我们很多操作性很高的指导。

什么样是一个好的函数?

本文完全是Clean Code一书Function一章的摘录。有些加入了我一些自己的认识。本文可以作为文摘阅读,具体可以查阅原文。

small!

Functions should hardly ever be 20 lines long.

Uncle Bob心目中理想的函数的样子:

Every function in this program was just two, or three, or four lines long.

  • Each was transparently obvious. Each told a story.
  • And each led you to the next in a compelling order.

That’s how short your functions should be!

实际上,我们很难做到一个函数只有2~4行,尤其像C语言这样强类型的非OO语言。如果刻意的为了短而短,牺牲了可读性,倒是没什么必要。但以我的经验做到不超过20行还是可以做到的。而且应该做到。

Blocks and Indenting

这个是说应该有一个良好且统一的编程格式风格。这个在我经历的公司已经都达成了共识了。所以不再赘述。

Do One Thing

我们知道设计模式中有一个SRP(Single Response Principle)原则。函数也应该符合SRP原则。

FUNCTIONS SHOULD DO ONE THING. THEY SHOULD DO IT WELL. THEY SHOULD DO IT ONLY.

但其实这句话说起来简单,做起来还是很不容易的。

If a function does only those steps that are one level below the stated name of the function, then the function is doing one thing. After all, the reason we write functions is to decompose a larger concept (in other words, the name of the function) into a set of steps at the next level of abstraction.

也就是说,一个函数只对其名称描述的功能做一层分解。
例如:

void handle_command(unsigned char *buf, size_t size)
{
    if (0 = strcmp(buf, "cmd1")) {
        int i = sizeof(struct header);
        buf[i] = 1;
        buf[i+1] = 2;
    }
}

这里应该当判断到命令是cmd1时,不应当在内联命令处理的代码,因为这已经是2级抽象了,应当是:

void handle_command(unsigned char *buf, size_t size)
{
    if (0 = strcmp(buf, "cmd1")) {
        handle_cmd1(buf, size);
    }
}

这就是所谓的一级抽象。特别是你想写这样的分段注释的时候:

public static int[] generatePrimes(int maxValue)
{
    if (maxValue >= 2) // the only valid case
    {
        // declarations
        int s = maxValue + 1;
        
        // size of array
        boolean[] f = new boolean[s];
        int i;
        // initialize array to true.
        for (i = 0; i < s; i++)
            f[i] = true;

        // get rid of known non-primes
        f[0] = f[1] = false;
        ...
    }
}

每一个section就可以提炼成一个函数。当你想用注释把一个函数分成一段一段的,每一段是一个步骤,那么就是机会提炼函数,提供抽象层级。

Switch Statements

这里是说switch泛滥,到处都是长长的对类型switch的语句。而这种情况通常可以由面向对象来解决。

The solution to this problem (see Listing 3-5) is to bury the switch statement in the basement of an ABSTRACT FACTORY, 9 and never let anyone see it.

对于C语言这种弱OO的语言,就要就事论事了。但通常C也是可以应用OO的一些思想来重构这种switch的问题。

My general rule for switch statements is that they can be tolerated if they appear only once, are used to create polymorphic objects, and are hidden behind an inheritance

Use Descriptive Names

这个不再赘述,它有多重要,应该已经得到共识。

Function Arguments

我们现实的编程生活中,函数参数也是非常容易忽视的地方。很多时候,我们为了信息传递的方便,参数一下4,5个,非常常见。却不自知,这样的代码味道很不好。

The ideal number of arguments for a function is zero (niladic). Next comes one (monadic), followed closely by two (dyadic). Three arguments (triadic) should be avoided where possible. More than three (polyadic) requires very special justification—and then shouldn’t be used anyway.

在看Uncle Bob的Clean Code之前,其实我也没有过多的关注函数参数的个数,只是偶尔隐隐的觉得调用参数多的函数时,有一种很茫然不知从何开始的感觉。要么翻阅文档,要么查看源码,总归是不那么直接,要费点力气。你看这里作者就明确指出了,参数越少越好(当然这我们也知道),超过3个就要慎重考虑了,尽量避免使用3个及以上个数的参数(作者说的优点夸张,shouldn’t be used anyway,绝对不许使用)。
参数个数多,代表代码有一些坏味道(代码坏味道由Martin Fowler在他的Refactoring一书里提出,即指虽然代码功能没问题,但却在向不好的方向发展,越来越坏,最后就可能出问题了)。

  • They take a lot of conceptual power.
    因为参数不属于函数名表达的抽象层次,所以要知道参数是什么意思,只能看调用时是怎么传入的。然后在阅读函数的时候要时时记得。
  • Arguments are even harder from a testing point of view. Imagine the difficulty of writing all the test cases to ensure that all the various combinations of arguments work properly.
  • Output arguments are harder to understand than input arguments. When we read a function, we are used to the idea of information going in to the function through arguments and out through the return value. We don’t usually expect information to be going out through the arguments.

一个参数的函数(Monadic Function)

有两种情况,很适合使用单参数函数:

  • transformation,做转换或者映射,把参数集映射到输出集
  • event:The overall program is meant to interpret the function call as an event and use the argument to alter the state of the system

标志位参数

Passing a boolean into a function is a truly terrible practice. It immediately complicates the signature of the method, loudly proclaiming that this function does more than one thing.
这时候应该做的是,用不同的函数名来阐述标志位想区分的情况。

两个参数的函数(Dydadic Function)

两个参数要比一个参数难理解的多,因为你需要理解参数的顺序是怎么回事儿。但作者也说了:

Dyads aren’t evil, and you will certainly have to write them. However, you should be aware that they come at a cost and should take advantage of what mechanims may be available to you to convert them into monads.

有两个参数的时候,就要慎重了。总是要尝试找机会转换成单参数的函数。实践来看,想转总是容易的。但是转完之后要符合逻辑语意,有时候就没那么容易了。但总归还是要去尝试,能让函数调用变得更加clean。

三个参数的函数(Triads)

Functions that take three arguments are significantly harder to understand than dyads. The issues of ordering, pausing, and ignoring are more than doubled. I suggest you think very carefully before creating a triad.

没啥好说的,三个参数比两个参数引入的额外effort翻倍都不止。所以尽量避免。
作者也提到了一个好的三个参数的例子:assertEquals(1.0, amount, .001)。对float变量的判断,第三个参数引入精度值,这样让调用者返回查看函数原型时,能够得到提醒,对于浮点数来说,相等总是相对的。

Argument Objects

When a function seems to need more than two or three arguments, it is likely that some of those arguments ought to be wrapped into a class of their own.

Reducing the number of arguments by creating objects out of them may seem like cheating, but it’s not. When groups of variables are passed together, they are likely part of a concept that deserves a name of its own.

Verbs and Keywords

这里作者想提醒的是为函数起一个好名字。最好就是用动词+名词的搭配,能阐述的更加清楚。例如:
assertEquals就没有assertExpectedEqualsActual(expected, actual)好。后者体现了参数顺序。
write(name)没有writeField(name)好。因为前者不知道name修饰的是什么,后者告诉我们name是一个field name。

Have No Side Effects

Side effects are lies. Your function promises to do one thing, but it also does other hidden things.
If you must have a temporal coupling, you should make it clear in the name of the function.

函数不要有side effect,也就是focus一件事情。我觉得这里的side effect应该不包括更新全局变量或者类对象的成员变量。

Command Query Separation

Functions should either do something or answer something, but not both. Either your function should change the state of an object, or it should return some information about that object.

这里的意思还是保持SRP,函数要么反应某个object的状态,要么对object做一些操作。对比下面两种写法:

if (setAndCheckIfExists("username", "unclebob"))...

if (attributeExists("username")) {
    setAttribute("username", "unclebob");
    ...
}

Don’t Repeat Yourself

DRY原则,这个也无需赘述

Duplication may be the root of all evil in software.

Prefer Exceptions to Returning Error Codes

使用exception便于在同一个地方处理错误情况。如果用return error code的方式,只能在error发生的地方处理。坏处是,正常逻辑的代码和错误代码会混合在一起。

Thus, a function that handles errors should do nothing else. This implies (as in the example above) that if the keyword try exists in a function, it should be the very first word in the function and that there should be nothing after the catch/finally blocks.

处理error的所有代码应该放在一起。不过这里的建议不适用于纯C编程,因为我们没有try-catch。

总结

写好一个函数看似简单,但其实难度不亚于起一个优雅又清晰的名字。Clean Code一书给了不少建议,其实可以反复参阅,勤加重构。
这些建议中,目前我认为重要的是篇首的几个,特别是Function Arguments特别发人警醒。

  • Small!
  • Do one thing
  • One Level of Abstraction per Function
  • Use Descriptive Names
  • Function Arguments
%0A%E6%9B%BE%E7%BB%8F%E7%9C%8B%E8%BF%87%E4%B8%80%E7%A7%8D%E8%AF%B4%E6%B3%95%EF%BC%8C%E5%86%99%E4%BB%A3%E7%A0%81%E6%9C%80%E9%9A%BE%E7%9A%84%E6%98%AF%E5%91%BD%E5%90%8D%EF%BC%8C%E5%BD%93%E6%97%B6%E4%B8%8D%E8%83%BD%E7%90%86%E8%A7%A3%E3%80%82%E8%BF%99%E4%B9%88%E5%A4%9A%E5%B9%B4%E5%86%99%E4%B8%8B%E6%9D%A5%EF%BC%8C%E5%8F%91%E7%8E%B0%E7%9C%9F%E7%9A%84%E6%98%AF%E8%BF%99%E6%A0%B7%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%A5%BD%E7%9A%84%E5%8F%98%E9%87%8F%E5%90%8D%E6%88%96%E8%80%85%E5%87%BD%E6%95%B0%E5%90%8D%EF%BC%8C%E8%A6%81%E7%AE%80%E7%9F%AD%EF%BC%8C%E5%8F%88%E8%A6%81%E5%8F%8D%E5%BA%94%E8%B6%B3%E5%A4%9F%E7%9A%84%E9%80%BB%E8%BE%91%E3%80%82%E7%A1%AE%E5%AE%9E%E5%BE%88%E9%9A%BE%EF%BC%8C%E5%B9%B6%E4%B8%8D%E6%98%AF%E4%B8%80%E5%8F%A5%E7%8E%A9%E7%AC%91%E8%AF%9D%E3%80%82%0A%E4%B8%8E%E6%AD%A4%E7%B1%BB%E4%BC%BC%E7%9A%84%E6%98%AF%EF%BC%8C%E5%A6%82%E4%BD%95%E5%86%99%E5%A5%BD%E4%B8%80%E4%B8%AA%E5%87%BD%E6%95%B0%EF%BC%8C%E4%B9%9F%E4%B8%8D%E6%98%AF%E9%82%A3%E4%B9%88%E7%AE%80%E5%8D%95%E7%9A%84%E3%80%82%E6%9B%BE%E7%BB%8F%E6%88%91%E4%BB%AC%E8%AE%A4%E4%B8%BA%E4%B8%8D%E7%AE%A1%E4%BB%A3%E7%A0%81%E5%86%99%E6%88%90%E4%BB%80%E4%B9%88%E6%A0%B7%EF%BC%8C%E5%8F%AA%E8%A6%81%E8%83%BD%E5%81%9A%E5%88%B0%E6%9C%80%E5%90%8E%E7%9A%84%E5%8A%9F%E8%83%BD%EF%BC%8C%E5%AE%83%E4%BB%AC%E5%B0%B1%E9%83%BD%E6%98%AF%E4%B8%80%E6%A0%B7%E7%9A%84%E3%80%82%E7%9C%9F%E7%9A%84%E6%98%AF%E8%BF%99%E6%A0%B7%E5%90%97%EF%BC%9F%0A%E5%B0%B1%E5%A5%BD%E6%AF%94%EF%BC%8C%E5%9B%B4%E6%A3%8B%E7%9A%84%E5%B8%83%E5%B1%80%E9%98%B6%E6%AE%B5%E3%80%82%E4%BD%A0%E5%8F%AF%E4%BB%A5%E8%AF%B4%EF%BC%8C%E4%B8%8D%E7%AE%A1%E5%B8%83%E5%B1%80%E6%80%8E%E4%B9%88%E4%B8%8B%EF%BC%8C%E5%8F%AA%E8%A6%81%E6%9C%80%E5%90%8E%E8%B5%A2%E6%A3%8B%E5%B0%B1%E5%8F%AF%E4%BB%A5%E4%BA%86%E3%80%82%E4%BD%86%E5%A6%82%E6%9E%9C%E5%B8%83%E5%B1%80%E9%98%B6%E6%AE%B5%E5%A4%B1%E8%B4%A5%EF%BC%8C%E4%BC%9A%E8%AE%A9%E4%BD%A0%E7%9A%84%E4%B8%AD%E7%9B%98%E5%AE%98%E5%AD%90%E5%A4%84%E5%A4%84%E8%A2%AB%E5%8A%A8%E3%80%82%E8%B4%A5%E5%B1%80%E4%BB%8E%E4%B8%80%E5%BC%80%E5%A7%8B%E5%B0%B1%E6%B3%A8%E5%AE%9A%E4%BA%86%E7%9A%84%E3%80%82%0A%E5%86%99%E4%BB%A3%E7%A0%81%E4%B9%9F%E6%98%AF%E8%BF%99%E6%A0%B7%EF%BC%8C%E8%99%BD%E7%84%B6%E5%87%BD%E6%95%B0%E5%8F%AF%E4%BB%A5%E6%83%B3%E6%80%8E%E4%B9%88%E5%86%99%E5%B0%B1%E6%80%8E%E4%B9%88%E5%86%99%EF%BC%8C%E8%99%BD%E7%84%B6%E6%9C%80%E5%90%8E%E7%9A%84%E5%8A%9F%E8%83%BD%E5%8F%AF%E4%BB%A5%E5%AE%9E%E7%8E%B0%EF%BC%8C%E4%BD%86%E6%98%AF%E5%90%8E%E7%BB%AD%E7%9A%84%E9%98%85%E8%AF%BB%EF%BC%8C%E6%89%A9%E5%B1%95%EF%BC%8C%E9%87%8D%E6%9E%84%E4%BC%9A%E8%B6%8A%E6%9D%A5%E8%B6%8A%E5%9B%B0%E9%9A%BE%E3%80%82%E6%9C%80%E7%BB%88%E7%A7%AF%E9%87%8D%E9%9A%BE%E8%BF%94%EF%BC%8C%E8%B4%A5%E5%B1%80%E4%B9%9F%E6%98%AF%E4%BB%8E%E4%B8%80%E5%BC%80%E5%A7%8B%E5%B0%B1%E6%B3%A8%E5%AE%9A%E4%BA%86%E7%9A%84%E3%80%82%0A%E9%82%A3%E4%B9%88%E5%A6%82%E4%BD%95%E7%9C%9F%E6%AD%A3%E7%9A%84%E5%86%99%E5%A5%BD%E4%B8%80%E4%B8%AA%E5%87%BD%E6%95%B0%E5%91%A2%EF%BC%9FUncle%20Bob%E7%94%A8%E4%BB%96%E7%9A%84%E7%BB%8F%E9%AA%8C%EF%BC%8C%E7%BB%99%E4%BA%86%E6%88%91%E4%BB%AC%E5%BE%88%E5%A4%9A%E6%93%8D%E4%BD%9C%E6%80%A7%E5%BE%88%E9%AB%98%E7%9A%84%E6%8C%87%E5%AF%BC%E3%80%82%0A%0A%23%23%20%E4%BB%80%E4%B9%88%E6%A0%B7%E6%98%AF%E4%B8%80%E4%B8%AA%E5%A5%BD%E7%9A%84%E5%87%BD%E6%95%B0%EF%BC%9F%0A%E6%9C%AC%E6%96%87%E5%AE%8C%E5%85%A8%E6%98%AFClean%20Code%E4%B8%80%E4%B9%A6Function%E4%B8%80%E7%AB%A0%E7%9A%84%E6%91%98%E5%BD%95%E3%80%82%E6%9C%89%E4%BA%9B%E5%8A%A0%E5%85%A5%E4%BA%86%E6%88%91%E4%B8%80%E4%BA%9B%E8%87%AA%E5%B7%B1%E7%9A%84%E8%AE%A4%E8%AF%86%E3%80%82%E6%9C%AC%E6%96%87%E5%8F%AF%E4%BB%A5%E4%BD%9C%E4%B8%BA%E6%96%87%E6%91%98%E9%98%85%E8%AF%BB%EF%BC%8C%E5%85%B7%E4%BD%93%E5%8F%AF%E4%BB%A5%E6%9F%A5%E9%98%85%E5%8E%9F%E6%96%87%E3%80%82%0A%23%23%23%20small%EF%BC%81%0A%3E%20Functions%20should%20hardly%20ever%20be%2020%20lines%20long.%0A%0AUncle%20Bob%E5%BF%83%E7%9B%AE%E4%B8%AD%E7%90%86%E6%83%B3%E7%9A%84%E5%87%BD%E6%95%B0%E7%9A%84%E6%A0%B7%E5%AD%90%EF%BC%9A%0A%3E%20Every%20function%20in%20this%20program%20was%20just%20two%2C%20or%20three%2C%20or%20four%20lines%20long.%20%0A%3E%20-%20**Each%20was%20transparently%20obvious.%20Each%20told%20a%20story.**%0A%3E%20-%20**And%20each%20led%20you%20to%20the%20next%20in%20a%20compelling%20order.**%0A%3E%20%0A%3E%20That%E2%80%99s%20how%20short%20your%20functions%20should%20be!%0A%0A%0A%E5%AE%9E%E9%99%85%E4%B8%8A%EF%BC%8C%E6%88%91%E4%BB%AC%E5%BE%88%E9%9A%BE%E5%81%9A%E5%88%B0%E4%B8%80%E4%B8%AA%E5%87%BD%E6%95%B0%E5%8F%AA%E6%9C%892%EF%BD%9E4%E8%A1%8C%EF%BC%8C%E5%B0%A4%E5%85%B6%E5%83%8FC%E8%AF%AD%E8%A8%80%E8%BF%99%E6%A0%B7%E5%BC%BA%E7%B1%BB%E5%9E%8B%E7%9A%84%E9%9D%9EOO%E8%AF%AD%E8%A8%80%E3%80%82%E5%A6%82%E6%9E%9C%E5%88%BB%E6%84%8F%E7%9A%84%E4%B8%BA%E4%BA%86%E7%9F%AD%E8%80%8C%E7%9F%AD%EF%BC%8C%E7%89%BA%E7%89%B2%E4%BA%86%E5%8F%AF%E8%AF%BB%E6%80%A7%EF%BC%8C%E5%80%92%E6%98%AF%E6%B2%A1%E4%BB%80%E4%B9%88%E5%BF%85%E8%A6%81%E3%80%82%E4%BD%86%E4%BB%A5%E6%88%91%E7%9A%84%E7%BB%8F%E9%AA%8C%E5%81%9A%E5%88%B0%E4%B8%8D%E8%B6%85%E8%BF%8720%E8%A1%8C%E8%BF%98%E6%98%AF%E5%8F%AF%E4%BB%A5%E5%81%9A%E5%88%B0%E7%9A%84%E3%80%82%E8%80%8C%E4%B8%94%E5%BA%94%E8%AF%A5%E5%81%9A%E5%88%B0%E3%80%82%0A%0A%23%23%23%20Blocks%20and%20Indenting%0A%E8%BF%99%E4%B8%AA%E6%98%AF%E8%AF%B4%E5%BA%94%E8%AF%A5%E6%9C%89%E4%B8%80%E4%B8%AA%E8%89%AF%E5%A5%BD%E4%B8%94%E7%BB%9F%E4%B8%80%E7%9A%84%E7%BC%96%E7%A8%8B%E6%A0%BC%E5%BC%8F%E9%A3%8E%E6%A0%BC%E3%80%82%E8%BF%99%E4%B8%AA%E5%9C%A8%E6%88%91%E7%BB%8F%E5%8E%86%E7%9A%84%E5%85%AC%E5%8F%B8%E5%B7%B2%E7%BB%8F%E9%83%BD%E8%BE%BE%E6%88%90%E4%BA%86%E5%85%B1%E8%AF%86%E4%BA%86%E3%80%82%E6%89%80%E4%BB%A5%E4%B8%8D%E5%86%8D%E8%B5%98%E8%BF%B0%E3%80%82%0A%0A%23%23%23%20Do%20One%20Thing%0A%E6%88%91%E4%BB%AC%E7%9F%A5%E9%81%93%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%B8%AD%E6%9C%89%E4%B8%80%E4%B8%AASRP%EF%BC%88Single%20Response%20Principle%EF%BC%89%E5%8E%9F%E5%88%99%E3%80%82%E5%87%BD%E6%95%B0%E4%B9%9F%E5%BA%94%E8%AF%A5%E7%AC%A6%E5%90%88SRP%E5%8E%9F%E5%88%99%E3%80%82%0A%3E%20**FUNCTIONS%20SHOULD%20DO%20ONE%20THING.%20THEY%20SHOULD%20DO%20IT%20WELL.%20THEY%20SHOULD%20DO%20IT%20ONLY.**%0A%0A%E4%BD%86%E5%85%B6%E5%AE%9E%E8%BF%99%E5%8F%A5%E8%AF%9D%E8%AF%B4%E8%B5%B7%E6%9D%A5%E7%AE%80%E5%8D%95%EF%BC%8C%E5%81%9A%E8%B5%B7%E6%9D%A5%E8%BF%98%E6%98%AF%E5%BE%88%E4%B8%8D%E5%AE%B9%E6%98%93%E7%9A%84%E3%80%82%0A%3E**If%20a%20function%20does%20only%20those%20steps%20that%20are%20one%20level%20below%20the%20stated%20name%20of%20the%20function%2C%20then%20the%20function%20is%20doing%20one%20thing.**%20After%20all%2C%20the%20reason%20we%20write%20functions%20is%20to%20decompose%20a%20larger%20concept%20(in%20other%20words%2C%20the%20name%20of%20the%20function)%20into%20a%20set%20of%20steps%20at%20the%20next%20level%20of%20abstraction.%0A%0A%E4%B9%9F%E5%B0%B1%E6%98%AF%E8%AF%B4%EF%BC%8C%E4%B8%80%E4%B8%AA%E5%87%BD%E6%95%B0%E5%8F%AA%E5%AF%B9%E5%85%B6%E5%90%8D%E7%A7%B0%E6%8F%8F%E8%BF%B0%E7%9A%84%E5%8A%9F%E8%83%BD%E5%81%9A%E4%B8%80%E5%B1%82%E5%88%86%E8%A7%A3%E3%80%82%0A%E4%BE%8B%E5%A6%82%EF%BC%9A%0A%60%60%60c%0Avoid%20handle_command(unsigned%20char%20*buf%2C%20size_t%20size)%0A%7B%0A%20%20%20%20if%20(0%20%3D%20strcmp(buf%2C%20%22cmd1%22))%20%7B%0A%20%20%20%20%20%20%20%20int%20i%20%3D%20sizeof(struct%20header)%3B%0A%20%20%20%20%20%20%20%20buf%5Bi%5D%20%3D%201%3B%0A%20%20%20%20%20%20%20%20buf%5Bi%2B1%5D%20%3D%202%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%E8%BF%99%E9%87%8C%E5%BA%94%E8%AF%A5%E5%BD%93%E5%88%A4%E6%96%AD%E5%88%B0%E5%91%BD%E4%BB%A4%E6%98%AFcmd1%E6%97%B6%EF%BC%8C%E4%B8%8D%E5%BA%94%E5%BD%93%E5%9C%A8%E5%86%85%E8%81%94%E5%91%BD%E4%BB%A4%E5%A4%84%E7%90%86%E7%9A%84%E4%BB%A3%E7%A0%81%EF%BC%8C%E5%9B%A0%E4%B8%BA%E8%BF%99%E5%B7%B2%E7%BB%8F%E6%98%AF2%E7%BA%A7%E6%8A%BD%E8%B1%A1%E4%BA%86%EF%BC%8C%E5%BA%94%E5%BD%93%E6%98%AF%EF%BC%9A%0A%60%60%60c%0Avoid%20handle_command(unsigned%20char%20*buf%2C%20size_t%20size)%0A%7B%0A%20%20%20%20if%20(0%20%3D%20strcmp(buf%2C%20%22cmd1%22))%20%7B%0A%20%20%20%20%20%20%20%20handle_cmd1(buf%2C%20size)%3B%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%E8%BF%99%E5%B0%B1%E6%98%AF%E6%89%80%E8%B0%93%E7%9A%84%E4%B8%80%E7%BA%A7%E6%8A%BD%E8%B1%A1%E3%80%82%E7%89%B9%E5%88%AB%E6%98%AF%E4%BD%A0%E6%83%B3%E5%86%99%E8%BF%99%E6%A0%B7%E7%9A%84%E5%88%86%E6%AE%B5%E6%B3%A8%E9%87%8A%E7%9A%84%E6%97%B6%E5%80%99%EF%BC%9A%0A%60%60%60java%0Apublic%20static%20int%5B%5D%20generatePrimes(int%20maxValue)%0A%7B%0A%20%20%20%20if%20(maxValue%20%3E%3D%202)%20%2F%2F%20the%20only%20valid%20case%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%2F%2F%20declarations%0A%20%20%20%20%20%20%20%20int%20s%20%3D%20maxValue%20%2B%201%3B%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%2F%2F%20size%20of%20array%0A%20%20%20%20%20%20%20%20boolean%5B%5D%20f%20%3D%20new%20boolean%5Bs%5D%3B%0A%20%20%20%20%20%20%20%20int%20i%3B%0A%20%20%20%20%20%20%20%20%2F%2F%20initialize%20array%20to%20true.%0A%20%20%20%20%20%20%20%20for%20(i%20%3D%200%3B%20i%20%3C%20s%3B%20i%2B%2B)%0A%20%20%20%20%20%20%20%20%20%20%20%20f%5Bi%5D%20%3D%20true%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20get%20rid%20of%20known%20non-primes%0A%20%20%20%20%20%20%20%20f%5B0%5D%20%3D%20f%5B1%5D%20%3D%20false%3B%0A%20%20%20%20%20%20%20%20...%0A%20%20%20%20%7D%0A%7D%0A%60%60%60%0A%E6%AF%8F%E4%B8%80%E4%B8%AAsection%E5%B0%B1%E5%8F%AF%E4%BB%A5%E6%8F%90%E7%82%BC%E6%88%90%E4%B8%80%E4%B8%AA%E5%87%BD%E6%95%B0%E3%80%82%E5%BD%93%E4%BD%A0%E6%83%B3%E7%94%A8%E6%B3%A8%E9%87%8A%E6%8A%8A%E4%B8%80%E4%B8%AA%E5%87%BD%E6%95%B0%E5%88%86%E6%88%90%E4%B8%80%E6%AE%B5%E4%B8%80%E6%AE%B5%E7%9A%84%EF%BC%8C%E6%AF%8F%E4%B8%80%E6%AE%B5%E6%98%AF%E4%B8%80%E4%B8%AA%E6%AD%A5%E9%AA%A4%EF%BC%8C%E9%82%A3%E4%B9%88%E5%B0%B1%E6%98%AF%E6%9C%BA%E4%BC%9A%E6%8F%90%E7%82%BC%E5%87%BD%E6%95%B0%EF%BC%8C%E6%8F%90%E4%BE%9B%E6%8A%BD%E8%B1%A1%E5%B1%82%E7%BA%A7%E3%80%82%0A%0A%23%23%23%20Switch%20Statements%0A%E8%BF%99%E9%87%8C%E6%98%AF%E8%AF%B4switch%E6%B3%9B%E6%BB%A5%EF%BC%8C%E5%88%B0%E5%A4%84%E9%83%BD%E6%98%AF%E9%95%BF%E9%95%BF%E7%9A%84%E5%AF%B9%E7%B1%BB%E5%9E%8Bswitch%E7%9A%84%E8%AF%AD%E5%8F%A5%E3%80%82%E8%80%8C%E8%BF%99%E7%A7%8D%E6%83%85%E5%86%B5%E9%80%9A%E5%B8%B8%E5%8F%AF%E4%BB%A5%E7%94%B1%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E6%9D%A5%E8%A7%A3%E5%86%B3%E3%80%82%0A%3E%20The%20solution%20to%20this%20problem%20(see%20Listing%203-5)%20is%20to%20bury%20the%20switch%20statement%20in%20the%20basement%20of%20an%20**ABSTRACT%20FACTORY**%2C%209%20and%20never%20let%20anyone%20see%20it.%0A%0A%E5%AF%B9%E4%BA%8EC%E8%AF%AD%E8%A8%80%E8%BF%99%E7%A7%8D%E5%BC%B1OO%E7%9A%84%E8%AF%AD%E8%A8%80%EF%BC%8C%E5%B0%B1%E8%A6%81%E5%B0%B1%E4%BA%8B%E8%AE%BA%E4%BA%8B%E4%BA%86%E3%80%82%E4%BD%86%E9%80%9A%E5%B8%B8C%E4%B9%9F%E6%98%AF%E5%8F%AF%E4%BB%A5%E5%BA%94%E7%94%A8OO%E7%9A%84%E4%B8%80%E4%BA%9B%E6%80%9D%E6%83%B3%E6%9D%A5%E9%87%8D%E6%9E%84%E8%BF%99%E7%A7%8Dswitch%E7%9A%84%E9%97%AE%E9%A2%98%E3%80%82%0A%3EMy%20general%20rule%20for%20switch%20statements%20is%20that%20they%20can%20be%20tolerated%20if%20they%20**appear%20only%20once**%2C%20are%20used%20to%20**create%20polymorphic%20objects**%2C%20and%20are%20hidden%20behind%20an%20**inheritance**%0A%0A%23%23%23%20Use%20Descriptive%20Names%0A%E8%BF%99%E4%B8%AA%E4%B8%8D%E5%86%8D%E8%B5%98%E8%BF%B0%EF%BC%8C%E5%AE%83%E6%9C%89%E5%A4%9A%E9%87%8D%E8%A6%81%EF%BC%8C%E5%BA%94%E8%AF%A5%E5%B7%B2%E7%BB%8F%E5%BE%97%E5%88%B0%E5%85%B1%E8%AF%86%E3%80%82%0A%0A%23%23%23%20Function%20Arguments%0A%E6%88%91%E4%BB%AC%E7%8E%B0%E5%AE%9E%E7%9A%84%E7%BC%96%E7%A8%8B%E7%94%9F%E6%B4%BB%E4%B8%AD%EF%BC%8C%E5%87%BD%E6%95%B0%E5%8F%82%E6%95%B0%E4%B9%9F%E6%98%AF%E9%9D%9E%E5%B8%B8%E5%AE%B9%E6%98%93%E5%BF%BD%E8%A7%86%E7%9A%84%E5%9C%B0%E6%96%B9%E3%80%82%E5%BE%88%E5%A4%9A%E6%97%B6%E5%80%99%EF%BC%8C%E6%88%91%E4%BB%AC%E4%B8%BA%E4%BA%86%E4%BF%A1%E6%81%AF%E4%BC%A0%E9%80%92%E7%9A%84%E6%96%B9%E4%BE%BF%EF%BC%8C%E5%8F%82%E6%95%B0%E4%B8%80%E4%B8%8B4%EF%BC%8C5%E4%B8%AA%EF%BC%8C%E9%9D%9E%E5%B8%B8%E5%B8%B8%E8%A7%81%E3%80%82%E5%8D%B4%E4%B8%8D%E8%87%AA%E7%9F%A5%EF%BC%8C%E8%BF%99%E6%A0%B7%E7%9A%84%E4%BB%A3%E7%A0%81%E5%91%B3%E9%81%93%E5%BE%88%E4%B8%8D%E5%A5%BD%E3%80%82%0A%3E%20The%20ideal%20number%20of%20arguments%20for%20a%20function%20is%20zero%20(niladic).%20Next%20comes%20one%20(monadic)%2C%20followed%20closely%20by%20two%20(dyadic).%20Three%20arguments%20(triadic)%20should%20be%20avoided%20where%20possible.%20More%20than%20three%20(polyadic)%20requires%20very%20special%20justi%EF%AC%81cation%E2%80%94and%20then%20shouldn%E2%80%99t%20be%20used%20anyway.%0A%0A%E5%9C%A8%E7%9C%8BUncle%20Bob%E7%9A%84Clean%20Code%E4%B9%8B%E5%89%8D%EF%BC%8C%E5%85%B6%E5%AE%9E%E6%88%91%E4%B9%9F%E6%B2%A1%E6%9C%89%E8%BF%87%E5%A4%9A%E7%9A%84%E5%85%B3%E6%B3%A8%E5%87%BD%E6%95%B0%E5%8F%82%E6%95%B0%E7%9A%84%E4%B8%AA%E6%95%B0%EF%BC%8C%E5%8F%AA%E6%98%AF%E5%81%B6%E5%B0%94%E9%9A%90%E9%9A%90%E7%9A%84%E8%A7%89%E5%BE%97%E8%B0%83%E7%94%A8%E5%8F%82%E6%95%B0%E5%A4%9A%E7%9A%84%E5%87%BD%E6%95%B0%E6%97%B6%EF%BC%8C%E6%9C%89%E4%B8%80%E7%A7%8D%E5%BE%88%E8%8C%AB%E7%84%B6%E4%B8%8D%E7%9F%A5%E4%BB%8E%E4%BD%95%E5%BC%80%E5%A7%8B%E7%9A%84%E6%84%9F%E8%A7%89%E3%80%82%E8%A6%81%E4%B9%88%E7%BF%BB%E9%98%85%E6%96%87%E6%A1%A3%EF%BC%8C%E8%A6%81%E4%B9%88%E6%9F%A5%E7%9C%8B%E6%BA%90%E7%A0%81%EF%BC%8C%E6%80%BB%E5%BD%92%E6%98%AF%E4%B8%8D%E9%82%A3%E4%B9%88%E7%9B%B4%E6%8E%A5%EF%BC%8C%E8%A6%81%E8%B4%B9%E7%82%B9%E5%8A%9B%E6%B0%94%E3%80%82%E4%BD%A0%E7%9C%8B%E8%BF%99%E9%87%8C%E4%BD%9C%E8%80%85%E5%B0%B1%E6%98%8E%E7%A1%AE%E6%8C%87%E5%87%BA%E4%BA%86%EF%BC%8C%E5%8F%82%E6%95%B0%E8%B6%8A%E5%B0%91%E8%B6%8A%E5%A5%BD%EF%BC%88%E5%BD%93%E7%84%B6%E8%BF%99%E6%88%91%E4%BB%AC%E4%B9%9F%E7%9F%A5%E9%81%93%EF%BC%89%EF%BC%8C%E8%B6%85%E8%BF%873%E4%B8%AA%E5%B0%B1%E8%A6%81%E6%85%8E%E9%87%8D%E8%80%83%E8%99%91%E4%BA%86%EF%BC%8C%E5%B0%BD%E9%87%8F%E9%81%BF%E5%85%8D%E4%BD%BF%E7%94%A83%E4%B8%AA%E5%8F%8A%E4%BB%A5%E4%B8%8A%E4%B8%AA%E6%95%B0%E7%9A%84%E5%8F%82%E6%95%B0%EF%BC%88%E4%BD%9C%E8%80%85%E8%AF%B4%E7%9A%84%E4%BC%98%E7%82%B9%E5%A4%B8%E5%BC%A0%EF%BC%8Cshouldn%E2%80%99t%20be%20used%20anyway%EF%BC%8C%E7%BB%9D%E5%AF%B9%E4%B8%8D%E8%AE%B8%E4%BD%BF%E7%94%A8%EF%BC%89%E3%80%82%0A%E5%8F%82%E6%95%B0%E4%B8%AA%E6%95%B0%E5%A4%9A%EF%BC%8C%E4%BB%A3%E8%A1%A8%E4%BB%A3%E7%A0%81%E6%9C%89%E4%B8%80%E4%BA%9B%E5%9D%8F%E5%91%B3%E9%81%93%EF%BC%88%E4%BB%A3%E7%A0%81%E5%9D%8F%E5%91%B3%E9%81%93%E7%94%B1Martin%20Fowler%E5%9C%A8%E4%BB%96%E7%9A%84Refactoring%E4%B8%80%E4%B9%A6%E9%87%8C%E6%8F%90%E5%87%BA%EF%BC%8C%E5%8D%B3%E6%8C%87%E8%99%BD%E7%84%B6%E4%BB%A3%E7%A0%81%E5%8A%9F%E8%83%BD%E6%B2%A1%E9%97%AE%E9%A2%98%EF%BC%8C%E4%BD%86%E5%8D%B4%E5%9C%A8%E5%90%91%E4%B8%8D%E5%A5%BD%E7%9A%84%E6%96%B9%E5%90%91%E5%8F%91%E5%B1%95%EF%BC%8C%E8%B6%8A%E6%9D%A5%E8%B6%8A%E5%9D%8F%EF%BC%8C%E6%9C%80%E5%90%8E%E5%B0%B1%E5%8F%AF%E8%83%BD%E5%87%BA%E9%97%AE%E9%A2%98%E4%BA%86%EF%BC%89%E3%80%82%0A-%20They%20take%20a%20lot%20of%20conceptual%20power.%0A%20%20%20%20%E5%9B%A0%E4%B8%BA%E5%8F%82%E6%95%B0%E4%B8%8D%E5%B1%9E%E4%BA%8E%E5%87%BD%E6%95%B0%E5%90%8D%E8%A1%A8%E8%BE%BE%E7%9A%84%E6%8A%BD%E8%B1%A1%E5%B1%82%E6%AC%A1%EF%BC%8C%E6%89%80%E4%BB%A5%E8%A6%81%E7%9F%A5%E9%81%93%E5%8F%82%E6%95%B0%E6%98%AF%E4%BB%80%E4%B9%88%E6%84%8F%E6%80%9D%EF%BC%8C%E5%8F%AA%E8%83%BD%E7%9C%8B%E8%B0%83%E7%94%A8%E6%97%B6%E6%98%AF%E6%80%8E%E4%B9%88%E4%BC%A0%E5%85%A5%E7%9A%84%E3%80%82%E7%84%B6%E5%90%8E%E5%9C%A8%E9%98%85%E8%AF%BB%E5%87%BD%E6%95%B0%E7%9A%84%E6%97%B6%E5%80%99%E8%A6%81%E6%97%B6%E6%97%B6%E8%AE%B0%E5%BE%97%E3%80%82%0A-%20Arguments%20are%20even%20harder%20from%20a%20**testing%20point%20of%20view**.%20Imagine%20the%20dif%EF%AC%81culty%20of%20writing%20all%20the%20test%20cases%20to%20ensure%20that%20all%20the%20various%20combinations%20of%20arguments%20work%20properly.%0A-%20**Output%20arguments**%20are%20harder%20to%20understand%20than%20input%20arguments.%20When%20we%20read%20a%20function%2C%20we%20are%20used%20to%20the%20idea%20of%20information%20going%20in%20to%20the%20function%20through%20arguments%20and%20out%20through%20the%20return%20value.%20We%20don%E2%80%99t%20usually%20expect%20information%20to%20be%20going%20out%20through%20the%20arguments.%0A%0A%23%23%23%23%20%E4%B8%80%E4%B8%AA%E5%8F%82%E6%95%B0%E7%9A%84%E5%87%BD%E6%95%B0%EF%BC%88Monadic%20Function%EF%BC%89%0A%E6%9C%89%E4%B8%A4%E7%A7%8D%E6%83%85%E5%86%B5%EF%BC%8C%E5%BE%88%E9%80%82%E5%90%88%E4%BD%BF%E7%94%A8%E5%8D%95%E5%8F%82%E6%95%B0%E5%87%BD%E6%95%B0%EF%BC%9A%0A-%20transformation%EF%BC%8C%E5%81%9A%E8%BD%AC%E6%8D%A2%E6%88%96%E8%80%85%E6%98%A0%E5%B0%84%EF%BC%8C%E6%8A%8A%E5%8F%82%E6%95%B0%E9%9B%86%E6%98%A0%E5%B0%84%E5%88%B0%E8%BE%93%E5%87%BA%E9%9B%86%0A-%20event%EF%BC%9AThe%20overall%20program%20is%20meant%20to%20interpret%20the%20function%20call%20as%20an%20event%20and%20use%20the%20argument%20to%20alter%20the%20state%20of%20the%20system%0A%0A%23%23%23%23%20%E6%A0%87%E5%BF%97%E4%BD%8D%E5%8F%82%E6%95%B0%0APassing%20a%20boolean%20into%20a%20function%20is%20a%20truly%20terrible%20practice.%20It%20immediately%20complicates%20the%20signature%20of%20the%20method%2C%20***loudly%20proclaiming%20that%20this%20function%20does%20more%20than%20one%20thing***.%0A%E8%BF%99%E6%97%B6%E5%80%99%E5%BA%94%E8%AF%A5%E5%81%9A%E7%9A%84%E6%98%AF%EF%BC%8C%E7%94%A8%E4%B8%8D%E5%90%8C%E7%9A%84%E5%87%BD%E6%95%B0%E5%90%8D%E6%9D%A5%E9%98%90%E8%BF%B0%E6%A0%87%E5%BF%97%E4%BD%8D%E6%83%B3%E5%8C%BA%E5%88%86%E7%9A%84%E6%83%85%E5%86%B5%E3%80%82%0A%0A%23%23%23%23%20%E4%B8%A4%E4%B8%AA%E5%8F%82%E6%95%B0%E7%9A%84%E5%87%BD%E6%95%B0%EF%BC%88Dydadic%20Function%EF%BC%89%0A%E4%B8%A4%E4%B8%AA%E5%8F%82%E6%95%B0%E8%A6%81%E6%AF%94%E4%B8%80%E4%B8%AA%E5%8F%82%E6%95%B0%E9%9A%BE%E7%90%86%E8%A7%A3%E7%9A%84%E5%A4%9A%EF%BC%8C%E5%9B%A0%E4%B8%BA%E4%BD%A0%E9%9C%80%E8%A6%81%E7%90%86%E8%A7%A3%E5%8F%82%E6%95%B0%E7%9A%84%E9%A1%BA%E5%BA%8F%E6%98%AF%E6%80%8E%E4%B9%88%E5%9B%9E%E4%BA%8B%E5%84%BF%E3%80%82%E4%BD%86%E4%BD%9C%E8%80%85%E4%B9%9F%E8%AF%B4%E4%BA%86%EF%BC%9A%0A%3E%20Dyads%20aren%E2%80%99t%20evil%2C%20and%20you%20will%20certainly%20have%20to%20write%20them.%20However%2C%20you%20should%20be%20aware%20that%20they%20come%20at%20a%20cost%20and%20should%20take%20advantage%20of%20what%20mechanims%20may%20be%20available%20to%20you%20to%20convert%20them%20into%20monads.%0A%0A%E6%9C%89%E4%B8%A4%E4%B8%AA%E5%8F%82%E6%95%B0%E7%9A%84%E6%97%B6%E5%80%99%EF%BC%8C%E5%B0%B1%E8%A6%81%E6%85%8E%E9%87%8D%E4%BA%86%E3%80%82%E6%80%BB%E6%98%AF%E8%A6%81%E5%B0%9D%E8%AF%95%E6%89%BE%E6%9C%BA%E4%BC%9A%E8%BD%AC%E6%8D%A2%E6%88%90%E5%8D%95%E5%8F%82%E6%95%B0%E7%9A%84%E5%87%BD%E6%95%B0%E3%80%82%E5%AE%9E%E8%B7%B5%E6%9D%A5%E7%9C%8B%EF%BC%8C%E6%83%B3%E8%BD%AC%E6%80%BB%E6%98%AF%E5%AE%B9%E6%98%93%E7%9A%84%E3%80%82%E4%BD%86%E6%98%AF%E8%BD%AC%E5%AE%8C%E4%B9%8B%E5%90%8E%E8%A6%81%E7%AC%A6%E5%90%88%E9%80%BB%E8%BE%91%E8%AF%AD%E6%84%8F%EF%BC%8C%E6%9C%89%E6%97%B6%E5%80%99%E5%B0%B1%E6%B2%A1%E9%82%A3%E4%B9%88%E5%AE%B9%E6%98%93%E4%BA%86%E3%80%82%E4%BD%86%E6%80%BB%E5%BD%92%E8%BF%98%E6%98%AF%E8%A6%81%E5%8E%BB%E5%B0%9D%E8%AF%95%EF%BC%8C%E8%83%BD%E8%AE%A9%E5%87%BD%E6%95%B0%E8%B0%83%E7%94%A8%E5%8F%98%E5%BE%97%E6%9B%B4%E5%8A%A0clean%E3%80%82%0A%0A%23%23%23%23%20%E4%B8%89%E4%B8%AA%E5%8F%82%E6%95%B0%E7%9A%84%E5%87%BD%E6%95%B0%EF%BC%88Triads%EF%BC%89%0A%3EFunctions%20that%20take%20three%20arguments%20are%20signi%EF%AC%81cantly%20harder%20to%20understand%20than%20dyads.%20The%20issues%20of%20ordering%2C%20pausing%2C%20and%20ignoring%20are%20more%20than%20**doubled**.%20I%20suggest%20you%20think%20very%20carefully%20before%20creating%20a%20triad.%0A%0A%E6%B2%A1%E5%95%A5%E5%A5%BD%E8%AF%B4%E7%9A%84%EF%BC%8C%E4%B8%89%E4%B8%AA%E5%8F%82%E6%95%B0%E6%AF%94%E4%B8%A4%E4%B8%AA%E5%8F%82%E6%95%B0%E5%BC%95%E5%85%A5%E7%9A%84%E9%A2%9D%E5%A4%96effort%E7%BF%BB%E5%80%8D%E9%83%BD%E4%B8%8D%E6%AD%A2%E3%80%82%E6%89%80%E4%BB%A5%E5%B0%BD%E9%87%8F%E9%81%BF%E5%85%8D%E3%80%82%0A%E4%BD%9C%E8%80%85%E4%B9%9F%E6%8F%90%E5%88%B0%E4%BA%86%E4%B8%80%E4%B8%AA%E5%A5%BD%E7%9A%84%E4%B8%89%E4%B8%AA%E5%8F%82%E6%95%B0%E7%9A%84%E4%BE%8B%E5%AD%90%EF%BC%9A%60assertEquals(1.0%2C%20amount%2C%20.001)%60%E3%80%82%E5%AF%B9float%E5%8F%98%E9%87%8F%E7%9A%84%E5%88%A4%E6%96%AD%EF%BC%8C%E7%AC%AC%E4%B8%89%E4%B8%AA%E5%8F%82%E6%95%B0%E5%BC%95%E5%85%A5%E7%B2%BE%E5%BA%A6%E5%80%BC%EF%BC%8C%E8%BF%99%E6%A0%B7%E8%AE%A9%E8%B0%83%E7%94%A8%E8%80%85%E8%BF%94%E5%9B%9E%E6%9F%A5%E7%9C%8B%E5%87%BD%E6%95%B0%E5%8E%9F%E5%9E%8B%E6%97%B6%EF%BC%8C%E8%83%BD%E5%A4%9F%E5%BE%97%E5%88%B0%E6%8F%90%E9%86%92%EF%BC%8C%E5%AF%B9%E4%BA%8E%E6%B5%AE%E7%82%B9%E6%95%B0%E6%9D%A5%E8%AF%B4%EF%BC%8C%E7%9B%B8%E7%AD%89%E6%80%BB%E6%98%AF%E7%9B%B8%E5%AF%B9%E7%9A%84%E3%80%82%0A%0A%23%23%23%23%20Argument%20Objects%0A%3EWhen%20a%20function%20seems%20to%20need%20more%20than%20two%20or%20three%20arguments%2C%20it%20is%20likely%20that%20some%20of%20those%20arguments%20ought%20to%20be%20wrapped%20into%20a%20class%20of%20their%20own.%0A%0A%3EReducing%20the%20number%20of%20arguments%20by%20creating%20objects%20out%20of%20them%20may%20**seem%20like%20cheating%2C%20but%20it%E2%80%99s%20not**.%20When%20groups%20of%20variables%20are%20passed%20together%2C%20**they%20are%20likely%20part%20of%20a%20concept%20that%20deserves%20a%20name%20of%20its%20own**.%0A%0A%23%23%23%23%20Verbs%20and%20Keywords%0A%E8%BF%99%E9%87%8C%E4%BD%9C%E8%80%85%E6%83%B3%E6%8F%90%E9%86%92%E7%9A%84%E6%98%AF%E4%B8%BA%E5%87%BD%E6%95%B0%E8%B5%B7%E4%B8%80%E4%B8%AA%E5%A5%BD%E5%90%8D%E5%AD%97%E3%80%82%E6%9C%80%E5%A5%BD%E5%B0%B1%E6%98%AF%E7%94%A8%E5%8A%A8%E8%AF%8D%2B%E5%90%8D%E8%AF%8D%E7%9A%84%E6%90%AD%E9%85%8D%EF%BC%8C%E8%83%BD%E9%98%90%E8%BF%B0%E7%9A%84%E6%9B%B4%E5%8A%A0%E6%B8%85%E6%A5%9A%E3%80%82%E4%BE%8B%E5%A6%82%EF%BC%9A%0A%60assertEquals%60%E5%B0%B1%E6%B2%A1%E6%9C%89%60assertExpectedEqualsActual(expected%2C%20actual)%60%E5%A5%BD%E3%80%82%E5%90%8E%E8%80%85%E4%BD%93%E7%8E%B0%E4%BA%86%E5%8F%82%E6%95%B0%E9%A1%BA%E5%BA%8F%E3%80%82%0A%60write(name)%60%E6%B2%A1%E6%9C%89%60writeField(name)%60%E5%A5%BD%E3%80%82%E5%9B%A0%E4%B8%BA%E5%89%8D%E8%80%85%E4%B8%8D%E7%9F%A5%E9%81%93name%E4%BF%AE%E9%A5%B0%E7%9A%84%E6%98%AF%E4%BB%80%E4%B9%88%EF%BC%8C%E5%90%8E%E8%80%85%E5%91%8A%E8%AF%89%E6%88%91%E4%BB%ACname%E6%98%AF%E4%B8%80%E4%B8%AAfield%20name%E3%80%82%0A%0A%23%23%23%20Have%20No%20Side%20Effects%0A%3ESide%20effects%20are%20lies.%20Your%20function%20promises%20to%20do%20one%20thing%2C%20but%20it%20also%20does%20other%20hidden%20things.%0A%3EIf%20you%20must%20have%20a%20temporal%20coupling%2C%20you%20should%20make%20it%20clear%20in%20the%20name%20of%20the%20function.%0A%0A%E5%87%BD%E6%95%B0%E4%B8%8D%E8%A6%81%E6%9C%89side%20effect%EF%BC%8C%E4%B9%9F%E5%B0%B1%E6%98%AFfocus%E4%B8%80%E4%BB%B6%E4%BA%8B%E6%83%85%E3%80%82%E6%88%91%E8%A7%89%E5%BE%97%E8%BF%99%E9%87%8C%E7%9A%84side%20effect%E5%BA%94%E8%AF%A5%E4%B8%8D%E5%8C%85%E6%8B%AC%E6%9B%B4%E6%96%B0%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F%E6%88%96%E8%80%85%E7%B1%BB%E5%AF%B9%E8%B1%A1%E7%9A%84%E6%88%90%E5%91%98%E5%8F%98%E9%87%8F%E3%80%82%0A%0A%23%23%23%20Command%20Query%20Separation%0A%3EFunctions%20should%20either%20do%20something%20or%20answer%20something%2C%20but%20not%20both.%20Either%20your%20function%20should%20change%20the%20state%20of%20an%20object%2C%20or%20it%20should%20return%20some%20information%20about%20that%20object.%0A%0A%E8%BF%99%E9%87%8C%E7%9A%84%E6%84%8F%E6%80%9D%E8%BF%98%E6%98%AF%E4%BF%9D%E6%8C%81SRP%EF%BC%8C%E5%87%BD%E6%95%B0%E8%A6%81%E4%B9%88%E5%8F%8D%E5%BA%94%E6%9F%90%E4%B8%AAobject%E7%9A%84%E7%8A%B6%E6%80%81%EF%BC%8C%E8%A6%81%E4%B9%88%E5%AF%B9object%E5%81%9A%E4%B8%80%E4%BA%9B%E6%93%8D%E4%BD%9C%E3%80%82%E5%AF%B9%E6%AF%94%E4%B8%8B%E9%9D%A2%E4%B8%A4%E7%A7%8D%E5%86%99%E6%B3%95%EF%BC%9A%0A%60%60%60java%0Aif%20(setAndCheckIfExists(%22username%22%2C%20%22unclebob%22))...%0A%0Aif%20(attributeExists(%22username%22))%20%7B%0A%20%20%20%20setAttribute(%22username%22%2C%20%22unclebob%22)%3B%0A%20%20%20%20...%0A%7D%0A%60%60%60%0A%0A%23%23%23%20Don%E2%80%99t%20Repeat%20Yourself%0ADRY%E5%8E%9F%E5%88%99%EF%BC%8C%E8%BF%99%E4%B8%AA%E4%B9%9F%E6%97%A0%E9%9C%80%E8%B5%98%E8%BF%B0%0A%3E%20Duplication%20may%20be%20the%20root%20of%20all%20evil%20in%20software.%0A%0A%23%23%23%20Prefer%20Exceptions%20to%20Returning%20Error%20Codes%0A%E4%BD%BF%E7%94%A8exception%E4%BE%BF%E4%BA%8E%E5%9C%A8%E5%90%8C%E4%B8%80%E4%B8%AA%E5%9C%B0%E6%96%B9%E5%A4%84%E7%90%86%E9%94%99%E8%AF%AF%E6%83%85%E5%86%B5%E3%80%82%E5%A6%82%E6%9E%9C%E7%94%A8return%20error%20code%E7%9A%84%E6%96%B9%E5%BC%8F%EF%BC%8C%E5%8F%AA%E8%83%BD%E5%9C%A8error%E5%8F%91%E7%94%9F%E7%9A%84%E5%9C%B0%E6%96%B9%E5%A4%84%E7%90%86%E3%80%82%E5%9D%8F%E5%A4%84%E6%98%AF%EF%BC%8C%E6%AD%A3%E5%B8%B8%E9%80%BB%E8%BE%91%E7%9A%84%E4%BB%A3%E7%A0%81%E5%92%8C%E9%94%99%E8%AF%AF%E4%BB%A3%E7%A0%81%E4%BC%9A%E6%B7%B7%E5%90%88%E5%9C%A8%E4%B8%80%E8%B5%B7%E3%80%82%0A%3EThus%2C%20a%20function%20that%20handles%20errors%20should%20do%20nothing%20else.%20This%20implies%20(as%20in%20the%20example%20above)%20that%20if%20the%20keyword%20try%20exists%20in%20a%20function%2C%20it%20should%20be%20the%20very%20%EF%AC%81rst%20word%20in%20the%20function%20and%20that%20there%20should%20be%20nothing%20after%20the%20catch%2Ffinally%20blocks.%0A%0A%E5%A4%84%E7%90%86error%E7%9A%84%E6%89%80%E6%9C%89%E4%BB%A3%E7%A0%81%E5%BA%94%E8%AF%A5%E6%94%BE%E5%9C%A8%E4%B8%80%E8%B5%B7%E3%80%82%E4%B8%8D%E8%BF%87%E8%BF%99%E9%87%8C%E7%9A%84%E5%BB%BA%E8%AE%AE%E4%B8%8D%E9%80%82%E7%94%A8%E4%BA%8E%E7%BA%AFC%E7%BC%96%E7%A8%8B%EF%BC%8C%E5%9B%A0%E4%B8%BA%E6%88%91%E4%BB%AC%E6%B2%A1%E6%9C%89try-catch%E3%80%82%0A%0A%23%23%20%E6%80%BB%E7%BB%93%0A%E5%86%99%E5%A5%BD%E4%B8%80%E4%B8%AA%E5%87%BD%E6%95%B0%E7%9C%8B%E4%BC%BC%E7%AE%80%E5%8D%95%EF%BC%8C%E4%BD%86%E5%85%B6%E5%AE%9E%E9%9A%BE%E5%BA%A6%E4%B8%8D%E4%BA%9A%E4%BA%8E%E8%B5%B7%E4%B8%80%E4%B8%AA%E4%BC%98%E9%9B%85%E5%8F%88%E6%B8%85%E6%99%B0%E7%9A%84%E5%90%8D%E5%AD%97%E3%80%82Clean%20Code%E4%B8%80%E4%B9%A6%E7%BB%99%E4%BA%86%E4%B8%8D%E5%B0%91%E5%BB%BA%E8%AE%AE%EF%BC%8C%E5%85%B6%E5%AE%9E%E5%8F%AF%E4%BB%A5%E5%8F%8D%E5%A4%8D%E5%8F%82%E9%98%85%EF%BC%8C%E5%8B%A4%E5%8A%A0%E9%87%8D%E6%9E%84%E3%80%82%0A%E8%BF%99%E4%BA%9B%E5%BB%BA%E8%AE%AE%E4%B8%AD%EF%BC%8C%E7%9B%AE%E5%89%8D%E6%88%91%E8%AE%A4%E4%B8%BA%E9%87%8D%E8%A6%81%E7%9A%84%E6%98%AF%E7%AF%87%E9%A6%96%E7%9A%84%E5%87%A0%E4%B8%AA%EF%BC%8C%E7%89%B9%E5%88%AB%E6%98%AFFunction%20Arguments%E7%89%B9%E5%88%AB%E5%8F%91%E4%BA%BA%E8%AD%A6%E9%86%92%E3%80%82%0A-%20Small!%0A-%20Do%20one%20thing%0A-%20One%20Level%20of%20Abstraction%20per%20Function%0A-%20Use%20Descriptive%20Names%0A-%20Function%20Arguments