今天继续翻译代码布局的这一部分。有些很明显的条目,就不翻译了,看看代码就应该明白是什么意思。

2.13 段落

代码要分段。

段落就是完成特定任务的语句的集合。文学上的段落是表达一个观点的一些句子,而编程中的段落则是完成算法的一步的语句。

应当将代码分段,然后在各个段落之间加一个空行。另外,在每段的开始处添加一行注释可以增加可读性。

2.14 Else语句

别拥抱else。

所谓的“拥抱”是指下面这个样子:

} else {

而“不拥抱”则为:

}
else {

“拥抱”能节省一行,但它从另一个方面降低了代码的可读性。被“拥抱”的else和相应的if以及结束括号不在同一列上,较难辩认。

更重要的是,else本意是区分出动作的另一方面,而“拥抱”会降低这种区别。

此外,将else单独写在一行,你可以很轻易地复制else部分,而不用担心多复制括号。

2.15 垂直对齐

将同类的项目垂直对齐。

这一条好像没有什么必要去翻译了,大家都能看明白。

my @months = qw(
    January   February   March
    April     May        June
    July      August     September
    October   November   December
);

my %expansion_of = (
    q{it's}    => q{it is},
    q{we're}   => q{we are},
    q{didn't}  => q{did not},
    q{must've} => q{must have},
    q{I'll}    => q{I will},
);

2.16 截断过长的行

在运算符之前断行。

当表达式过长时,人们通常喜欢在运算符之后断行,并为第二行之后的部分添加一层缩进。如:

push @steps, $steps[-1] +
    $radial_velocity * $elapsed_time +
    $orbital_velocity * ($phase + $phase_shift) -
    $DRAG_COEFF * $altitude;

其理由是,行尾的运算符看起来像一个“连续行”的标记, 暗示着这一行并未结束。

这个想法的确不错,但有个很严重的问题。人们很少去注意一行的最右端。 程序中绝大部分提示语义的元素(如关键字)都写在一行的左侧。 更为重要的是,代码的结构暗示——如缩进——也占据了左侧这个最重要的位置。 表达式第二行之后的缩进很容易给人造成错觉。

解决方法之一,就是在运算符之前断行。这样能保证接下来的每一行都以运算符开始, 与Perl中其他的代码迥然不同,这样读者看到这一行马上就能意识到它是前一行未结束的部分。

第二行之后的缩进也很重要。不应简单地缩进一层,而是应当与表达式的起始列对齐。 这样最终的代码如下所示:

push @steps, $steps[-1]
             + $radial_velocity * $elapsed_time
             + $orbital_velocity * ($phase + $phase_shift)
             - $DRAG_COEFF * $altitude
             ;

这种格式能从视觉上很好地区分开push的两个参数。

2.17 不在结尾的表达式

对语句中间的表达式进行重构。

上一条仅适用于表达式位于语句结尾的情况。如果表达式出现在语句的中间, 那么最好对其进行重构,将表达式赋给另一个变量。例如:

my $next_step = $steps[-1]
                + $radial_velocity * $elapsed_time
                + $orbital_velocity * ($phase + $phase_shift)
                - $DRAG_COEFF * $altitude
                ;
add_step( \@steps, $next_step, $elapsed_time);

这种写法要远远好于下面这种写法:

add_step( \@steps, $steps[-1]
                   + $radial_velocity * $elapsed_time
                   + $orbital_velocity * ($phase + $phase_shift)
                   - $DRAG_COEFF * $altitude
                   , $elapsed_time);