编写高质量的代码(2)


编码前全面考虑所有可能的输入,确保写出的代码在完成了基本功能之外,还考虑了边界条件,并做好了错误处理。只要全面考虑到这三方面的代码才是完整的代码。

要重视代码的鲁棒性,确保自己写出的程序不会轻易崩溃。平时在写代码时,养成防御式编程的习惯,在函数入口判断输入是否有效并对各种输入做好相应的处理

目的:提高代码可读性、维护性,降低bug,提高程序性能,最终保证代码质量

建议+案例+原因;

checklist

 

阅读代码:了解其运行机制、内部结构;学习其技巧。

阅读代码可作为学习程序设计的方法。

花时间经常阅读高质量的代码——>提高编写代码的能力!“为什么要这样写?”

提高自身的开发和设计能力——>广泛阅读现有的构架,了解它们是如何组织的。

 

编写的代码总是存在改进的空间。

编码时就要考虑使之易于阅读。

 

分析设计良好的软件系统的内部系统可以学到新的构架模式、数据结构、编码方法、算法、风格和文档规范、应用程序编程接口、甚至新的计算机语言。

 

从小型的程序开始阅读,通过运行程序来得到反馈。主动修改代码来检验对代码的理解是否正确。要从小的改动做起,逐渐增大它们的范围。

考虑如何改进它?——更好的设计、算法或功能。为代码编写文档。

 

自身价值的体现——不是掌握了多少知识,而是体现在我们创造的系统上

 

物理模型

 

与代码相关的概念:

编程构造(基本编程元素)、数据类型、数据结构、控制流程、项目组织、代码规范、文档和构架。

 

在软件系统的工作投入中,40%~70%是用在系统首次编写完成之后。

 

 

1、原则

a、OCP开放-关闭原则:指导封装;

b、SRP单一职责原则:粒度控制;

c、DIP依赖倒置原则:

d、LSP里氏替换原则:指导多态;

e、ISP接口隔离原则:粒度控制;

 

2、避免错误

(1)合理使用注释

同步修改注释,和代码保持一致;

注释加在接口上;


(2)避免空指针:调用对象的方法,一定要明确该对象是否会空,不能确定时要判断!开发者常常自以为该对象不为null,而没有去看代码的实现或没有思考周全,漏掉了一些分支情况。

对于允许其值为null的变量,在对其操作前,需要预先判断其是否为null。


(3)Serializable对象

所有Serializable对象必须设置serialVersionUID,除非特殊情况。


序列化是为了保持版本的兼容性,即在版本升级时反序列化仍保持对象的唯一性。


(4)在finally中释放资源——数据库连接、打开的文件等。


3、维护性

(1)重复代码:

a、保持类和方法职责单一。(粒度划分)

b、尽量利用框架提供的功能。

c、采用合理的设计模式。


(2)异常处理:打印合理的异常。

a、只捕获对自己有意义的特定异常,一般不要捕获Exception异常;

b、抛出对自己无意义的异常,并保留原始的异常对象(嵌套异常),并描述异常的原因;

如:

try{

          createMember();

catch(SQLException e) {

           throw  new MemberCreationException("Failed to create member", e);

}

c、所有异常要么捕获、要么抛出、要么记录。


(3)常量定义(什么时候定义常量?在哪里定义?如何定义?

a、多次引用的字符串和数字需要定义常量;

b、根据引用的范围(同一个类、不同类):

类中;

单独的常量类或接口;

c、常量定义处需要详细的注释;


(4)在配置文件中指定字符集编码,由框架来转换字符串避免在代码中假设用户和系统的字符集编码

如:

下列代码“假设”了用户的字符集编码:

// 如果源代码是以GBK编译的,那么该URL也是GBK编码的,然而用户可能使用UTF-8编码

response.sendRedirect(http://localhost/mypage.htm?p=中文); 

 

//总是以GBK输出页面

response.setContentType("text/html; charset=GBK");

 

 

下列代码的结果依赖于操作系统的字符集编码:

Stringurl =URLEncoder.encode(str);            // str转换成URL兼容的格式byte[] 


bytes =str.getBytes();                  // string转成bytes

Stringstr = new String(bytes);                //bytes转成string

 

(5)避免硬编码URL、文件路径:因为URL、文件路径等资源的不确定性,应避免在程序中硬编码这些内容。

 

4、性能

(1)拼装字符串:用StringBuffer,而不用"+"或"+="来拼装大量字符串。可以使用StringBuilder来代替StringBuffer。前者是后者的非同步版本,性能更优。

如:StringBuffer sb = new StringBuffer();

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

    sb.append("aa").append(" ");

}

String str = sb.toString();

 

(2)预编译正则表达式

利用java.util.regex.*:

Pattern pattern = Pattern.compile("^\\d+$");

Matcher matcher = pattern.matcher(str);

if(matcher.matches()) {

}

而不是:

if(str.matches("^\\d+$")) {

}

 

(3)日志输出:要明白什么时候需要打印日志,采用什么级别打印日志。

不要以System.out和System.err来输出信息,而应该采用框架提供的Logging API。

在生产环境中必须关闭DEBUG日志。

 

正式使用日志时,尽量不要使用warn级别,避免日志文件臃肿。


(4)批量操作SQL

批量插入、更新操作:

PreparedStatement ps = conn.preparedStatement("insert into test_table(...) values(?,?,...)");

ps.setString(1,"aaa")

ps.addBatch();

.....

 

ps.executeBatch();

 

(5)线程同步:避免长时间地锁定线程。

 

4、开发技巧

(1)尽可能使用泛型而不是直接使用集合类:将运行时错误转化为编译时错误。

 

(2)开发小工具

Findbugs:

Relo:帮助开发人员研究大型代码库的好工具,它能一步步的跟踪你所展开的代码包,并快速生成类似UML的类图。

 

(3)阅读源码:JDK、Spring等。

 

5、TIPS

(1)不要往cookie中设置过多过大的数据。

 

(2)任何数据放入cache中都要考核这些数据是否符合三个指标(更新频率、访问量、命中率)。要把更新不频繁、访问量高、命中率高的数据放入cache中。同时慎用OSCache的文件持久化。

(3)在使用SQL语句时一定要清楚它的执行频率

 

(4)一条正确的SQL语句随着时间的推移,数据量越来越大,也可能不合适了。在使用SQL语句时一定要弄清楚它的数据量的增长

 

(5)如何区分好代码与坏代码

 

(6)阅读代码的方法

 

6、PS

(1)《effective java》、《重构》

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值