1. 引言
无论你是经验丰富的开发人员还是刚入门的新手,大概率都接触过变量和函数命名的格式规范,比如 camelCase、PascalCase、snake_case 和 kebab-case 等。
这只是众多代码格式规范中的一小部分。除此之外,还有诸如文件行数限制、缩进风格、方法与类的排布规则等。每种编程语言也有其特定的语法要求。
在本文中,我们会讨论一些实用的代码格式规范,帮助提升代码可读性。✅ 团队协作中,代码是成员之间的沟通工具,仅让程序跑起来是不够的,维护性差会带来严重问题。
我们将聚焦于如何写出结构清晰、易于理解的代码。文中示例使用 Java 编写,但其中的理念适用于任何语言。
2. 垂直格式规范
编写整洁代码时,一个经典的类比是“报纸式阅读”:我们先看标题,再看摘要,最后根据兴趣决定是否深入了解细节。
同理,文件标题和关键逻辑应出现在代码顶部,便于快速理解整体结构。那些用于实现细节的小函数和变量则应放在后面。
2.1. 垂直密度
如果一段代码表示一个完整概念(例如 HTML 渲染字符串),我们应在它与相邻代码块之间留出空行,这就是所谓的“概念间垂直开放”。
而“垂直密度”则强调:如果代码行之间逻辑紧密,就不要人为插入空行打断阅读流。
来看一个反面例子:
package fitnesse.wikitext.widgets;
import java.util.regex.*;
public class BoldWidget extends ParentWidget {
public static final String REGEXP = "'''.+?'''";
private static final Pattern pattern = Pattern.compile("'''(.+?)'''", Pattern.MULTILINE + Pattern.DOTALL);
public BoldWidget(ParentWidget parent, String text) throws Exception {
super(parent);
Matcher match = pattern.matcher(text);
match.find();
addChildWidgets(match.group(1));}
public String render() throws Exception {
StringBuffer html = new StringBuffer("<b>");
/**
* Adds the HTML closing tag
*/
html.append(childHtml()).append("</b>");
return html.toString();
}
}
这段代码完全没有垂直开放,所有内容挤在一起,还插入了一段无意义的注释打断逻辑流。
来看优化后的版本:
package fitnesse.wikitext.widgets;
import java.util.regex.*;
public class BoldWidget extends ParentWidget {
public static final String REGEXP = "'''.+?'''";
private static final Pattern pattern = Pattern.compile("'''(.+?)'''",Pattern.MULTILINE + Pattern.DOTALL);
public BoldWidget(ParentWidget parent, String text) throws Exception {
super(parent);
Matcher match = pattern.matcher(text);
match.find();
addChildWidgets(match.group(1));
}
public String render() throws Exception {
StringBuffer html = new StringBuffer("<b>");
html.append(childHtml()).append("</b>");
return html.toString();
}
}
优化后的代码结构清晰,一眼就能看出每个部分的用途。
想象一下,如果整个项目文件都像第一个版本那样写,即使作者本人,几个月后再看也可能一头雾水 ❌。
2.2. 垂直距离
为了减少读者的查找成本,相关代码应尽可能放在一起。尤其是变量声明,应尽量靠近其使用位置,特别是只在某个作用域内使用的局部变量。
举个例子,假设你定义了一个处理公司员工信息的类,包括构造函数和属性赋值。接着你又写了一个生成随机值的类用于测试。如果构造函数定义在 500 行之后甚至另一个文件中,那对读者来说就是一种折磨 ❌。
2.3. 垂直顺序
代码的顺序应该反映其依赖关系。读代码时,应能自然理解上下文。
如果一个高层函数调用了低层函数,建议先写高层函数,后写低层函数,这样读者看到调用时不会急着跳到别处找定义。
3. 水平格式规范
代码行的长度应该控制在多少字符以内?一个传统做法是参考 1890 年美国人口普查用的打孔卡片,每行 80 字符。
但这个数字不应成为硬性规定,尤其在现代框架中,函数名可能本身就很长(比如 iOS 中的方法名)。
Linus Torvalds 也曾公开反对这种限制,认为长行在某些场景下更自然。因此,没有统一标准,但我们可以参考一些通用建议。
3.1. 水平开放与密度
随着显示器分辨率的提升,我们可以参考 Uncle Bob 的建议:
✅ 每行代码控制在 100~120 字符之间,避免水平滚动。
像赋值操作符这样的关键位置应使用空格分隔,以增强可读性:
public class CountCharsInString {
public static void main(String[] args) {
String exampleString = "This is just a sample string";
long totalCharacters = exampleString.chars().filter(ch -> ch != ' ').count();
System.out.println("There are total " + totalCharacters + " characters in exampleString");
}
}
注意函数名与括号之间不需要空格,因为它们是强关联的。
3.2. 水平对齐与缩进
水平对齐不是必须的,有时甚至会误导阅读顺序。比如下面这种强行对齐的写法:
public FitNesseExpediter(Socket s,
FitNesseContext context) throws Exception
{
this.context = context;
socket = s;
input = s.getInputStream();
output = s.getOutputStream();
requestParsingTimeLimit = 10000;
}
读者可能会先看到变量名,而不是它们的赋值内容,容易产生混淆。
✅ 缩进才是代码结构的核心。
源码本质上是层级结构,缩进可以帮助读者快速识别代码块的归属关系。比如下面这个没有缩进的例子:
public class Factorial{ public static void main(String[] args){ final int NUM_FACTS = 100; for(int i = 0; i < NUM_FACTS; i++) System.out.println( i + "! is " + factorial(i));}
public static int factorial(int n){ int result = 1;for(int i = 2; i <= n; i++) result *= i; return result;}}
几乎无法阅读 ❌。
而加上缩进后,结构一目了然:
public class Factorial{
public static void main(String[] args){
final int NUM_FACTS = 100;
for(int i = 0; i < NUM_FACTS; i++)
System.out.println( i + "! is " + factorial(i));
}
public static int factorial(int n) {
int result = 1;
for(int i = 2; i <= n; i++)
result *= i;
return result;
}
}
4. 总结
虽然我们有自由选择代码格式,但必须意识到:别人将来可能会阅读甚至修改你的代码。团队协作时,应统一规范,保持项目风格一致,提升可维护性。
正如 Robert C. Martin 在《Clean Code》中所说:
“编码风格和可读性不仅影响当前代码,更会在项目演化过程中持续影响可维护性和可扩展性。你的风格和纪律会比你的代码活得更久。” ✅