18.1 使代码更易于理解的东西
使代码易于理解的两个最重要的技术已经在前面的章节中讨论过了。第一个是选择好的名称(第14章)。精确而有意义的名称可以阐明代码的行为,减少对文档的需求。如果名称模糊不清,那么读者将不得不通读代码,以推断出被命名实体的含义;这既费时又容易出错。第二个技巧是一致性(第17章)。如果类似的事情总是以类似的方式完成,那么读者就可以识别出他们以前见过的模式,并立即得出(安全的)结论,而无需详细分析代码。
下面是一些其他的通用技术,可以使代码更加明显。
明智地使用空白。代码的格式化方式可以影响它的易懂程度。考虑一下下面的参数文档,其中的空白已经被挤掉了:
/**
* ...
* @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.
*/
很难看到一个参数的文档在哪里结束,下一个参数在哪里开始。甚至不知道有多少个参数,或者它们的名字是什么。如果增加一点空白,结构就会突然变得清晰,文档也会更容易浏览:
/**
* @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.
*/
空行对于分隔一个方法中的主要代码块也很有用,比如下面的例子。
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;
}
如果每个空行后的第一行是描述下一个代码块的注释,这种方法就特别有效:空行使注释更加明显。
语句中的空白有助于阐明语句的结构。比较以下两条语句,其中一条有空白,一条没有。
for(int pass=1;pass>=0&&!empty;pass--) {
for (int pass = 1; pass >= 0 && !empty; pass--) {
注释。有时无法避免不易于理解的代码。当这种情况发生时,重要的是使用注释来弥补所缺的信息。要做好这一点,你必须把自己放在读者的位置上,弄清楚什么东西可能会使他们感到困惑,什么信息可以消除这种困惑。下一节将介绍几个例子。
Last updated