2006年01月26日

 


http://www.tvmao.com/
感觉很不错的服务,可以通过mail定制电视节目单,也可以通过MSN机器人(MSN@TVmao.com)在线询问,可以很方便的查询电视节目。
可惜我家现在还没有电视,


 

本篇文章使用aigaogao Blog软件发布, “我的Blog要备份”

2006年01月25日

昨天还在加班,后天就回家过年了。


2005年3月1号开始在公司实习,算算到现在就快11个月了,总结一下在这将近一年的时间里的收获。



  1. 2005年3月30日 得到签约通知  很兴奋 也很激动,这是我的第一份工作。
  2. 2005年4月12日 完成了第一个练习项目 这是我工作的起点。
  3. 2005年4月15日 接手制作公司的网站 。
  4. 2005年5月24日 网站的方案被否。之后重新设计成了现在的样子公司的网站
  5. 2005年05月27日 答辩结束,学校的生活结束了。
  6. 2005年06月15日 在公司的日语培训暂停,从此便没有再参加培训。
  7. 2005年7月10日 与COSMIC(大连)科技有限公司正式签约3年。
  8. 下半年工作很忙,完善社内系统,网站维护,blog也无暇打理。
  9. 2005年8月 参与京王旅游系统(.Net)的测试,从此 上半夜能回家就算早了,有几次还在公司通宵了。
  10. 2005年10月 加入品质部,由一个叫菱田的日本人领导,期间用3天时间制作了个品质部资料管理系统(java),第一次受到批评,反省后决心改变自己。
  11. 2005年10月底 在品质部,被安排制作新的日报系统(java),期间定为20天,按期纳品后再次受到批评,情绪受到强烈打击,事后反省决心要控制自己。
  12. 2005年12月 品质部解散,被安排到java组作医疗系统,至此才正式参与了大型项目的开发。
  13. 2005年12月被安排修正原系统(诊所系统)检查结果表示部分(BizDesigner+java)。
  14. 2006年1月14日 原系统的修正工作结束
  15. 2006年1月16日 日方客户来公司做了一周的业务讲解。
  16. 2006年1月25日 今天,做了流水账式的总结。

这大半年来我的一点感受是



  1. 在学校中的学习是被动,是可以计划的,失败是可以没有后果的,做错了是可以重来的。
  2. 工作中的学习是主动的,是关乎生死存亡的,是关乎未来机遇的。
  3. 工作中的一切都是由代价的。
  4. 工作中的错误与失败容易留下阴影,要克服自己的恐惧,给自己信心。
  5. 工作中要看重别人胜过自己。
  6. 明确目标和方向,在工作中迷路要及时反省。
  7. 不断反省自己,给自己信心。
  8. 提前准备,不打无准备之仗。

本篇文章使用aigaogao Blog软件发布, “我的Blog要备份”

2006年01月21日


转自:http://www.jdon.com/jive/thread.jsp?forum=91&thread=24681


 


前段时间读了《软件的最大追求是什么》,击节叫好,深以为然,虽然该文章很多地方显得有点极端。

如今的软件系统越来越复杂,如果软件的结构不好会影响软件的可维护性,重构代码是一件极其痛苦的事情。

关于软件的复杂性问题,我做了一些思考:

1) Cyclomatic Complexity (圈复杂性 = number of decision points +1    其中number of decision points是指一个if else之类的条件判断语句 (引自《软件的最大追求是什么》)

if else 语句可以被行为模式/策略模式代替,不妨看下列的例子:

假设我们要根据条件判断来完成不同的行为,用if else 是这样写的:

main() {

if(case A){

//do with strategy A

}else(case B){

//do with strategy B

}else(case C){

//do with strategy C

}

}



用策略模式则如下:

class runner{

do();

}



class A extends runner{

do(){

//do with strategy A

}

}



class B extends runner{

do(){

//do with strategy B

}

}



class C extends runner {

do(){

//do with strategy C

}

}



main(){

runner.do();

}



用了策略模式后main()中的语句的确简单多了,再也看不到该死的if else了^_^酷~~~



可实际上是这样简单吗???仔细研究一下上面的代码就能看出问题出来,首先这两段代码中的A、B、C的实际意义是不一样的:第一段代码中ABC代表的是某一个逻辑条件的值而第二段中的ABC则是具体的类;第二段得到如此简化的前提是它得到的逻辑条件就是一个类;如果得到的仍然只是一个逻辑条件,那么为了达到代码简化的效果,必须由另一个类(或方法)完成这种逻辑条件到具体类的转换,会出现类似下列的代码

class RunnerFactory{

runner getInstante(case){

if (case A) return new A();

else if (case B) return new B();

else if (case C) return new C(); } }



从测试的角度来说,两者的测试分支都是3,复杂度相同,而第二种方法在很多的时候貌似还要测试借口的有效性。用策略模式还有一个缺点就是会使系统中的类的数量大大的增加,如上的例子,采用if else类的数量为1,而采用策略模式的类个数为5个或6个(主要取决于逻辑映射是否用单独的类)。

如果逻辑判断的条件有三个,每个逻辑条件有三种可能的话,用策略模式系统至少会增加10个新类;如果条件更多的话类的个数也会更多 这么看来GOF的策略模式还要它干嘛??

当然不是,策略模式在很多情况下是一种非常好的解决方案。

这还要从if else 语句造成程序复杂以至难以维护的真正原因说起。就我个人的感觉真正造成if else语句难以维护的原因是每一个逻辑分支中的处理语句过长。比如我现在工作中维护的代码,常常一个条件下面的业务处理语句有两三千行,每次我光确定某个逻辑分支的结束位置就要找半天,头晕-_-!。如果是多层条件的话情况就更糟了。一个分支就一千多行,几个分支上万行自然很难维护。 if else 语句本质上是程序的流程控制语句,而分支中N长的代码通常是业务处理语句。

行为模式/策略模式就是把流程判断和业务处理进行了一次解耦,将业务逻辑封装成一个个单独的类。换句话说,行为模式/策略模式并不是不需要if else 语句(事实上该判断的还是要判断),只不过的换了地方或者是别的代码帮你做了。另一方面,进行逻辑判断的语句被集中起来而不是分散在程序的各个角落,有利于逻辑本身的维护。策略模式/行为模式还有一个明显的好处就是如果新增加了一种状态,我们只需要新增加一个策略类(同上的ABC)就可以了,避免了在程序中改动那些大段大段让人厌烦的if else 语句。

所以对于你的程序来说到底是使用设计模式还是简单的使用if else 关键在于你的程序是否复杂,有没有必要将控制逻辑和业务逻辑进行解耦。当然如果你可以用别的方式实现解耦也是非常好的。



2) Response for Class(RFC) 当一个类和很多其他类存在依赖时,它就变得复杂甚至难以修改和维护,这样,RFC值越大,表示你的系统味道越坏。(引自《软件的最大追求是什么》)



复杂性是由类与类之间的依赖关系(dependency)造成的。

具体如下所示:

interface Runner;

class A implement runner{ do(){}; }



一个大型的系统中很多地方用到了runner接口,于是在很多地方出现了如下的相同代码:

{

Runner r = new A();

r.do();

}



如果因为某种原因runner接口的实现类改为B,则在所有用到runner接口的地方代码都要统统改为:

{

//Runner r = new A();

Runner r = new B(); r.do();

}



这些遍布系统各个角落的改动是繁琐且容易出错的。

于是出现了各种框架和模式,其中最著名的当然是IOC(Inversion of Control)反转控制或者称之为依赖型注射(Dependency Injection) 那些讨厌的代码变成了如下:

{

ApplicationContext ctx = new FileSystemXmlApplicationContext(“spring.xml”);

Runner r = (Runner)ctx.getBean(“Runner”);

r.do();

}



这样我们就不需要对各个角落的代码进行维护了,容器会自动的为我们选择合适的类。

我到觉得维护的工作还是我们的,为了让容器注射入合适的类,我们必须要维护一个叫spring.xml的配置文件,或者如果你不喜欢配置文件这个东东的话(比如偶)就得自己写一个注册类,将依赖关系一一注册进去。你还要为使用该接口的类定义一个以该接口为参数的构造函数或者该接口的setter方法,好让容器可以将实现类顺利的注射进来。

该做的还是要做,只不过换了一个地方做而已。但就是换了个地方,实现了对依赖关系的集中维护(又是集中),大大的改善了系统的结构,明确了不同职责单位之间的分工。呵呵,有时自己也极端的觉得设计的工作说到底就是解决代码结构的问题^_^



IOC一直是和轻量级框架联系在一起的。所谓的重量级框架EJB也有实现相同功能的解决方案:Service Locator Service Locator就是一个定位器,它维护了一个数据结构(比如一个表),通过这个定位器你可以准确的定位到你的接口想要的实现类,Service Locator同样使你免去了改变接口实现类后的维护恶梦:

{

Runner r = (Runner)ServiceLocator.lookup(“Runner”);

r.do();

}



无论是IOC还是Service Locator都帮助你维护了类之间的依赖关系。那么是否我们在编程中一定要用呢,这又是个权衡的问题,IOC带来了很多的好处,不过我个人认为它的代码是让人费解的(你根本不知道它做了什么),并且为了用它,一方面你要借助于容器,另一方面你要编写配置文件,要为依赖型注射提供合适的途径。

如果你的系统类之间的依赖型错综复杂,需求的变化常常导致实现类的变化,同时你又希望采用测试驱动的快速开发模式,IOC毫无疑问是一个完美的解决方案;如果你的系统不存在上述的问题,为什么不简简单单的在程序中写死呢,何苦去维护一堆配置文件(我所在的开发部门貌似都比较痛恨配置文件这个东东)。Service Locator也有很多缺点,被骂的最多的就是没法快速测试。

反转控制,即转换控制权。依赖关系控制权的转换是对代码结构的一次重构,重构的目标还是解耦,让不同的职责代码集中放到不同的地方,于是程序员可以更加专注的解决特定的问题,比如业务逻辑。

程序设计的发展就是对代码结构的不断调整,不断解耦,让特定的代码解决特定的问题而不是什么都混在一起。从面向过程到面向对象难道不是这样吗,封装的本质也是解耦。



在实际问题的解决当中,最重要的信条就是合适,要记住任何结构的改进都会付出代价,你的改进是否值得你为此付出的代价。比如当你做一个嵌入式程序的时候你首要考虑的自然是效率问题;而如果你做的是一个ERP产品,在系统设计的时候,光系统的可维护性问题就让你不得不绞尽脑汁考虑一下代码的结构。



一句话,只做最对的。

程序设计的最大追求就是在合适的地方做正确的事。

本篇文章使用aigaogao Blog软件发布, “我的Blog要备份”