其他分享
首页 > 其他分享> > 由量变到质变 写出高质量代码

由量变到质变 写出高质量代码

作者:互联网

本文由于总结《阿里Java开发手册》、《用友技术review手册》及个人Java开发工作经验,并结合这半年来的源码阅读经验进行编写。回顾那些写过的 读过的代码,回顾自己。

第一章 基础编码规范

1.1 命名规范

1.2 常量定义

public enum SeasonEnum {
     SPRING(1), SUMMER(2), AUTUMN(3), WINTER(4);
     private int seq;     
     
     SeasonEnum(int seq){
         this.seq = seq;     
     } 
} 

1.3 代码格式

代码格式无非就是一些空格、换行、缩进的问题,没必要死记,直接用开发工具(eclipse、IDEA)format一下即可,省时省力。

1.4 OOP 规约

1.5 集合处理

// 正例:   
List<String> list = new ArrayList<String>(2);      
list.add("guan");      
list.add("bao");       
String[] array = new String[list.size()];      
array = list.toArray(array);    
// 反例:直接使用 toArray 无参方法存在问题,此方法返回值只能是 Object[]类,
// 若强转其它 类型数组将出现 ClassCastException 错误。 

// 这是我平时的写法,初始化一个list.size()大小的数组似乎效率更好一些,如果数组的容量
// 比list小,原来的数组对象不会被使用,浪费系统资源
String[] strs = list.toArray(new String[0]);
String[] str = new String[] { "you", "wu" };     
List list = Arrays.asList(str);   
第一种情况:list.add("yangguanbao"); 运行时异常。   
第二种情况:str[0] = "gujin"; 那么 list.get(0)也会随之修改。 
// <? extends T>:上界通配符(Upper Bounds Wildcards)  
// <? super T>:下界通配符(Lower Bounds Wildcards)   
List<? extends C> list1; // list1 的元素的类型只能是 C 和 C 的子类。
List<? super C> list2; // list2 的元素的类型只能是 C 和 C 的父类。
// 简单来说就是 <? extends C> 上界为 C 类型范围粗略理解为 [C,+∞),
// 不允许添加除 null 的元素,获取的元素类型是 C ;
// <? super C> 下界为 C 类型范围粗略理解为 (-∞,C],允许添加 C 以及 C 的子类类型元素,
// 获取的元素类型是 Object

// 扩展说一下 PECS(Producer Extends Consumer Super)原则。  
// 第一、频繁往外读取内容的,适合用<? extends T>。  
// 第二、经常往里插入的,适合用<? super T>。 
// 正例:
List<String> list = new ArrayList<>();      
list.add("1");      
list.add("2");    
Iterator<String> iterator = list.iterator();    
while (iterator.hasNext()) {          
    String item = iterator.next();                   
    if (删除元素的条件) {                          
        iterator.remove();                 
    }      
} 

// 反例:对比ArrayList的remove()和Iterator的remove()方法,可以找到其中的坑。
for (String item : list) {      
    if ("1".equals(item)) {          
        list.remove(item);          
    }      
} 
// 反例:下例中没有处理相等的情况,实际使用中可能会出现异常: 
new Comparator<Student>() {
    @Override
    public int compare(Student o1, Student o2) {
    	return o1.getId() > o2.getId() ? 1 : -1;
    }
};  
// 正例: 
// <> diamond 方式 
HashMap<String, String> userCache = new HashMap<>(16); 
// 全省略方式 
ArrayList<User> users = new ArrayList(10);
// 创建一个Map
Map<String, Object> infoMap = new HashMap<>();
infoMap.put("name", "Zebe");
infoMap.put("site", "www.zebe.me");
infoMap.put("email", "zebe@vip.qq.com");

// 传统的Map迭代方式
for (Map.Entry<String, Object> entry : infoMap.entrySet()) {
    System.out.println(entry.getKey() + ":" + entry.getValue());
}

// JDK8的迭代方式
infoMap.forEach((key, value) -> {
    System.out.println(key + ":" + value);
});
集合类 Key Value Super 说明
HashMap 允许为 null 允许为 null AbstractMap 线程不安全
ConcurrentHashMap 不允许为 null 不允许为 null AbstractMap 锁分段技术(JDK8:CAS)
Hashtable 不允许为 null 不允许为 null Dictionary 线程安全
TreeMap 不允许为 null 允许为 null AbstractMap 线程不安全

反例: 由于 HashMap 的干扰,很多人认为 ConcurrentHashMap 是可以置入 null 值,而事实上, 存储 null 值时会抛出 NPE 异常。

1.6 并发处理

// 正例: 
public class TimerTaskThread extends Thread {
	public TimerTaskThread() {
		super.setName("TimerTaskThread");
		...
	}
} 
// 正例:注意线程安全,使用 DateUtils。亦推荐如下处理: 
private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>() {
	@Override
	protected DateFormat initialValue() {
		return new SimpleDateFormat("yyyy-MM-dd");
	}
};    
// 说明:如果是 JDK8 的应用,可以使用 Instant 代替 Date,LocalDateTime 代替 Calendar, 
// DateTimeFormatter 代替 SimpleDateFormat,
// 官方给出的解释:simple beautiful strong immutable thread-safe。 
// 反例: 
class LazyInitDemo {
	private Helper helper = null;  
	public Helper getHelper() {
		if (helper == null) 
		synchronized(this) {
			if (helper == null)
				helper = new Helper();
			}
		return helper;
	}
	// other methods and fields...
}  
// 如果是 count++操作,使用如下类实现:   
AtomicInteger count = new AtomicInteger();
count.addAndGet(1);
// 如果是 JDK8,推 荐使用 LongAdder 对象,比 AtomicLong 性能更好(减少乐观锁的重试次数)。 

1.7 控制语句

if (condition) {
	...
	return obj;
}   
// 接着写 else 的业务逻辑代码;  
// 说明:如果非得使用 if()...else if()...else...方式表达逻辑,【强制】避免后续代码维护困难,
// 		请勿超过 3 层。  
// 正例:超过 3 层的 if-else 的逻辑判断代码可以使用卫语句、策略模式、状态模式等来实现,其中卫语句示例如下: 
public void today() {
	if (isBusy()) {
		System.out.println(“change time.”);
		return;
	} 
	if (isFree()) {
		System.out.println(“go to travel.”);
		return;
	} 
 	System.out.println(“stay at home to learn Alibaba Java Coding Guidelines.”);
 	return;
} 
// 正例: 
// 伪代码如下 
final boolean existed = (file.open(fileName, "w") != null) && (...) || (...); 
if (existed) {
	... 
}   
// 反例:在我们的代码中可以看到很多这种把复杂冗长的逻辑判断写在if语句中的
if ((file.open(fileName, "w") != null) && (...) || (...)) {
    ... 
} 

1.8 注释规约

注释感觉是我们代码规范的重灾区咯,也是大家最容易忽略的地方。

// 反例: 
// put elephant into fridge  
put(elephant, fridge);      
// 方法名 put,加上两个有意义的变量名 elephant 和 fridge,已经说明了这是在干什么,
// 语义清晰的代码不需要额外的注释。 

1.9 其它

第二章 异常与日志规范

2.1 异常处理

// 正例:
// 一个类中有多个 public 方法,都需要进行数行相同的参数校验操作,这个时候请抽取: 
private boolean checkParam(DTO dto) {...}

2.2 日志规约

import org.slf4j.Logger;  
import org.slf4j.LoggerFactory; 
 
private static final Logger logger = LoggerFactory.getLogger(Abc.class);  
// 正例:
//(条件)建议采用如下方式 
if (logger.isDebugEnabled()) {
    logger.debug("Processing trade with id: " + id + " and symbol: " + symbol);
}
// 正例:(占位符) 
logger.debug("Processing trade with id: {} and symbol : {} ", id, symbol);  
<!-- 正例: -->
<logger name="com.taobao.dubbo.config" additivity="false">  

第三章 数据库规范

我们 to B 的业务主要使用的是Oracle和SQL server,去年参与适配了国产的华为GaussDB及达梦DM数据库。

3.1 建表规约

3.2 SQL语句

3.3 ORM映射

我们的JDBC框架是自己研发的,之前也有看过Mybatis的源码,两者的设计及使用还是差别挺大的。

// 正例:
Map<String, Object> map = new HashMap<>();    
map.put("start", start);    
map.put("size", size);    

3.4 索引规范

安全规约

YupyMan 发布了39 篇原创文章 · 获赞 1 · 访问量 1万+ 私信 关注

标签:正例,质变,代码,量变,高质量,说明,索引,使用,方法
来源: https://blog.csdn.net/qq_38038396/article/details/104087549