public User getUser(String username, String telephone, String email);
// 拆分成多个函数
public User getUserByUsername(String username);
public User getUserByTelephone(String telephone);
public User getUserByEmail(String email);
将函数的参数封装成对象
public void postBlog(String title, String summary, String keywords, String content, String category, long authorId);
// 将参数封装成对象
public class Blog {
private String title;
private String summary;
private String keywords;
private Strint content;
private String category;
private long authorId;
}
public void postBlog(Blog blog);
public void buyCourse(long userId, long courseId, boolean isVip);
// 将其拆分成两个函数
public void buyCourse(long userId, long courseId);
public void buyCourseForVip(long userId, long courseId);
public List<Transaction> selectTransactions(Long userId, Date startDate, Date endDate) {
if (startDate != null && endDate != null) {
// 查询两个时间区间的transactions
}
if (startDate != null && endDate == null) {
// 查询startDate之后的所有transactions
}
if (startDate == null && endDate != null) {
// 查询endDate之前的所有transactions
}
if (startDate == null && endDate == null) {
// 查询所有的transactions
}
}
// 拆分成多个public函数,更加清晰、易用
public List<Transaction> selectTransactionsBetween(Long userId, Date startDate, Date endDate) {
return selectTransactions(userId, startDate, endDate);
}
public List<Transaction> selectTransactionsStartWith(Long userId, Date startDate) {
return selectTransactions(userId, startDate, null);
}
public List<Transaction> selectTransactionsEndWith(Long userId, Date endDate) {
return selectTransactions(userId, null, endDate);
}
public List<Transaction> selectAllTransactions(Long userId) {
return selectTransactions(userId, null, null);
}
private List<Transaction> selectTransactions(Long userId, Date startDate, Date endDate) {
// ...
}
针对这种情况,我们也应该将其拆分成多个函数
拆分之后的函数职责更明确,不容易用错
函数设计要职责单一
public boolean checkUserIfExisting(String telephone, String username, String email) {
if (!StringUtils.isBlank(telephone)) {
User user = userRepo.selectUserByTelephone(telephone);
return user != null;
}
if (!StringUtils.isBlank(username)) {
User user = userRepo.selectUserByUsername(username);
return user != null;
}
if (!StringUtils.isBlank(email)) {
User user = userRepo.selectUserByEmail(email);
return user != null;
}
return false;
}
// 拆分成三个函数
public boolean checkUserIfExistingByTelephone(String telephone);
public boolean checkUserIfExistingByUsername(String username);
public boolean checkUserIfExistingByEmail(String email);
对于函数的设计来说,更要满足单一职责原则
相对于类和模块,函数的粒度比较小,代码行数少
所以在应用单一职责原则的时候,没有像应用到类或者模块那样模棱两可,能多单一就多单一
移除过深的嵌套层次
定义
代码嵌套层次过深往往是因为 if-else、switch-case、for 循环过度嵌套导致的
个人建议,嵌套最好不超过两层,超过两层之后就要思考一下是否可以减少嵌套
过深的嵌套本身理解起来就比较费劲
嵌套过深很容易因为代码多次缩进,导致嵌套内部的语句超过一行的长度而折成两行,影响代码的整洁
去掉多余的 if 或 else 语句
// 示例一
public double caculateTotalAmount(List<Order> orders) {
if (orders == null || orders.isEmpty()) {
return 0.0;
} else { // 此处的else可以去掉
double amount = 0.0;
for (Order order : orders) {
if (order != null) {
amount += (order.getCount() * order.getPrice());
}
}
return amount;
}
}
// 示例二
public List<String> matchStrings(List<String> strList,String substr) {
List<String> matchedStrings = new ArrayList<>();
if (strList != null && substr != null) {
for (String str : strList) {
if (str != null) { // 跟下面的if语句可以合并在一起
if (str.contains(substr)) {
matchedStrings.add(str);
}
}
}
}
return matchedStrings;
}
使用编程语言提供的 continue、break、return 关键字,提前退出嵌套
// 重构前的代码
public List<String> matchStrings(List<String> strList,String substr) {
List<String> matchedStrings = new ArrayList<>();
if (strList != null && substr != null){
for (String str : strList) {
if (str != null && str.contains(substr)) {
matchedStrings.add(str);
// 此处还有10行代码...
}
}
}
return matchedStrings;
}
// 重构后的代码:使用continue提前退出
public List<String> matchStrings(List<String> strList,String substr) {
List<String> matchedStrings = new ArrayList<>();
if (strList != null && substr != null){
for (String str : strList) {
if (str == null || !str.contains(substr)) {
continue;
}
matchedStrings.add(str);
// 此处还有10行代码...
}
}
return matchedStrings;
}
调整执行顺序来减少嵌套
// 重构前的代码
public List<String> matchStrings(List<String> strList,String substr) {
List<String> matchedStrings = new ArrayList<>();
if (strList != null && substr != null) {
for (String str : strList) {
if (str != null) {
if (str.contains(substr)) {
matchedStrings.add(str);
}
}
}
}
return matchedStrings;
}
// 重构后的代码:先执行判空逻辑,再执行正常逻辑
public List<String> matchStrings(List<String> strList,String substr) {
if (strList == null || substr == null) { //先判空
return Collections.emptyList();
}
List<String> matchedStrings = new ArrayList<>();
for (String str : strList) {
if (str != null) {
if (str.contains(substr)) {
matchedStrings.add(str);
}
}
}
return matchedStrings;
}
将部分嵌套逻辑封装成函数调用,以此来减少嵌套
// 重构前的代码
public List<String> appendSalts(List<String> passwords) {
if (passwords == null || passwords.isEmpty()) {
return Collections.emptyList();
}
List<String> passwordsWithSalt = new ArrayList<>();
for (String password : passwords) {
if (password == null) {
continue;
}
if (password.length() < 8) {
// ...
} else {
// ...
}
}
return passwordsWithSalt;
}
// 重构后的代码:将部分逻辑抽成函数
public List<String> appendSalts(List<String> passwords) {
if (passwords == null || passwords.isEmpty()) {
return Collections.emptyList();
}
List<String> passwordsWithSalt = new ArrayList<>();
for (String password : passwords) {
if (password == null) {
continue;
}
passwordsWithSalt.add(appendSalt(password));
}
return passwordsWithSalt;
}
private String appendSalt(String password) {
String passwordWithSalt = password;
if (password.length() < 8) {
// ...
} else {
// ...
}
return passwordWithSalt;
}
学会使用解释性变量
常量取代魔法数字
public double CalculateCircularArea(double radius) {
return (3.1415) * radius * radius;
}
// 常量替代魔法数字
public static final Double PI = 3.1415;
public double CalculateCircularArea(double radius) {
return PI * radius * radius;
}