分析一套源代码的代码规范和风格并讨论如何改进优化代码

我的工程实践选题主要是实现一个前后端分离的数据可视化项目,后端在数据获取这块,应用的是Mybaits框架,最近也一直在学习相关内容,以下分析的,便是一套基于Mybaits的增删改查入门案例。

一、分析源代码目录结构

 

 

/src  源代码目录

  /src/main  工程源代码目录

    /src/main/java  工程java源代码目录

    /src/main/resources  工程的资源目录(Mybatis、Spring等的配置文件)

  /src/test  单元测试目录

    /src/test/java  工程java单元测试目录,存放所有测试.java文件,如JUnit测试类

/target  输出目录,存放所有的输出文件(如 .class、.jar、.war 等文件)

 

  /target/classes  编译之后的class文件

Maven Dependencies  引到项目的jar包

pom.xml  maven最核心的配置文件,与构建过程相关的设置都在这个文件中配置

 

maven工程的目录结构均按此标准,实现项目的自动化构建。遵循 约定->配置->编码 的过程,可以进行配置的不需要专门编码指定,能按照实现约定好的规则处理的不需要再多余配置,能够减少多余劳动力,还能够预防低级错误。

 

二、文件名/类名/函数名/变量名等命名规范

 

 

 

符合Java的命名规范有两种:

1、camel命名方式:用于方法名和普通变量名称

  • 若标识是由单个单词组成的,则单词全部小写。例如:private Integer name;
  • 若标识是由多个单词组成的,则第一个单词为小写,第二个单词及其之后的,首字母均需大写。例如:private Integer myName;

2、pascal命名方式:用于类、接口命名

  • 类名是以大写字母开头的单词。例如:class User;
  • 若类名由多个单词组成,则每个单词首字母大写。例如:class MyUser;

类名:pascal命名方式

变量名(局部变量、形参、实例域、静态域):camel命名方式

函数名:camel命名方式

包名:全小写

常量:全部大写,多个单词之间用“_”隔开

类名、接口名:与源文件名一致

 

三、接口定义规范

 

 

 

 

接口定义统一放在 dao 文件夹中,因为是针对User类的相关属性进行“增删改查”,命名为“IUserDao”,I 代表 Interface,User 即对应相应的操作类,Dao 说明是数据操作层。

接口中定义的方法名,也以动词+名词的方法,体现其实现的功能。

 

四、单元测试组织形式

 

 

 

在 /test/java 的文件夹下,建立和 /main 文件夹一样的路径信息 /com/lyg,创建单元测试文件。命名规则为“待操作类+Test”。

 

 

 

引入 junit 包,实现单元测试功能。

 

 

 

 

针对待测试的功能,通过 @Test 注解,创建 “void  功能名”的方法,并在该方法中使用待测试的功能,运行单元模块,输出结果进行判断。

 

五、列举哪些做法符合代码规范和风格一般要求

 

如红圈标示所示,针对某一具体路径的 java工程,对应的配置文件,单元测试类所处的相对路径相同。使得整体一致,方便自动对应,减少设置路径的代码工作。

 

 

 

Mybatis的事务操作前需要设置配置并连接数据库,事务操作后需要提交事务并释放资源,在每个测试方法中都需要应用到。

通过@Before、@After的注解,抽离成独立的方法,提升了代码的可阅读性和简洁性。

 

 

 

Mybatis的特点之一在于,利用配置文件去实现Dao层的数据库操作,不需要程序员去具体实现接口功能。只要在接口对应的配置文件中将所需实现功能的SQL语句写好,即可实现该功能。极大简化了程序员的开发工作量,将精力集中在具体业务实现的逻辑中,简化其他繁琐工作。

 

六、列举哪些做法有悖于“代码的简洁、清晰、无歧义”的基本原则,及如何进一步优化改进

接口的方法定义中,void类型方法没有考虑失败情况,不返回任何数据。

改进:将void改为boolean类型,若成功返回true值,失败返回false。

 

同一接口返回格式不统一,有返回 User 的,也有返回 List<User>的。

改进:定义一个统一的格式类,ResultBean,集成所有相关类型。

 

 

 

七、总结同类编程语言或项目在代码规范和风格的一般要求(引用CSDN博主「下班后的爪哇菌」的博客内容https://blog.csdn.net/lxxiang1/article/details/81042604)

排版:

1、不同的程序块之间,用空行隔开。

2、较长的语句应该换行,并适当缩紧保持可读性。长表达式优先在操作符处划分,操作符放在新行之首。

3、一行只声明一个变量。

4、if、for、while、do while语句,哪怕只有一条语句,也必须使用{ }隔开。

5、类属性和类方法不要交叉放置,不同存取范围(private、protected、public)的属性或者方法也尽量不要交叉放置。

6、修饰词按照指定顺序书写:[访问权限][static][final]。

7、类内部的代码布局顺序:类属性、构造方法、方法、main方法

注释:

1、类和接口的注释放在class或者interface关键字之前,import关键字之后,使用“/** */”注释方式。

格式举例

/**

 * <一句话功能简述>

 * <功能详细描述>

 * @author [作者](必须)

 * @see [相关类/方法](可选)

 * @since [产品/模块版本](必须)

 * @deprecated (可选)

 */

 

2、类属性的注释放在属性前面

格式:

/**

 * 注释内容

 */

private String userName;

 

3、公共(public)和保护(protected)方法注释内容:列出方法的一句话功能简述、功能详细描述、输入参数、输出参数、返回值、异常等。

格式示例(根据各公司具体要求有所不同):

/**

 * <一句话功能简述>

 * <功能详细描述>

 * @param [参数1] [参数1说明]

 * @param [参数2] [参数2说明]

 * @return [返回类型说明]

 * @exception/throws [异常类型][异常说明]

 * @see [类、类#方法、类#成员]

 * @since [起始版本]

 * @deprecated

 */

注意:异常注释用@exception或@throws表示,在JavaDoc中两者等价,但推荐用@exception标注Runtime异常,用throws标注非Runtime异常。

异常的注释必须说明该异常的含义及什么条件下抛出该异常。


4、代码注释使用 // 进行,与其描述的代码相近,对代码的注释应放在其上方,并与其上面的代码用空行隔开,注释与所描述内容进行同样的缩进。

 

命名规则:

1、类名和接口名字使用意义完整的英文描述,增强可读性。每个英文单词的首字母使用大写,其余字母使用小写。

例如:ConnectionManager、UserDAO、Customer;

2、属性名使用意义完整的英文描述,第一个单词的字母使用小写,剩余单词的首字母大写、其余字母小写。属性名不能与方法名相同,集合意义的属性名使用复数形式。

例如:private String customerName; private List<Customer> customers;

3、方法名的命名规则基本与属性名相同,不过方法名一般以动词开头。

例如:private void initFrame(){ }

4、常量名使用全大写的英文描述,英文单词之间用下划线隔开,并使用final或者static final修饰。

例如:public final int MAX_VALUE = 1000;

 

性能与可靠性:

1、使用System.arrayCopy方法进行数组拷贝,提高性能。

int[] a = {3,5,6,12,45};

int[] b = {23,12,4,53,2};

System.arraycopy(a, 1, b, 2, 2);

for(int i=0; i < b.length; i++){

System.out.print(b[i]+" "); //23 12 5 6 2

}
2、把集合转换成数组时,使用Collection中的toArray方法,不要使用循环。

List<String> strList = new ArrayList<String>(15);

String[] strArr = new String[strList.size()];

String[] strs = strList.toArray(strArr);

3、大量字符串的相加等于处理应该使用StringBuffer。“大量”一般指5次“+=”以上或者在循环中进行字符串“+=”操作。

例如:

String[] strs = {"aa","bb","cc","dd","ee","ff","gg"};

String str = "";

for(int i = 0; i < strs.length; i++){

str += strs[i];

}

应改为

String[] strs = {"aa","bb","cc","dd","ee","ff","gg"};

StringBuffer sbf = new StringBuffer();

for(String str : strs){

sbf.append(str);

}
4、尽量使用JDK自带的API类库中的类和方法,不要自己写类似功能的类。API在可靠性、性能方面一般有更好的表现,必须熟练掌握,特别是算法方面的。

5、IO操作流使用有Buffer功能的类,如BufferedReader以及BufferedWriter,拥有更好的性能,没有Buffer的IO流频繁IO操作,效率相对低。

FileReader fr = new FileReader("D://test.txt");

BufferedReader br = new BufferedReader(fr);

String line = br.readLine();

while(line != null){

System.out.println(line);

line = br.readLine();

}
6、不要在循环内执行不必要的重复操作,可在循环外调用一次的,就避免在循环内进行不必要的反复调用。

例如:

for(int i = 0; i < result.size(); i++){

//...

}

应写成:

int size= result.size(); 

for(int i = 0; i < size; i++){

//...

}

7、除非必要,否则不要频繁在循环内创建对象,以免影响效率。

8、除非必要,否则尽量把循环次数多的循环放在内层,减少跨切循环的次数。循环次数不要超过三层。

posted @ 2019-10-09 21:52  lggang  阅读(263)  评论(0编辑  收藏  举报