代码规范

456 阅读4分钟

代码规范不仅在项目合作中影响非作者的阅读修改,导致他人无法接手,也一定程度上影响着代码的效率。软件系统思维有句话“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 考虑周全所有情况

用户输入是不是空值?

网络连接突然变换怎么办?

异常抛出怎么解决?

如何防止输入信息是注入代码?