代码规范不仅在项目合作中影响非作者的阅读修改,导致他人无法接手,也一定程度上影响着代码的效率。软件系统思维有句话“Less coding, more thinking(少编码、多思考)”,也有这么一句俚语“Think more, code less(思考越多,编码越少)”本文以java为例,说明一些常见的问题和注意事项。
1. 使用通用的工具函数
案例一 不完善的写法:
!(list == null || list.isEmpty();
案例一 修改方案:
import org.apache.commons.colections4.CollectionUtils;
Collections.isNotEmpty(list);
修改原因:一 函数式编程,业务代码减少,逻辑清晰
二 通用函数工具考虑周全,出错率低
2. 拆分较大函数
如果一个函数超过80行,就属于较大函数,需要进行拆分,可以将每个代码块写成一个函数
案例一 不完善的写法
public void liveDaily(){
// 吃饭,相关代码几十行
// 工作,相关代码几十行
// 睡觉,相关代码几十行
}
案例一 建议方案
将每个代码块封装成函数
public void liveDaily(){
eat();
work();
sleep();
}
private void eat(){
//吃饭相关几十行代码
}
private void work(){
//工作相关几十行代码
}
private void sleep(){
//睡觉相关代码几十行
}
案例二 不完善的写法:
//生活函数
public void live(){
while(isAlive){
eat();
work();
sleep();
}
}
案例二 建议方案:将每个循环体分装成函数
//生活函数
public void live(){
while(isAlive){
//每日生活
liveDaily();
}
}
private void liveDaily(){
//吃饭
eat();
//工作
work();
//睡觉
sleep();
}
案例三 不完善的写法
//外出函数
public void goOut(){
//判断是否为周末,是周末就出去玩
if(isWeekDay()){
//玩游戏代码几十行
}else{
//工作代码几十行
}
}
案例三 建议方案将每个条件体封装成函数
//外出函数
public void goOut(){
//判断是否是周末
if(isWeekDay){
//周末就玩
play();
}else{
//工作日就工作
work();
}
}
private void play(){
//玩的代码几十行
}
private void work(){
//工作的代码几十行
}
修改原因:一 函数越长越不容易维护
二 过长函数,难以发现重复代码
3.同一函数代码块最好在一个级别上
案例一 不完善的写法
//每日生活函数
public void liveDaily(){
//吃饭
eat();
//工作
work();
//睡觉
//睡觉几十行代码
}
案例一 修改方案//每日生活函数
public void liveDaily()
{
//吃饭
eat();
//工作
work();
//睡觉
sleep();
}
private void sleep(){
//睡觉几十行代码
}
修改原因:一 函数表达逻辑易于实现,层次感分明
二 不同量级的代码块放在一个函数内,头重脚轻
4. 封装相同功能代码为函数
案例一 不完善的写法
//禁用用户函数
public void disableuser(){
//禁用黑名单用户
List<Long> userIdList = queryBlackUser();
for(Long userId : userIdList){
User userUpdate = new User();
userUpdate.setId(userId);
userUpdate.setEnable(Boolean.FALSE);
userDAO.update(userUpdate);
}
//禁用过期用户
userIdList = queryExpireUser();
for(Long usrId:userIdList){
User userUpdate = new User();
userUpdate.setId(userId);
userUpdate.setEnable(Boolean.FALSE);
userDAO.update(userUpdate);
}
案例一 修改方案
封装相同功能代码为函数
//禁用用户函数
public void disableuser(){
//禁用黑名单用户
List<Long> userIdList = queryBlackUser();
for(Long userId : userIdList){
disableUser(userId);
}
//禁用过期用户
userIdList = queryExpireUser();
for(Long usrId:userIdList){
disableUser(userId);
}
//禁用用户函数
private void disableUser(Long userId){
User userUpdate = new User();
userUpdate.setId(userId);
userUpdate.setEnable(Boolean.FALSE);
userDAO.update(userUpdate);
}
案例二 不完善的写法//通过工单函数
public void adoptOrder(Long orderId){
Order orderUpdate = new Order();
orderUpdate.setId(orderId);
orderUpdate.setStatus(OrderStatus.ADOPTED);
orderUpdate.setAuditTime(new Date());
orderUpdate.update(orderUpdate);
}
//驳回工单函数
public void rejectOrder(Long orderId){
Order orderUpdate = new Order();
orderUpdate.setId(orderId);
orderUpdate.setStatus(OrderStatus.REJECTED);
orderUpdate.setAuditTime(new Date());
orderUpdate.update(orderUpdate);
}
案例二 修改方案将相似代码封装
//通过工单函数
public void adpotOrder(Long orderId){
auditOrder(orderId,OrderStatus.ADOPTED);
}
//驳回工单函数
public void rejectOrder(Long orderId){
auditOrder(orderId,OrderStatus.REJECTED);
}
//审计工单函数
private void auditOrder(Long orderId,OrderStatus orderStatus){
Order orderUpdate = new Order();
orderUpdate.setId(orderId);
orderUpdate.setStatus(orderStatus);
orderUpdate.setAuditTime(new Date());
orderUpdate.update(orderUpdate);
}
修改原因:减少代码函数,可读性、可维护性增强
5. 封装获取参数值函数
案例一 不完善的写法
//是否通过函数
public boolean isPassed(Long userId)
{
//获取阈值
double thisPassThreshold = PASS_THRESHOLD;
if(Objects.nonNull(passThreshold)){
thisPassThreshold = passThreshold;
}
//获取通过率
double passRate = getPassRate(userId);
//判断是否通过
return passRate >= thisPassThreshold;
}
案例二 修改方案//是否通过函数
public boolean isPassed(Long userId)
{
//获取阈值
double thisPassThreshold = getPassThreshold();
//获取通过率
double passRate = getPassRate(userId);
//判断是否通过
return passRate >= thisPassThreshold;
}
//获取通过阈值函数
private double getPassThreshold(){
if(Objects.nonNull(passThreshold)){
return passThreshold;
}
return PASS_THRESHOLD;
}
修改原因:
获取参数值拿出来,业务逻辑清晰且方便重复调用
6 行间距
不同函数之间空两个空行,一个函数内部空一行
//一天生活函数
public void liveDaily()
{
//吃饭
eat();
//工作
work();
//睡觉
sleep();
}
//吃饭函数
public void eat()
{
}
//工作函数
public void work()
{
}
//睡觉函数
public void sleep()
{
}
7 驼峰命名法
studentNumber
className
liveDailyFunc
8 简洁干净的注释
//用户注册
public bool register()
{
}
9 打印相关信息
养成打印的习惯,方便后期debug
10 考虑周全所有情况
用户输入是不是空值?
网络连接突然变换怎么办?
异常抛出怎么解决?
如何防止输入信息是注入代码?