代码格式化很重要。它太重要了,不能被忽视,同事它也不能过于教条地对待。代码格式化是关于沟通的,而沟通是专业开发人员的首要任务。

垂直格式化

概念间垂直开放性

这个概念包括如何在代码中分隔概念,下面的例子可以说明这一点。

  1. // 良好的垂直开放性
  2. package fitnesse.wikitext.widgets;
  3. import java.util.regex.*;
  4. public class BoldWidget extends ParentWidget {
  5. public static final String REGEXP = "'''.+?'''";
  6. private static final Pattern pattern = Pattern.compile("'''(.+?)'''", Pattern.MULTILINE + Pattern.DOTALL);
  7. public BoldWidget(ParentWidget parent, String text) throws Exception {
  8. super(parent);
  9. Matcher match = pattern.matcher(text);
  10. match.find();
  11. addChildWidgets(match.group(1));
  12. }
  13. public String render() throws Exception {
  14. StringBuffer html = new StringBuffer("<b>");
  15. html.append(childHtml()).append("</b>");
  16. return html.toString();
  17. }
  18. }
  1. // 较差的垂直开放性
  2. package fitnesse.wikitext.widgets;
  3. import java.util.regex.*;
  4. public class BoldWidget extends ParentWidget {
  5. public static final String REGEXP = "'''.+?'''";
  6. private static final Pattern pattern = Pattern.compile("'''(.+?)'''", Pattern.MULTILINE + Pattern.DOTALL);
  7. public BoldWidget(ParentWidget parent, String text) throws Exception {
  8. super(parent);
  9. Matcher match = pattern.matcher(text); match.find(); addChildWidgets(match.group(1));
  10. }
  11. public String render() throws Exception {
  12. StringBuffer html = new StringBuffer("<b>");
  13. html.append(childHtml()).append("</b>");
  14. return html.toString();
  15. }
  16. }

如你所见,第一个示例的可读性优于第二个。

垂直密度

垂直密度意味着紧密关联。因此,紧密相关的代码行应该在垂直方向上显得密集。查看以下示例:

  1. // 较差的垂直密度
  2. public class ReporterConfig {
  3. /**
  4. * The class name of the reporter listener
  5. */
  6. private String m_className;
  7. /**
  8. * The properties of the reporter listener
  9. */
  10. private List<Property> m_properties = new ArrayList<Property>();
  11. public void addProperty(Property property) { m_properties.add(property);
  12. }
  1. // 良好的垂直密度
  2. public class ReporterConfig {
  3. private String m_className;
  4. private List<Property> m_properties = new ArrayList<Property>();
  5. public void addProperty(Property property) {
  6. m_properties.add(property);
  7. }
  8. }

第二个代码更容易阅读。它适合一次性浏览。

垂直距离

变量声明。变量应该尽可能靠近其使用位置声明。因为我们的函数非常短,局部变量应该出现在每个函数的顶部。

实例变量,另一方面,应该在类的顶部声明。这不应该增加这些变量的垂直距离,因为在一个设计良好的类中,它们被许多,如果不是所有,类的方法使用。

关于实例变量应该放在哪里,已经有很多争论。在C++中,我们通常采用所谓的剪刀规则,将所有实例变量放在底部。然而,在Java中,常见的惯例是将它们全部放在类的顶部。我看不出有理由遵循任何其他惯例。重要的是在众所周知的地方声明实例变量。每个人都应该知道去哪里查看声明。

依赖函数。如果一个函数调用另一个函数,它们应该在垂直方向上靠近,如果可能的话,调用者应该在被调用者上方。这给程序提供了自然的流程。如果可靠地遵循了这一惯例,读者将能够相信函数定义将紧随其使用之后。

概念亲和性。某些代码片段想要靠近其他代码片段。它们具有某种概念上的亲和性。亲和力越强,它们之间的垂直距离就应该越小。

垂直排序

通常我们希望函数调用依赖指向下方。也就是说,被调用的函数应该在调用函数的下方。这在源代码模块中从高层到低层创造了一个良好的流程。(这与Pascal、C和C++等语言正好相反,这些语言强制在函数使用前定义或至少声明函数)

水平格式化

水平开放性和密度

我们使用水平空白来关联紧密相关的事物,以及将关系较弱的事物分开。示例:

  1. // 良好的水平开放性和密度
  2. private void measureLine(String line) {
  3. lineCount++;
  4. int lineSize = line.length();
  5. totalChars += lineSize;
  6. lineWidthHistogram.addLine(lineSize, lineCount);
  7. recordWidestLine(lineSize);
  8. }

赋值语句有两个明显且主要的元素:左侧和右侧。空格使这种分离变得明显。

水平对齐

  1. // 过时的水平对齐
  2. public class Example implements Base
  3. {
  4. private Socket socket;
  5. private inputStream input;
  6. protected long requestProgress;
  7. public Expediter(Socket s,
  8. inputStream input) {
  9. this.socket = s;
  10. this.input = input;
  11. }
  12. }

在现代语言中,这种类型的对齐是没有用的。对齐似乎强调了错误的事物,引导我的视线远离真正的意图。

  1. // 更好的方法
  2. public class Example implements Base
  3. {
  4. private Socket socket;
  5. private inputStream input;
  6. protected long requestProgress;
  7. public Expediter(Socket s, inputStream input) {
  8. this.socket = s;
  9. this.input = input;
  10. }
  11. }

这是更好的方法。

缩进

缩进很重要,因为它帮助我们拥有可见的层次结构和定义良好的块。

团队规则

每个程序员都有自己喜欢的格式化规则,但如果他在团队中工作,那么团队的规则优先。

开发团队应该就单一的格式化风格达成一致,然后每个团队成员都应该使用那种风格。我们希望软件具有一致的风格。我们不希望它看起来像是一群意见不合的个人编写的。