关于编码规范和如何写出易读代码的心得

编写出规范,易读,优雅的代码能够大大方便代码的维护,推荐相关书籍——代码整洁之道。

目录

一、变量名

1.名字和变量的意义要一致;

2.一个变量,不能当成俩个变量来使用

二、方法

1.只关注一件事,那就是这个方法名所赋予的事

2.参数个数要少,这样耦合性就低,规范要求是少于5个

3.行数不易过多,50行左右,最多不过100行,一般超过100行,说明方法内部有代码需要整合成另一个方法,当然,赋值超过100行不算

4.方法内位于同一抽象层级

三、实体类

四、模型类

五、服务类

六、Controller类

七、mapper或者dao类


一、变量名

1.名字和变量的意义要一致;

2.一个变量,不能当成俩个变量来使用

场景:在一个方法内,程序员发现有一个字符串变量只有在最开始或者某一段中使用到时,为了充分利用这个变量,不再重新声明新变量,而是一直对该变量进行操作。

    private String getTempString(String type)
    {
        if ("xxx".equals(type))
        {
            return "";
        }
        
        String temp = "xxxxx";
        
        //下面全是对temp字符串进行操作,type已经没有用了
        return temp;
    }

对于上面那种情况,可能少部分程序员发现type只有在最开始用到了,而之后从来没有使用,那么他可能会选择不声明temp变量,而使用type来操作,这个时候,虽然你减少了局部变量的个数,但是变量的意义在这个方法内确有不同的意义了,那么对于后来维护代码的人来说,这是很痛苦的,并且这个方法的意义就是获取temp字符串,你返回一个type字符串,虽然可能最后的值相同,但是对于第三者来说,会觉得很矛盾。比如,上面的代码写成这样:

    private String getTempString(String type)
    {
        if ("xxx".equals(type))
        {
            return "";
        }

        type = "xxxxx";

        //下面全是对temp字符串进行操作,type已经没有用了
        return type;
    }

二、方法

1.只关注一件事,那就是这个方法名所赋予的事

2.参数个数要少,这样耦合性就低,规范要求是少于5个

3.行数不易过多,50行左右,最多不过100行,一般超过100行,说明方法内部有代码需要整合成另一个方法,当然,赋值超过100行不算

4.方法内位于同一抽象层级

举个例子,如下:

    private void deleteSomeThing(String user, String startTime, String endTime)
    {
        if (user.length() > 5)
        {
            user = user.substring(0, user.length() - 5);
        }

        Date startDate = simpleDateFormat.parse(startTime);
        Date endDate = simpleDateFormat.parse(endTime);

        Calendar startCalendar = Calendar.getInstance();
        startCalendar.setTime(startDate);
        /**
         * xxxxxxx
         * xxxxxxx
         * xxxxxxx
         * 一系列对user,startTime,endTime的操作,然后最后得到一个删除条件
         */
        String condition = "xxxxxx";
        //最后通过mapper或者dao操作数据库删除数据
        mapper.deleteSomeThingByCondition(condition);
    }

像这种,直接在一个方法内,写了太多的操作,如果逻辑复杂一点,行数就会飙升,代码可读性也变得很差;如果修改如下:

    private String getUserCondition(String user)
    {
        if (user.length() > 5)
        {
            user = user.substring(0, user.length() - 5);
        }
        //xxxxxxxx
        //xxxxxxxx
        //xxxxxxxx
        String userConditon = "xxxxx";
        return userConditon;
    }

    private String getTimeCondition(String startTime, String endTime)
    {
        Date startDate = simpleDateFormat.parse(startTime);
        Date endDate = simpleDateFormat.parse(endTime);

        Calendar startCalendar = Calendar.getInstance();
        startCalendar.setTime(startDate);
        //xxxxxxxx
        //xxxxxxxx
        //xxxxxxxx
        String timeCondition = "xxxxxx";
        return timeCondition;
    }

    private String mergeCondition(String userCondition, String timeCondition)
    {
        String allCondition = "xxxxx";
        return  allCondition;
    }

    private String getConditions(String user, String startTime, String endTime)
    {
        String userCondition = getUserCondition(user);
        String timeCondition = getTimeCondition(startTime, endTime);
        String condition = mergeCondition(userCondition, timeCondition);
        
        return  condition;
    }
    
    private void deleteSomeThing(String user, String startTime, String endTime)
    {
        mapper.deleteSomeThingByCondition(getConditions(user, startTime, endTime));
    }

其实,如果能够实现,每个方法抽象层级相同,那么方法的其他规范就很容易满足,像上面这种修改,通过抽象层级的划分,每个方法的行数一定会很少,参数也不会很多。虽然多出了很多方法,但是每个方法干什么都能一清二楚,并且可能不需要你阅读方法内的代码,你只需要看方法名就知道作用了。不过这个列子比较极端,拆分了很多方法,具体需要如何拆分,拆分多少个方法视情况而定,比如整个操作代码行数都不过50行,那么全部写在一个方法内也可以。

那么再回到抽象层级来讲,以这个列子为例,

第一层:deleteSomeThing(String user, String startTime, String endTime)

deleteSomeThing方法内部层级只有mapper层,和条件变量(可以把getConditions返回值返回给一个条件变量,然后mapper传入这个变量),因为当你要删除某些数据的时候,最直观的就是,调用mapper,删除满足条件的数据,至于,这个条件是什么,怎么获取,这个层级是不关心的;

第二层:getConditions(String user, String startTime, String endTime)

这个层级只需要返回条件给上一层调用,不需要操作参数来合成条件(当然,如果逻辑简单,也可以在这一次层级操作参数),所以他只关心条件本身,不关心条件如何操作。这个方法内部就只有各种已经处理好的条件变量。

第三层:

getUserCondition(String user)
getTimeCondition(String startTime, String endTime)
mergeCondition(String userCondition, String timeCondition)

这三层都是操作参数以返回目标条件格式,所以,这三层关心的就是对参数的操作。

三、实体类

至于数据库交互,与数据库表或者文档中的字段一一对应,不多不少;在新增数据,更新数据时使用该类。

四、模型类

与前端交互,前端需要哪些属性,模型类中就应该有哪些属性。

其实大部分情况系,模型类和实体类的属性字段相差不大,或者说可能一模一样,那么在这种情况下有必要分实体类和模型类吗?答案是肯定的,之所以有这两个层级,就是为了将保存数据和前端交互分隔开。考虑一种情况,当前实体类和模型类字段一模一样,那么不久之后因为业务的变更,模型类字段突然发生了大改变,但是保存的数据还是和之前一直,那么,如果最开始不区分实体类和模型类,都用同一个类,这个时候这个类的定义就会模糊了,因为这个类的字段是数据库表中的字段和前端需要的字段的融合,而且因为修改了这个类,可能会对于数据的保存和查询都产生影响。但是如果一开始就区分了,那么只需要修改模型类,对保存数据这部分是没有任何影响的。

五、服务类

提供一组功能,完成某个模块的所有功能,主要是对业务逻辑的处理

六、Controller类

与前端交互,只负责对前端数据的传递,接收和返回,不参与数据的处理、加工

七、mapper或者dao类

只与数据库交互,尽量不参与数据的加工。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章