# 18.1 使代码更易于理解的东西

使代码易于理解的两个最重要的技术已经在前面的章节中讨论过了。第一个是选择好的名称（第14章）。精确而有意义的名称可以阐明代码的行为，减少对文档的需求。如果名称模糊不清，那么读者将不得不通读代码，以推断出被命名实体的含义；这既费时又容易出错。第二个技巧是一致性（第17章）。如果类似的事情总是以类似的方式完成，那么读者就可以识别出他们以前见过的模式，并立即得出（安全的）结论，而无需详细分析代码。

下面是一些其他的通用技术，可以使代码更加明显。

**明智地使用空白。**&#x4EE3;码的格式化方式可以影响它的易懂程度。考虑一下下面的参数文档，其中的空白已经被挤掉了：

```java
/** 
 * ...
 * @param numThreads The number of threads that this manager should
 * spin up in order to manage ongoing connections. The MessageManager
 * spins up at least one thread for every open connection, so this
 * should be at least equal to the number of connections you expect
 * to be open at once. This should be a multiple of that number if
 * you expect to send a lot of messages in a short amount of time.
 * @param handler Used as a callback in order to handle incoming
 * messages on this MessageManager's open connections. See
 * {@code MessageHandler} and {@code handleMessage} for details.
 */
```

很难看到一个参数的文档在哪里结束，下一个参数在哪里开始。甚至不知道有多少个参数，或者它们的名字是什么。如果增加一点空白，结构就会突然变得清晰，文档也会更容易浏览：

```java
/** 
* @param numThreads
*          The number of threads that this manager should spin up in
*          order to manage ongoing connections. The MessageManager spins
*          up at least one thread for every open connection, so this
*          should be at least equal to the number of connections you
*          expect to be open at once. This should be a multiple of that
*          number if you expect to send a lot of messages in a short
*          amount of time.
* @param handler
*          Used as a callback in order to handle incoming messages on
*          this MessageManager's open connections. See
*          {@code MessageHandler} and {@code handleMessage} for details.
*/
```

空行对于分隔一个方法中的主要代码块也很有用，比如下面的例子。

```cpp
void* Buffer::allocAux(size_t numBytes) 
{
    // Round up the length to a multiple of 8 bytes, to ensure alignment.
    uint32_t numBytes32 = (downCast<uint32_t>(numBytes) + 7) & ~0x7; 
    assert(numBytes32 != 0);
    
    // If there is enough memory at firstAvailable, use that. Work down
    // from the top, because this memory is guaranteed to be aligned
    // (memory at the bottom may have been used for variable-size chunks).
    if (availableLength >= numBytes32) {
       availableLength -= numBytes32;
       return firstAvailable + availableLength;
    }
    
    // Next, see if there is extra space at the end of the last chunk.
    if (extraAppendBytes >= numBytes32) {
       extraAppendBytes -= numBytes32;
       return lastChunk->data + lastChunk->length + extraAppendBytes;
    }
    
    // Must create a new space allocation; allocate space within it.
    uint32_t allocatedLength;
    firstAvailable = getNewAllocation(numBytes32, &allocatedLength);
    availableLength = allocatedLength numBytes32;
    return firstAvailable + availableLength;
}
```

如果每个空行后的第一行是描述下一个代码块的注释，这种方法就特别有效：空行使注释更加明显。

语句中的空白有助于阐明语句的结构。比较以下两条语句，其中一条有空白，一条没有。

```cpp
for(int pass=1;pass>=0&&!empty;pass--) {

for (int pass = 1; pass >= 0 && !empty; pass--) {
```

**注释。**&#x6709;时无法避免不易于理解的代码。当这种情况发生时，重要的是使用注释来弥补所缺的信息。要做好这一点，你必须把自己放在读者的位置上，弄清楚什么东西可能会使他们感到困惑，什么信息可以消除这种困惑。下一节将介绍几个例子。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://placeboy.gitbook.io/a-philosophy-of-software-design/ch18/18.1-shi-dai-ma-geng-yi-yu-li-jie-de-dong-xi.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
