你认为多少级缩进是合理的?
我认为C++函数有4/5个或更多级缩进通常是不好的。这意味着你必须一直在脑海中跟踪4/5个或更多的事情。
我的观点是否合理?
(是的,如果完全不进行缩进,就可以避免出现多级缩进:)
你认为多少级缩进是合理的?
我认为C++函数有4/5个或更多级缩进通常是不好的。这意味着你必须一直在脑海中跟踪4/5个或更多的事情。
我的观点是否合理?
(是的,如果完全不进行缩进,就可以避免出现多级缩进:)
我同意你的观点。如果一个函数包含4或5个以上嵌套的if/switch/loop/try语句,应将其部分内容提取到自己的函数中。
这将使代码更易读,因为提取后的函数名称通常比代码本身更具描述性。
实际上,最导致代码难以阅读的不是缩进层数,而是你正在查看的模块/函数/方法的长度。
当然,长的代码段通常有更多的缩进层次,因为代码块被嵌入到一行内而不是分开。个人认为,如果一个方法有超过几个屏幕的代码和超过6个缩进层次,那么就会有一种气味。
我曾经认为Linus在这方面有点固执,他说不要超过3个层级,否则你的代码就会出问题。但是遵循这个原则在推理控制流方面对我帮助很大。话虽如此,我必须以不同的方式来解释它。直觉上的解释是你应该创建更多微小的函数。我不建议将这个想法发挥到极致,因为这样会使你的控制流和副作用变得难以理解,当所有的副作用都被函数调用所遮盖时,你会被引导到各个地方。
对我帮助最大的是喜欢延迟处理和简单的循环。以这个为例:
// Remove vertices from mesh.
for each vertex in vertices.to_remove:
{
for each edge in vertex.edges:
{
for each face in edge.faces:
{
face.remove_edge(edge);
if (face.size() < 3)
face.remove();
}
edge.remove();
}
vertex.remove();
}
上面那个有四层缩进的庞然大物很尴尬(如果不是伪代码形式,可能还需要更新纹理映射等,需要更多层次的缩进)。我们可以这样做:
for each vertex in vertices.to_remove:
{
for each edge in vertex.edges:
edges_to_remove.insert(edge);
}
for each edge in edges_to_remove:
{
for each face in edge.faces:
faces_to_rebuild.insert(face, edge);
}
for each face,edge in faces_to_rebuild:
{
face.remove_edge(edge);
if (face.size() < 3)
face.remove();
}
for each edge in edges_to_remove:
edge.remove();
for each vertex in vertices_to_remove:
vertex.remove();
虽然这需要对数据进行更多的遍历和一些额外的状态,但它使每个循环变得更简单。当我们有了这些更简单的循环时,它们变得更容易并行化,并且在适当的数据结构下,内存访问模式可以开始采用缓存友好型。
我发现倾向于这种延迟处理不仅减少了缩进,而且简化了我的理解代码的能力,因为控制流非常简单,它们都只会引起一种统一的副作用。这使得更容易看到每个循环正在做什么,并在一眼之间理解它是否正在做正确的事情,因为每个循环都专门用于引起一种类型的副作用,而不是许多不同类型的副作用。令人惊讶的是,尽管需要额外的工作,它通常会改善缓存一致性,并打开多线程和SIMD的新大门,最终获得比开始时更高效的结果。
我认为这取决于情况,但通常你会想要减少嵌套。
嵌套循环会影响性能,而嵌套的if语句通常可以被减少到较少的层级。
问题在于你经常会遇到在开发早期过早优化的问题。我认为在进行三层或以上的嵌套之前应该花点时间考虑可能性。
我对缩进唯一的不满是当使用两个关键字时,一个依赖于另一个。例如:
switch (c) {
case 'x':
foo = bar;
这是不好的,你不能在switch之外有一个case,所以:
switch (c) {
case 'x':
foo = bar;
..会好得多。在带有if / else if / else的switch语句中,缩进往往会变得混乱。我还强烈建议在缩进时保持80(最多110列限制)。没有人喜欢向右滚动30列以查看您正在做什么,然后向左滚动30列以查看您如何处理结果 :) 更不用说那些必须在服务器上使用愚蠢的80x25控制台模式编辑您的代码的可怜人了。
尽管我要说的是从普通C角度来看的,但它可能也适用于C++。我青睐Linux内核编码风格:使用8个字符宽的Tab缩进(自然Tab),并且在80x25终端上适合有多少层缩进(不能超出80个字符宽度)。
过多的缩进可能意味着您应该进行重构:创建几个具有良好名称的小方法。这样,您可以将逻辑分解为更小的部分,更容易理解。
这与函数应该有多长的问题有关。如果您将函数体保持在十行或更少的长度,那么很难出现太多层次的缩进。
我认为4或5个级别太多了。您几乎可以将其中一些内部循环或条件语句分解成它们自己的函数。
我自己感到有点不安,当缩进达到三个级别时。即使是两个级别也会让我重新考虑我的做法。
只要您在编辑器中同时看到所有打开和关闭的括号,多层缩进就没问题。
实际上,这往往会限制您最多使用4个级别。