编写高质量代码的思考

前言

最近在看《代码大全》,可以说是一本软件开发的百科全书,特别厚,但是干货也很多。平时写代码,代码规范是一个最低的要求(很多老代码连最低要求都达不到),为什么要这样规定代码要这么写,而不是那么写?这是一个值得深究的问题。而不是说我照着代码规范写代码就算完了,高质量的代码是一个专业工程师的追求。要知其然知其所以然,最近写发票解析的代码,因为涉及带解析PDF的算法,复杂度比较高,所以花了很多时间在重构,学以致用的时候积累了一些心得。

信息隐藏原则

信息隐藏是面向对象设计的一个原则,是对封装和模块化的一个更高维度的概括。从Java的整个访问限制设计就体现了信息隐藏的原则,各种访问修饰符:public,protect,private,在类设计的时候,我们就要决定什么暴露给外部,什么隐藏起来。

举一个例子下面的代码表示一个有自增ID的Person类。

public class Person {

int id;

private static int G_MAX_ID = 0;

public Person() {

this.id = ++G_MAX_ID;

}

}

上面的类设计有什么问题呢?它违反了信息隐藏的原则,直接将ID分配的方式暴露了,这会给后面的维护带来很多问题:当你想给id的范围做出限制的时候怎么办?当你在所有代码中使用++G_MAX_ID分配ID时突然需要修改ID分配的算法怎么办?是不是需要去改所有++G_MAX_ID出现的地方?更好的设计是将ID的分配算法隐藏起来。

public class Person {

int id;

private static int G_MAX_ID = 0;

public Person() {

this.id = NewId();

}

private int NewId() {

return ++G_MAX_ID;

}

}

咋一看只是将++G_MAX_ID写到一个方法里面而已,但是它隐藏了ID分配的算法,让调用者不需要关心里面的实现,同时控制了变化,不管ID分配算法怎么变,都不会影响其他的代码。调用者了解的信息越多,受到的影响就越大,信息隐藏可以降低复杂度,控制变化的范围。

上面的例子只是信息隐藏的一个简单应用,下面我们来举几个其他的应用例子:

  • 为什么不推荐使用魔法值(即未经定义的常量)?:这个明显违反了信息隐藏的原则,当你将字面量直接写在代码里面时,就将信息直接暴露了,后面需要修改的时候,一旦少改了某个地方的字面量,bug就出现了。
  • 循环依赖(即A调用B,B调用A的情况):类或方法之间的循环依赖会破坏信息隐藏,一个很直接的影响就是在测试的时候,A,B都需要同时准备好才能进行测试,而无法mock任意一方。
  • 使用全局变量:这个就不用说了,所有人都可以访问你的时候信息就暴露无疑了,全局变量能不用就不用。
  • 考虑性能损失:有时候我们为了一些性能上的考虑就破坏信息隐藏原则,将一些变量全局化,这样性能提高得不多,维护成本却上升不少,完全是得不偿失。
    最后总结一下信息隐藏的好处:
  • 隐藏信息即隐藏了复杂度,降低了编程的负担。
  • 隐藏信息即隐藏了底层变化,以便于在局部控制变化。
    一些不太常见的编程技巧

函数(function)与过程(procedure)的选择

我们先来看看函数与过程区别:

  • Function:有返回值的方法
  • Procedure:没有返回值的方法
    平时我们编程其实没有太区别函数与过程,什么时候用函数,什么时候用过程其实没有过多的考虑,感觉都可以用。一个选择的规则就是当你的方法的目的是想返回跟你方法名称相符的值的时候用函数,否则用过程

举个例子,我看过很多XXProcessor接口里面的方法都是XX process(),严格来讲,这样的命名是不符合上面的规则的,process是一个没有含义的命名,但是却有返回值,如果没有返回值那它的命名才是合理的。

当然了,上面的规则仅供参考,世事无绝对,具体情况具体分析,当你不清楚用函数还是用过程的时候,可以参考这个规则。

使用boolean值来给程序做注释

相信大家看到一个if语句有很多条件的时候都会特别头痛,因为很难理解。例如下面的例子:

if ( ( elementIndex < 0 ) || ( MAX_ELEMENTS < elementIndex ) || elementIndex == lastElementIndex) {

do....

}

但如果换成下面的写法,用boolean值的名字来给if语句注释,看起来就很好理解了。

finished = ( ( elementIndex < 0 ) || ( MAX_ELEMENTS < elementIndex ) );

repeatedEntry = ( elementIndex == lastElementIndex );

if ( finished || repeatedEntry ) {

...

}

总结

怎么写高质量的代码是一个很大的话题,这里只是抛砖引玉,其实面向对象设计的很多原则都能够给我们写代码的时候提供指导,写代码的时候要时刻记得学以致用,而不是敷衍了事,专业的软件工程师必然要能写得一手好代码。

喜欢小编就关注小编吧!

原文地址:http://blog.51cto.com/13952975/2171402

时间: 2024-10-14 16:47:13

编写高质量代码的思考的相关文章

转载-------编写高质量代码:改善Java程序的151个建议(第1章:JAVA开发中通用的方法和准则___建议1~5)

阅读目录 建议1:不要在常量和变量中出现易混淆的字母 建议2:莫让常量蜕变成变量 建议3:三元操作符的类型务必一致 建议4:避免带有变长参数的方法重载 建议5:别让null值和空值威胁到变长方法              The reasonable man adapts himself to the world; The unreasonable one persists in trying to adapt the world himself. 明白事理的人使自己适应世界:不明事理的人想让世

编写高质量代码改善java程序的151个建议——[110-117]异常及Web项目中异常处理

原创地址:http://www.cnblogs.com/Alandre/(泥沙砖瓦浆木匠),需要转载的,保留下! 文章宗旨:Talk is cheap show me the code. 大成若缺,其用不弊.大盈若冲,其用不穷.  <道德经-老子>最完满的东西,好似有残缺一样,但它的作用永远不会衰竭:最充盈的东西,好似是空虚一样,但是它的作用是不会穷尽的 Written In The Font 摘要: 异常处理概述 学习内容: 建议110: 提倡异常封装 建议111: 采用异常链传递异常 建议

编写高质量代码改善C#程序的157个建议——建议78:应避免线程数量过多

建议78:应避免线程数量过多 在多数情况下,创建过多的线程意味着应用程序的架构设计可能存在着缺陷.经常有人会问,一个应用程序中到底含有多少线程才是合理的.现在我们找一台PC机,打开Windows的任务管理器,看看操作系统中正在运行的程序有多少个线程. 在笔者当前的PC机上,线程数最多的一个应用程序是某款杀毒软件,它一共拥有116个线程数:其次是Windows自身的System进程,当前共有104个线程:第三多的进程是Sqlservr.exe,锐减到了35个线程:剩下还有63个进程,估计它们平均约

编写高质量代码改善C#程序的157个建议——建议73:避免锁定不恰当的同步对象

建议73:避免锁定不恰当的同步对象 在C#中,让线程同步的另一种编码方式就是使用线程锁.线程锁的原理,就是锁住一个资源,使得应用程序在此刻只有一个线程访问该资源.通俗地讲,就是让多线程变成单线程.在C#中,可以将被锁定的资源理解成new出来的普通CLR对象. 既然需要锁定的资源就是C#中的一个对象,我们就该仔细思考,到底什么样的对象能够成为一个锁对象(也叫同步对象)?在选择同步对象的时候,应当始终注意以下几点: 1)同步对象在需要同步的多个线程中是可见的同一个对象.2)在非静态方法中,静态变量不

每周一书-编写高质量代码:改善C程序代码的125个建议

首先说明,本周活动有效时间为2016年8月28日到2016年9月4日.本周为大家送出的书是由机械工业出版社出版,马伟编著的<编写高质量代码:改善C程序代码的125个建议>. 编辑推荐 10余年开发经验的资深C语言专家全面从C语法和C11标准两大方面深入探讨编写高质量C代码的技巧.禁忌和实践 C语言因为既具有高级语言特性,又具有汇编语言特性,所以它是近二十几年来使用较为广泛.生命力较强的编程语言.无论是操作系统.嵌入式系统.普通应用软件,还是移动智能设备开发,它都能够很好地胜任,是公认的强大的语

代码质量优先——《编写高质量代码:改善c程序代码的125个建议》

高质量的代码不但可以促进团队合作.减少bug处理.降低维护成本,对程序员自身的成长也是至关重要的.很难想象一个参考<如何编写无法维护的代码>写代码的程序员技术成长的上限有多么低.为了写出高质量的代码,我们需要听取过来人的改善代码质量的经验,<编写高质量代码:改善c程序代码的125个建议>就是一本能让人写出高质量代码的好书. 本书的第三章<程序控制语句应该保持简洁高效>首先用简练的语言介绍了流程控制结构的概念,然后提供了对if.else.for.do-while.swit

[ 转 ]编写高质量代码:改善Java程序的151个建议

记得3年前刚到公司,同桌同事见我无事可做就借我看<编写高质量代码:改善Java程序的151个建议>这本书,当时看了几页没上心就没研究了.到上个月在公司偶然看到,于是乎又找来看看,我的天,真是非常多的干货,对于我这种静不下心的人真是帮助莫大呀. 看完整本书,也记了不少笔记,我就分享一部分个人觉得有意义的内容,也为了方便以后自己温习. --警惕自增陷阱 i++表示先赋值后自增,而++i表示先自增后赋值.下面的代码返回结果为0,因为lastAdd++有返回值,而返回值是自增前的值(在自增前变量的原始

编写高质量代码改善C#程序的157个建议——建议45:为泛型类型参数指定逆变

建议45:为泛型类型参数指定逆变 逆变是指方法的参数可以是委托或者泛型接口的参数类型的基类.FCL4.0中支持逆变的常用委托有: Func<int T,out TResult> Predicate<in T> 常用委托有: IComparer<in T> 下面例子演示了泛型类型参数指定逆变所带来的好处: class Program { static void Main() { Programmer p = new Programmer { Name = "Mi

编写高质量代码改善C#程序的157个建议——建议27:在查询中使用Lambda表达式

建议27:在查询中使用Lambda表达式 LINQ实际上是基于扩展方法和Lambda表达式的.任何LINQ查询都能通过扩展方法的方式来代替. var personWithCompanyList = from person in personList select new { PersonName = person.Name, CompanyName = person.CompanyID==0?"Micro":"Sun" }; foreach (var item in