>欢迎来到啾啾的博客🐱。
记录学习点滴。分享工作思考和实用技巧,偶尔也分享一些杂谈💬。
有很多很多不足的地方,欢迎评论交流,感谢您的阅读和评论😄。
目录
引言
从在大学机房里敲下Hello World那刻起,我踏入了编程的世界。
工作以来,不同的项目、不同的团队都带来有不同的编程规范,关于规范的注意事项是在太多太多,最后留在脑海里的只余下“可读性、可拓展性、设计原则”,让具体阐释一时间也说不出个所以然来。
哦,脑海里还余下了阅读、改动那些没遵守规范的代码时头疼的感觉。
为了消除这“头疼的感觉”,今天便系统整理一下代码规范,什么样的规范才是好的规范呢?
良好的命名规范能减轻工作负担。 —— 啾啾
先从命名开始。
命名——提炼含义减少注释
好的命名再怎么强调也不为过。
我们可能见过一些程序员,他们会为代码写上一大堆注释来说明这个方法做了什么。
可是事实上,“注释往往是最短命的代码”,注释本身有着不确定的一致性。
正确的做法是,提炼含义,使用描述明确的代码类、函数方法命名,好的代码注释应该解释“为什么”,而非“是什么”。(代码本身应该尽量自解释)
下面以一些Java基础类为例。
类名命名
先看一些Java源码示例。
类名 | 含义解析 |
---|---|
ArrayList | 基于数组(Array)的List实现 |
LinkedList | 基于链表(Linked)的List实现 |
TreeSet | 基于红黑树(Tree结构)的Set实现 |
SimpleDateFormat | 简单的日期格式化工具(Simple 修饰核心功能DateFormat ) |
FileInputStream | 基于文件(File)的输入流(InputStream)实现 |
类的命名上,要含义明确得体现实现方式或功能,避免模糊命名。
还有一种情况,即项目结构是Service、DAO、BO、VO这些,命名需要使用后缀体现层级关系。
类名 | 含义解析 |
---|---|
UserServiceImpl | 实现UserService 接口的业务逻辑类 |
OrderDAO | 数据访问层(DAO)的订单操作类 |
ProductBO | 业务对象(Business Object),封装业务逻辑 |
CartVO | 视图对象(View Object),用于前端展示的数据模型 |
接口与实现类的命名
接口/抽象类 | 实现类 | 含义解析 |
---|---|---|
List | ArrayList , LinkedList | 实现类通过后缀明确具体实现方式 |
Map | HashMap , TreeMap , LinkedHashMap | 实现类通过后缀明确具体实现方式 |
Collection | ArrayList , HashSet , PriorityQueue | 通过具体实现类名体现数据结构 |
方法命名的最佳实践
方法命名的核心原则是意图明确、参数隐含、无歧义。以下是具体示例和规则:
1. 方法名的结构
- 动词 + 对象/动作:方法名以动词开头,描述操作内容。
- ✅
addElement()
(添加元素) - ✅
calculateTotalPrice()
(计算总价) - ✅
saveToFile()
(保存到文件) - ❌
process()
(模糊,应具体化为processPayment()
或processRequest()
)
- ✅
2. 参数与返回值的隐含
- 通过方法名暗示参数和返回值的类型:
- ✅
findUserById(String id)
(隐含返回User
对象) - ✅
getMaxValue(int[] numbers)
(隐含返回最大值) - ❌
getSomething()
(不明确返回值类型或用途)
- ✅
3. 避免缩写
- ❌ 缩写:
calc()
(不明确) - ✅ 完整命名:
calculate()
(清晰)
4. 逻辑与副作用的体现
- 副作用:若方法有副作用(如修改状态),应在名称中体现:
- ✅
updateCache()
(明确修改缓存) - ✅
resetSettings()
(明确重置设置) - ❌
doAction()
(不明确副作用)
- ✅
5. 条件判断方法
- 布尔方法以
is
、has
、can
开头:- ✅
isConnected()
(判断是否连接) - ✅
hasPermission()
(判断是否有权限) - ✅
canExecute()
(判断是否可执行)
- ✅
长命名处理——实战答疑
在命名时,偶尔会有业务复杂命名难以提炼的情况。
处理方法
可以通过以下策略在保持清晰性和可维护性的同时缩短名称:
1. 利用上下文环境简化名称
-
类/模块上下文:在类或模块名中已体现的业务范围,方法名/变量名可省略重复信息。
- 示例:
// 类名已包含 "Transaction",方法名无需重复
public class TransactionProcessor {
private void validateTransaction() { ... } // 可简化为 validate()
private void calculateTotal() { ... } // 上下文已明确是交易总金额
}
-
参数/返回值隐含:通过参数名或返回值类型暗示功能,减少名称冗余。
- 示例:
// 参数已明确是 "User",方法名无需重复
public void sendVerificationEmailToUser(User user) { ... }
// 可简化为
public void sendVerificationEmail(User user) { ... }
2. 使用领域术语或缩写
-
领域术语:使用业务领域中的通用术语,减少冗余描述。
- 示例:
// 业务术语 "SubscriptionTier" 可直接使用
public double calculateDiscount(SubscriptionTier tier) { ... }
-
合理缩写:
- 通用缩写:如
Tx
(Transaction)、Svc
(Service)、Mgr
(Manager)。 - 团队约定:确保团队对缩写达成一致(如
User
代替UserAccount
)。 - 示例:
- 通用缩写:如
// 原名称:calculateCustomerDiscountBasedOnSubscriptionTier
// 简化后:calculateDiscountByTier(假设Tier是业务术语)
public double calculateDiscountByTier(SubscriptionTier tier) { ... }
3. 拆分复杂逻辑为小模块
-
方法拆分:将长方法拆分为多个职责单一的小方法,每个方法命名清晰。
- 示例:
// 原长方法:processOrderWithPaymentAndDelivery()
// 拆分后:
public void processOrder(Order order) {
validateOrder(order);
applyPayment(order);
scheduleDelivery(order);
}
-
类拆分:将复杂类拆分为多个子类或辅助类,通过组合提升可读性。
- 示例:
// 原类:OrderProcessorWithPaymentAndDelivery
// 拆分后:
public class OrderProcessor {
private final PaymentProcessor paymentProcessor;
private final DeliveryScheduler deliveryScheduler;
// ...
}
4. 使用组合命名结构
-
Builder模式:通过链式调用或构建器减少参数名称的冗余。
- 示例:
// 原名称:createOrderWithCustomerAndItemsAndDiscount()
// 使用Builder模式:
Order order = new Order.Builder()
.setCustomer(customer)
.addItems(items)
.applyDiscount(discount)
.build();
-
前缀/后缀模式:通过通用前缀或后缀表达功能,减少重复描述。
- 示例:
// 原名称:convertUserToUserDTO()
// 简化为:toDTO()
public UserDTO toDTO(User user) { ... }
5. 保留核心信息,舍弃冗余修饰词
-
去除冗余动词:如
get
、process
、handle
等,通过方法位置或参数推断功能。- 示例:
// 原名称:handleUserRegistrationRequest()
// 简化为:registerUser()
public void registerUser(User user) { ... }
-
聚焦核心业务:名称应体现“做什么”而非“如何做”。
- 示例:
// 原名称:calculateTotalPriceIncludingTaxAndDiscount()
// 简化为:calculateTotal()
// 通过注释或文档说明包含税和折扣
原始名称 | 优化后 | 策略 |
---|---|---|
getCustomerInformationFromDatabaseUsingId | findCustomerById() | 参数隐含(id )、领域术语(Customer ) |
validateUserRegistrationFormAndSaveToDatabase | registerUser() | 拆分方法,聚焦核心动作 |
TransactionProcessorForECommerceOrders | OrderTransactionProcessor | 上下文明确(ECommerce 是模块名) |
calculateMonthlySubscriptionCostBasedOnPlanTypeAndUserTier | computeSubscriptionCost() | 参数隐含(planType , userTier ) |
注意事项
-
避免过度缩写:确保缩写在团队中统一且易懂(如
Svc
代表 Service,但Svc
对新人可能不直观)。 -
保持一致性:同一项目中命名风格需统一(如是否使用
CamelCase
或Snake_Case
)。 -
注释补充:对于非常规缩写或复杂逻辑,可通过注释或文档说明。
-
IDE辅助:利用 IDE 的自动补全功能(如 IntelliJ 的智能提示),减少长名称输入负
总结原则
-
优先上下文:在类/模块/参数中已包含的信息,方法名/变量名可省略。
-
领域术语优先:使用业务领域中的通用术语替代冗长描述。
-
拆分优先:复杂逻辑拆分为小模块,每个模块命名清晰。
-
可读性 > 简洁性:宁可稍长但明确,也不要过于晦涩的缩写。