冯.诺依曼贡献了关于计算机的一个重要隐喻:一系列依次执行的指令。这一隐喻贯穿了许多编程语言,当然也包括java。那么我们应该如何表达程序的行为(也就是一系列指令)。
1. 控制流
作为程序员,你要决定如何去表达心目中的控制流,是表达成一个含有例外情况的主体流,还是表达成多个同样重要的流,又或者是两者的混合,这样一个问题要先想清楚。另外,写程序的时候,将控制流的小片段归类,让不想深入研究的阅读者首先得到一个抽象的理解,同时又为需要深入领会的阅读者提供更详尽的细节。
2. 主体流
程序员通常心里都会想象一个程序控制流的主干。处理过程从这里开始,到那里结束,一路上会有一些决策和异常,但整个运算还是有路可循的。要用你的编程语言清晰地表达这个流。总之,把今后可能会被频繁地阅读,理解与修改的部分表达清楚。
3. 选择性消息
有时候发送消息去选择一个实现,例如,如果打算用若干方法中的一个来显示一个图形,我会发送一条多态的消息来传达出“选择将在运行是发生”的消息。
public void displayShape(Shape subject, Brush brush) {
brush.display(subject);
}
brush在运行的时候,有可能是ScreenBrush,PostscriptBrush等等。都是Brush类的子类。不同的brush实现的display方法不同,也就能画出不同的图形。
4. 反置性消息
对称性可以提高代码的可读性,请看下列代码:
void compute() {
input();
helper.process(this);
output();
}
构成这个方法的三个方法调用缺乏对称性,通过引入一个辅助方法来揭示隐含的对称性可以提高这个方法的可读性。
void process(Helper helper) {
helper.process(this);
}
void compute() {
input();
process(helper);
output();
}
不过如果过度使用反置性消息可能会掩盖需要进行功能移动的迹象。有时候我觉得仅仅为了达到对称性这样的美学要求的冲动而引入一个新方法有点蠢。不过美学之深妙不止于此。比起严格的线性逻辑思维,美学能调动更多的脑细胞。一旦培养起对代码之美的嗅觉,从代码中得到的美感将是对代码质量的一种宝贵的反馈。这些从象征性思维层面之下涌出的感觉,其价值一点都不逊于经过充分证明并明确命名的模式。
5. 解释性消息
意图与实现之间的区分在软件开发中总是很重要的。它让你首先理解运算的目的,如果有必要,再进一步理解其实现的细节。可以用消息来彰显这种区分,首先发送一条“以要解决的问题来命名”的消息,这条消息再发送“以问题如何被解决来命名”的消息。比如:
highlight(Rectangle area) {
reverse(area);
}
highlight 表达的是意图:要将这一区域高亮度显示。 reverse表达的是实现:如何实现我们的意图。
有时候,当你觉得需要单独注释一行代码的时候,可以引入一条解释性消息。当我看到:
flags = LOADED_BIT //Set the loaed bit
我会宁愿看到:
setLoadedFlag();
void setLoadedFlag() {
flags = LOADED_BIT;
}
6. 卫述句
即使程序有一个主体流,有些情况下也会需要偏离它。卫述句是一种表达简答和局部的异常状况的方式,它的影响后果完全是局部的。
比如:
void compute() {
Server server = getServer();
if (server != null) {
Client client = server.getClient();
if (client != null) {
Request current = client.getRequest();
if(current != null) {
processRequest(current);
}
}
}
嵌套的条件语句孕育着错误。用卫述句改写的代码强调了请求处理的先决条件,而不需要用到复杂的控制结构:
void compute() {
Server server = getServer();
if (server == null) {
return;
}
Client client = server.getClient();
if (client == null) {
return;
}
Request current = client.getRequest();
if (current == null) {
return;
}
processRequest(current);
}
总之,卫述句就是尽量将异常流结束,尽快将主体流上的一些分支流结束掉。
卫述句的一个变体是在循环中使用continue语句,它的意思是“别管这个元素,继续下一个。”