Profil de javax咖啡生活PhotosBlogListes Outils Aide

javax

21 juin

软件设计编程得基本技术

1.设计父类时考虑不周到,等到设计或者编写子类的时候,才发现父类需要修改、增加功能等等,都很平常

2.尽量避免多次写同样的代码

3. 持续改进

4.评价软件设计的高低的几个基本原则

内容

1.软件设计/编程中,有一门基本技术叫“面向对象编程”。面向对象编程的基本思路是对象封装和继承。继承的基本思路是,所有子类共同的部分,提取、抽象后,放到父类中。

这是一个说起来容易,做起来难的事情。父类总是先设计,先实现。一个父类一般都有多个子类。没有人能够先知先觉。设计父类时考虑不周到,等到设计或者编写子类的时候,才发现父类需要修改、增加功能等等,都很平常。例如
public class RequestInfo{
    public DataItem getDI(String name){
    }
}

public class DataItem{
    public String getValue() {
    }
}

当我们经常写
String cycCode = info.getDI("cycCode") == null ? null : info.getDI("cycCode").getValue();

的时候,我们自然会想,如果在 class RequestInfo 中增加一个函数 getDIValue() 就可以写更短的代码了:
String cycCode = info.getDIValue("cycCode");
这样做的好处,代码更简洁,更易懂,也更容易维护。
同样的道理,当我们经常需要从 info 中取 int value 的时候,我们自然会知道,应该往 class RequestInfo 中增加 getIntValue().

2.在软件开发的过程中,最基本的原则是,避免多次写同样的代码。举例来说:

这是很常见的基类设计时考虑不周导致的问题,每个子类有同样的代码,。解决方法也很简单,将共同的部分放在 base class 中就可以了:

 

3.软件行业和其他行业一样,要想做出质量好的产品,关键在于“持续改进”。持续改进的意思是,如果发现了不好的设计,就应该修改。然而,很多时候事情并不这样简单。
例如,一个公司有两百个同样的生产线,现在有人发现了一个改进办法,可以提高效率。我们都知道,不可能把所有的生产线同时进行改造,那样对于现有的生产造成很大的影响,并且从人力物力方面,也有很大问题。更好的办法是,对于新的生产线,采用新的改进办法。原有的生产线,既然还能工作,就不用立即修改,可以在以后逐步改进。
这个例子换成软件行业的话:
一个公司有两百个类似功能的软件模块/类(比如 xxxBPI),现在有人发现了一个改进办法,可以在子类中写更少的代码,提高效率,代码更易于维护。我们都知道,不可能把所有 xxxBPI同时进行改造,那样对于现有的开发造成很大的影响,并且从人力物力方面,也有很大问题。更好的办法是,对于新的xxxBPI,采用新的改进办法。原有的代码,既然还能工作,就不用立即修改,可以在以后逐步改进。

因此,大型的软件中,新老方法并用的情况很多。比如, MS SQL Server, 很多原有的代码是从 Sybase 购买,MS 的技术专家发现了一些提高性能的办法,在经过多年,多个版本更新后,才逐步完成了改进老的代码。在开源的项目上面,也有很多项目版本说明中申明,计划采用某某技术改写原有的代码,目前完成哪些模块,计划增加哪些模块。改进和增加新功能永远是同时进行的。

上面的例子,采用持续改进的方法后,变成下面的样子:

4.评价软件设计的高低的几个基本原则

评价软件设计的高低的几个基本原则依次为:易懂,易用,稳定性,功能。
易懂:VB 的用户之所以比 VC 多,在于它易懂。用 Word 写设计文档的人比用 Rose 的人多,也在于懂 Word 的人更多。易懂意味着可以用更短的时间学会。
易用:如果 class A 和 class B 完成同样的功能,但使用 class A 需要写的代码更少,我们就说 class A 设计得比 class B 更好。因为使用 class A 写代码,代码更短,开发效率更高。代码短对于以后的维护也更容易。
稳定性,功能:软件的卖点在于稳定性,功能。之所以这两项排在前面亮项后面,同样有事实为证:Unix/Linux 的稳定性、功能超过于 Windows,但是它的用户反而少,原因就在于它输在 “易懂,易用”这两项上面。



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=98170

[点击此处收藏本文]   jacklondon发表于 2004年09月08日 13:37:00
 
chon 发表于2004-09-19 08:20:00  IP: 218.86.50.*
class A 需要写的代码更少,我们就说 class A 设计得比 class B 更好

这个说法是错的,很多高效的算法的代码都会比一般的方法代码要少,担是它很容易带来一个难以维护的问题.
还有一些教学上的方法,如i+++i+++++i什么的运算式,它也是很短的,但是它就有一个难以理解的坏味道,我就会把它分成多个式子,容易看懂.

所以,代码少,就会容易出现难以理解的坏味道.

 
Jacklondon Chen 发表于2004-09-19 21:40:00  IP: 61.149.102.*
在同样容易理解的情况下面,使用MS XML lib 写程序比使用 IBM XML lib 的代码少,因此我们认为MS XML lib 设计得更好。
一般来说,组件完成功能是第一步,接口简化是第二步,更高级的一步。

Jakarta Project 的 Commons tools各个子项目

Apache 的 Jakarta Project  里面有很多子项目。其中的 Commons 着眼于提供各种很通用的函数/类,这

样大家可以在平时自己的项目中用。这些 tools 因为非常 common, 以至于无论你用哪种 framework ,你

可以用到其中的一部分,来节省自己的编码量,并且其代码质量也是非常不错的。

Commons tools 一部分出发点在于解决 JDK 中的各种不足:

1. Exception 不好用,不得不写很多 try catch, 而改成使用 C/C++ 常用的以返回值判断,可以少写很多代

码。这方面以 jdbc interface 最为臭名昭著。

2. 弥补 JDK 类库的不完善地方。比如 String , Collection Framework, 正则表达式等等。

打算写文章介绍其中几个我认为比较通用的东西:

Codec 包含 Hex, Base64, URL 的编码和反解码。对于 web 应用很有用处。

Commons-Collections 增强 jdk 的 Collection Framework 功能。

Commons-Configuration 读写配置参数。大多数程序都有运行参数放在某个地方,这个工具可以读写各种参数格式:数据库,xml ,Properties 文件,系统变量,等等。强吧?

Commons-DBCP 数据库连接池,呵呵,现在连接池很多服务器都自带。但也有很多直接用这个。如果写 java application 要用到数据库,用这个吧。

DbUtils 可以减少写 JDBC 程序的 try catch, 减少代码量。一个我想写一直没有时间写的东西。但没有想象中那么好。

Email 发电子邮件。JDK 标准库对于发电子邮件支持不强,很让人看不懂。

FileUpload 文件上传。J2EE 标准库对于文件上传支持不强,也让人看不懂。这两个功能对于现在的 j2ee 应用来说,是基本功能了。稍微大一点的系统都会有。

IO 虽然 jdk 号称 IO 重写了,并且还用了 nio(new IO) 的 package 名,但是还是不够好。这个可以看作是增强版了。

Commons-Lang 好东西。 lang 包是 java 最基本的包,默认自动 import , 功能还是不够强,补补!这个包在其他系统,包括 weblogic, websphere 中都大量用它。基本上凡是有点名气的 java 系统都会用它。

Commons-Logging 好东西。大多数 EJB server 和 tomcat 都用到它。开源的 java project 也大部分用它。log 的抽象层。Java 中的 log 以前有很多种,如果你选了一种开发程序,以后想换另一种,比较麻烦。通过这个工具抽象一把,就很容易换了。不过最近 log4j 一支独大,JDK 自带的 log 没有几个人用,似乎不会有人换其他的 log, 让人搞不懂。

Math 呵呵。Java 中的 Math 包只能勉强够用,如果稍微偏们一点的数学函数,都要自己写了。用它吧,节省时间。

Net 增强 Java 网络功能。Java 的网络类库比起专业一点的 C++ 网络类库,差别还是很大。这里还是增强一点为好。

Commons-Pool 普通的对象池。不是 EJB 的对象池。池这个东西,很难写好。弄不好特耗内存,速度反而慢(比如 EJB)。无论如何,是个好的思路,可以借鉴。

Validator 这是好东西。不管是写 web 应用程序还是普通 java 应用程序,只要有用户输入界面,都用得上。比自己写省事阿。不赞成写在 xml 中,多一个字母少一个字母很难查。

Commons project 下面还有 Sandbox,包含Cache ,Clazz ,Compress, Convert ,I18n,Id ,Mapper, SQL ,ThreadPool 等等,很多都用得上。哎,好东西真多,怎么介绍得完呢?

慢慢来,一个一篇文章,慢慢来。希望大家支持。

Apache Jakarta Common Configuration, 系统配置, 工具包

在很多系统中,需要用到配置文件来存放配置参数。配置参数从代码中单独提出来主要是为了方便修改用的。常见的一个用法是将数据库连接参数(数据库服务器 IP,用户名,密码等等)写在一个配置文件中,这主要是系统可能会更换数据库,或者网络可能更换 IP 地址范围,或者服务器 IP 可能会变动等等。
  
  配置参数不仅限于配置文件,也可以保存在其他地方,比如数据库单独用一个表保存配置参数,或者在内存中,或者在操作系统环境变量中,等等。有个现成的读写配置数据工具包,让人感觉很不错。
  
  早期的配置文件主要用 ini 文件,或者类似 ini 文件格式。这种配置文件格式简单,相应的读写工具类也很容易写,各种开发语言基本上都能在网上找到现成的代码。其主要特点是 key <--> value 对应。ini 文件是纯文本文件,对于不是程序员的最终用户,修改 ini 配置文件也没有太多的难度。相比较而言,其他格式的配置都比 ini 有更大的难度。

  可惜的是 Common Configuration 工具包不支持 ini 格式。文档中说它支持的配置参数来源有:
  * Properties files
  * XML documents
  * Property list files (.plist)
  * JNDI
  * JDBC Datasource
  * System properties
  * Applet parameters
  * Servlet parameters

  数据形式也不限于 key <--> value 形式,Common Configuration 工具包也支持树形结构的参数配置。

  Common Configuration 工具包体系比较简单。一个基本的 Configuration interface 定义了各种配置通用的操作,一个 AbstractConfiguration 从 Configuration interface 下来将所有公用的操作实现了,留下一个不通用的函数 getProperty, setProperty 等待子类实现。真正有实际操作的 DatabaseConfiguration、PropertiesConfiguration、XMLConfiguration、XMLPropertiesConfiguration、MapConfiguration 等等,都是从 AbstractConfiguration 继承。MapConfiguration 是基于内存操作的配置参数读写工具类,XMLPropertiesConfiguration 则是基于 XML 文件的模仿 java properties 格式的配置文件读写工具类。有点怪吧?主要是因为 java property 文件本来设计只是为了存放多语言字符串用的,有的 java 程序员希望在 java 中有类似 INI 文件的配置文件,但是 JDK 中没有现成的工具类,只能用 property 文件凑合着用。举例来说, log4j 就可以用 property 格式的配置文件。但是这种格式的配置文件有个很大的弱点,如果里面包含非 ASCII 字符,比如说是中文,必须要写成 UNICODE 编码格式。如果软件交付给用户,用户需要改一个参数,用户没有办法改这种 property 文件。XMLPropertiesConfiguration 使用的是 XML 格式配置文件,一般用 UTF-8 编码,这种文件可以用常用操作系统自带的软件来修改(比如 windows 的记事本程序),因而更加方便。XML property 格式配置文件现在已经用得比较多了,在 J2SE 5.0 中也定义了一种 XML property 格式,这里的 XMLPropertiesConfiguration 工具类就是遵循这种格式标准。

  Configuration interface 定义了一些基本操作:addProperty, clear, clearProperty, containsKey, getBigDecimal, getBigInteger, getBoolean, getByte,getDouble,getFloat,getInt, getKeys, getList, getLong, getProperties, getProperty, getShort, getString, getStringArray, isEmpty, setProperty 等等。看起来还是比较齐全。也可以用 DataConfiguration 将已有的 Configuration 重新包装一下,然后可以读写其它类型的配置参数:URL, Locale, Date, Calendar, Color, 以及各种形式对象的  lists 和 arrays。DataConfiguration 主要做的事情是在读写配置数据的时候将这些额外的类型数据与 String 类型相互转换,最终所有配置参数还是保存成 String 形式。

  这里面还有另外一个类 CompositeConfiguration, 可以将几个 Configuration 并在一起用,这不太常见,偶尔会用到。举例来说,将数据库连接参数放在文件型配置文件中,将系统其他参数放在数据库中是一个比较常见的设计。如果几个程序员同时调试程序,可能需要将数据库中同一个配置参数设置成不同的值,这个时候就比较麻烦,要吵架了。这个时候可以将文件型配置和数据库配置做成一个组合配置CompositeConfiguration, 优先读取文件型配置中参数,如果文件型配置参数中没有才读取数据库中参数。这样就可以解决了。真正最后系统交付的时候把所有配置放在数据库中,只留下数据库连接配置放在文件型配置中。

  值得注意的是,有的 Configuration 性能不够优化,可能需要自己写一个相应的子类将 getProperty, setProperty 等函数重新写一下。现成的思路是,DatabaseConfiguration 每次 getProperty 都读取一次数据库,如果不是在集群环境,可以把所有配置数据一次读出放在一个 map 中,这样每次 getProperty 速度快很多。

  无论如何,Common Configuration 是一个非常优秀的 java 工具包。我注意到,在它的开发 roadmap 中,INI 格式配置计划在 1.3 版本中支持,应该说 INI 格式不难,不知道为什么要放到 1.3 版本中才能实现。1.3 版本还计划支持 windows 注册表格式的配置,个人觉得没有什么大的用处。其他有些稀奇古怪的计划,可能是有的开发人员提出的不太通用的一些要求。从目前的开发版本的 bugzilla 上面看,没有较核心的 bug ,比较让人放心,值得推荐。

Apache Jakarta Common Lang 介绍

无论你在开发哪中 Java 应用程序,都免不了要写很多工具类/工具函数。你可知道,有很多现成的工具类可用,并且代码质量都很不错,不用你写,不用你调试,只要你发现。
  在 Apache Jakarta Common 中, Lang 这个 Java 工具包是所有 Apache Jakarta Common 项目中被使用最广泛的,几乎你所知道的名气比较大的软件里面都有用到它,包括 Tomcat, Weblogic, Websphere, Eclipse 等等。我们就从这个包开始介绍整个 common 项目。
  Lang 中最大的也是最常用的类是 StringUtils, StringUtils 最常用的函数是 isEmpty。这里举一个例子让你熟悉一下:

  String str = null;

  if(StringUtils.isEmpty(str)){

  }

  str = StringUtils.lowerCase(str);
  str = StringUtils.capitalize(str);
  str = StringUtils.swapCase(str);
  StringUtils.isNumeric(str);
  StringUtils.isAsciiPrintable(str);
  StringUtils.equalsIgnoreCase(str,"");

  其中,
  if(StringUtils.isEmpty(str)){

  }
  相当于
  if(str == null || str.length() == 0){

  }


  从以上代码可以看出这个工具类的特点:
  第一、这些函数都是静态函数,并且很少抛出异常,也很少抛出空指针异常。
  第二、这些函数的功能大多是增强标准 Java 中 java.lang.String 类的功能。

  其实,整个 lang 包的函数基本上都在增强 java.lang 包的功能。一个有趣的设计是,虽然 StringUtils 里面的函数都是静态函数,按照通常的做法,会把构造函数设计成 private, 但是不!StringUtils 的构造函数是 public 的。构造函数里面的注释写着 "no init"。这就有意思了,你可以 new 一个 StringUtils,虽然没有特别的好处,但是也没有特别的坏处;你可以写一个 StringUtils 的子类,虽然这也不太常见。这里面的思想似乎是,使用这个工具包的软件开发人员想怎么用就怎么用,做工具类的时候不用太多限制。
  至于不抛异常是因为现在很多人已经意识到 Java 中的异常不是什么好东西,如果不用异常也能写程序,为什么还要用异常?用了异常就要写很多 try catch,在很多场合,比如 jdbc driver,这已经证明了会使代码量增加并且代码的可读性变差。
  这里的思路会不会影响大家写程序的习惯呢?

  StringUtils 的函数很多,不一一列举。 Lang 中次重要的类要数 ArrayUtils,主要功能涉及到数组的比较、转换、拆分、合并、查找、增减、倒转等等操作。在 JDK 中,这类操作没有现成的函数。

  Lang 中工具类比较多,这里介绍几个主要的:
  ClassUtils getShortClassName,这个函数应该在 java.lang.Class 类中有的,我看到很多人自己写这个函数。getAllInterfaces,convertClassNamesToClasses,isAssignable,primitivesToWrappers,isInnerClass。
  NumberUtils 关于数字以及数字和字符串转换的类 stringToInt,toDouble,createNumber,isAllZeros, int compare(float lhs, float rhs), isNumber(String str),double min(double[] array)。
  RandomUtils 用于产生随机数的。
  DateFormatUtils 日期时间格式转换,以及本地时间和 UTC 时间转换。
  DateUtils 日期工具类。isSameDay,truncate,round,modify。

  基于反射机制的几个类:
  CompareToBuilder 比较,用在算法、排序、比较的地方。reflectionCompare,append。
  EqualsBuilder 通过反射机制比较。reflectionEquals 很多项目中用到。
  HashCodeBuilder 可以通过反射生成 hash code,很多算法的地方涉及到 hash code,但是并不是每个人都知道一种 hash code 的生成方法。
  ToStringBuilder 当你需要重载 toString 函数而不想写代码把当前类的所有成员信息列出来,可以用这个函数。

  其它的几个类我用得比较少:
  SerializationUtils Java 中得序列化比较奥妙,容易出错啊。
  SystemUtils 可以读取一些关于 jdk 信息,操作系统信息的工具类。


instanceof应用

instanceof
instanceof是Java的一个二元操作符,和==,>,<是同一类东东。由于它是由字母组成的,所以也是Java的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例,返回boolean类型的数据。举个例子:

String s = "I AM an Object!";
boolean isObject = s instanceof Object;

我们声明了一个String对象引用,指向一个String对象,然后用instancof来测试它所指向的对象是否是Object类的一个实例,显然,这是真的,所以返回true,也就是isObject的值为True。

org.apache.commons.beanutils.BeanUtils 简介

BeanUtils简读本
一、简介:

BeanUtils提供对 Java反射和自省API的包装。其主要目的是利用反射机制对JavaBean的属性进行处理。我们知道,一个JavaBean通常包含了大量的属性,很多情况下,对JavaBean的处理导致大量get/set代码堆积,增加了代码长度和阅读代码的难度。

二、用法:

BeanUtils是这个包里比较常用的一个工具类,这里只介绍它的copyProperties()方法。该方法定义如下:

public static void copyProperties(java.lang.Object dest,java.lang.Object orig)
  throws java.lang.IllegalAccessException,
         java.lang.reflect.InvocationTargetException


如果你有两个具有很多相同属性的JavaBean,一个很常见的情况就是Struts里的PO对象(持久对象)和对应的ActionForm,例如 Teacher和TeacherForm。我们一般会在Action里从ActionForm构造一个PO对象,传统的方式是使用类似下面的语句对属性逐个赋值:

//得到TeacherForm
TeacherForm teacherForm=(TeacherForm)form;
//构造Teacher对象
Teacher teacher=new Teacher();
//赋值
teacher.setName(teacherForm.getName());
teacher.setAge(teacherForm.getAge());
teacher.setGender(teacherForm.getGender());
teacher.setMajor(teacherForm.getMajor());
teacher.setDepartment(teacherForm.getDepartment());

//持久化Teacher对象到数据库
HibernateDAO=;
HibernateDAO.save(teacher);

而使用BeanUtils后,代码就大大改观了,如下所示:
//得到TeacherForm
TeacherForm teacherForm=(TeacherForm)form;
//构造Teacher对象
Teacher teacher=new Teacher();
//赋值
BeanUtils.copyProperties(teacher,teacherForm);
//持久化Teacher对象到数据库
HibernateDAO=;
HibernateDAO.save(teacher);


如果Teacher和TeacherForm间存在名称不相同的属性,则BeanUtils不对这些属性进行处理,需要程序员手动处理。例如 Teacher包含modifyDate(该属性记录最后修改日期,不需要用户在界面中输入)属性而TeacherForm无此属性,那么在上面代码的 copyProperties()后还要加上一句:

teacher.setModifyDate(new Date());


怎么样,很方便吧!除BeanUtils外还有一个名为PropertyUtils的工具类,它也提供copyProperties()方法,作用与BeanUtils的同名方法十分相似,主要的区别在于后者提供类型转换功能,即发现两个JavaBean的同名属性为不同类型时,在支持的数据类型范围内进行转换,而前者不支持这个功能,但是速度会更快一些。BeanUtils支持的转换类型如下:

    * java.lang.BigDecimal
    * java.lang.BigInteger
    * boolean and java.lang.Boolean
    * byte and java.lang.Byte
    * char and java.lang.Character
    * java.lang.Class
    * double and java.lang.Double
    * float and java.lang.Float
    * int and java.lang.Integer
    * long and java.lang.Long
    * short and java.lang.Short
    * java.lang.String
    * java.sql.Date
    * java.sql.Time
    * java.sql.Timestamp


这里要注意一点,java.util.Date是不被支持的,而它的子类java.sql.Date是被支持的。因此如果对象包含时间类型的属性,且希望被转换的时候,一定要使用java.sql.Date类型。否则在转换时会提示argument mistype异常。

三、优缺点:

Apache Jakarta Commons项目非常有用。我曾在许多不同的项目上或直接或间接地使用各种流行的commons组件。其中的一个强大的组件就是BeanUtils。我将说明如何使用BeanUtils将local实体bean转换为对应的value 对象:


BeanUtils.copyProperties(aValue, aLocal)


上面的代码从aLocal对象复制属性到aValue对象。它相当简单!它不管local(或对应的value)对象有多少个属性,只管进行复制。我们假设local对象有100个属性。上面的代码使我们可以无需键入至少100行的冗长、容易出错和反复的get和set方法调用。这太棒了!太强大了!太有用了!

现在,还有一个坏消息:使用BeanUtils的成本惊人地昂贵!我做了一个简单的测试,BeanUtils所花费的时间要超过取数据、将其复制到对应的 value对象(通过手动调用get和set方法),以及通过串行化将其返回到远程的客户机的时间总和。所以要小心使用这种威力!

通用日志接口

Common-logging

Common-logging的应用程序编程接口主要在org.apache.commons.logging.log接口中

定义,这个接口主要定义了两类操作:

一类是级别判断,用于减少不必要的日志操作的参数计算从而提高性能,函数名

和参数如下所示:

log.isDebugEnabled();

log.isTraceEnabled();

下面的代码可以很好地解释这点:

  if (log.isDebugEnabled()) {

        ... 一些高代价操作 ...

        log.debug(theResult);

    }

如果日志设施的级别定义高于debug,这些高代价操作可以避免运行。

另一类是日志登记,按照级别登记日志信息,函数名和参数如下所示:

log.debug(Object message);

log.debug(Object message, Throwable t);

log.trace(Object message);

log.trace(Object message, Throwable t);

日志登记操作分又为两小类:一个参数的日志信息登记操作和两个参数的日志信

息登记操作。前者对三类用户都适用,后者用于打印日志登记处的出错堆栈信息,

所以更适用于开发人员调式与维护使用

 
Aucun album photo n'a été ajouté.
La liste est vide.