cast 的个人资料nonocast ! 真诚原是一种需要坚强不屈的...照片日志列表更多 ![]() | 帮助 |
|
|
6月10日 推卸责任也是一种责任过去常常不理解Assert的用法,总是觉得有些鸡肋
用Assert的地方都是可以用Exception来替代,
but .NET依然保留,而Java 5中竟然加入了Assert
其实个人认为Assert的用意在于推诿责任,将异常处理交由最恰当的对象去处理
同时更为重要的是明确了处理这个异常不是我的责任
只有在职责明晰的情况下,才能做出正确的推卸,say no是有前提的
4月23日 单元测试的重要性UnitTest不仅是对代码正确性的检验,更是在考验你的设计
每一个类处于不同的层次.平面上,拥有不同的职责
能相对独立的解决某一问题
是某个实体或行为或算法或业务或X的抽象
当然他有存在的上下文,要食人间烟火的,没有依赖关系就没有存在的必要
所以如何能让一个类在相对封闭的环境中进行**单元**测试是一个很大的课题
很多时候不是你不想做单元测试,而是你的设计导致你根本无法下手做单元测试
心有余而力不从
你不妨随意瞄一眼你现在IDE中正在Edit的类,他能进行单元测试吗?
一个好的对象设计应该很容易为他的每个单元进行测试
其实这一点可以上升到对一个设计的评价尺度上
所以在设计的同时多考虑一下单元测试是一个设计师的职责
对异常以及错误上的探索也同样属于设计师的职责
这个在编写有效用例中已经大下笔墨的问题也无需再提及
实践证明,对一个类是否能测试以及对错误的管理不是编码中可以轻易重构的
重构不要成为设计推卸责任的借口
其实在细节的把握往往成为决定胜负手的一个关键
随着长期的实践,我们才会渐渐有信心写出让人让自己放心的软件
11月23日 Behavior First!过去以为类是整个面向对象模型的核心,很自然的让人联想到类的结构,把大量的功夫都耗费在建立一个完整的类模型,面对问题上来就是拆解结构,
电脑,电脑由显示器,机箱组成,机箱又有主板,芯片,电源,插槽,内存,硬盘....组成。 然后提出'设备'这样一个抽象类,全部从此派生,多么美妙的对象模型啊! Oops,如果你正在写一个程序,希望它能让他做点什么的话...其实你知道,本质是行为,而不是结构,没有行为,即使你对整个宇宙建立模型,也不能解决任何问题。 我想说的也正是这个,软件的本质是行为,它能做什么,而一切一切的结构都是在为行为服务。
So, Behavior First! 好的结构只是一个好的行为必然的伴随物罢了,不要把设计一个好的静态模型作为最大的靶子,那你就失去了系统本身最重要的意义。
11月21日 Interface Vs Abstract Class个人认为两者是完全不同的两个概念
inferface专注于概念层的抽象
而abstract class专注于解决实现层的抽象
比较来说,就是他们抽象的层面不同
这也同时体现在建模过程中
过程应该是,
interface + class > concrete class > abstract class
从具体类到抽象类的过程类似于提取公因式,说白了就是为了少些代码罢了,当然还有其他作用,比如多态
而interface才是整个领域的起点,目的是抽象概念,来表示系统中概念的消息以及协议
interface应该依赖于interface
当然概念并不是只有interface来表现的,对于那种相对稳定的概念应该直接使用class
过多的interface同样不是一个好的设计
设计时需要对系统的变化进行管理,什么是最易变的,什么是最有可能被扩展的,当然也要把那种maybe,perhaps尽早扼杀掉
否则成本....
总结一下,interface是抽象的,abstarct class是具体的,这里的抽象和具体是相对于两者的,呵呵
BTW:抽象类之所以叫抽象类就是表明了在类层次中的抽象,而interface则是在领域中进行抽象
把层次分清楚就容易辨识这两个看似功能很像的概念
8月27日 概念惯性需求如下(非常简单), 为一个学校提供课程计划任务的打印功能,打印出来的数据就是 XX系XX专业XX年级 于 XX学期(大学4年8个学期) 开设 XX课
那么首先就要对系,专业,年级,课建立相应的对象,如图,
这样很容易理解, 年级: 外语系英语专业02级 课程: 计算机系软件专业汇编原理 然后课程任务就是, 外语系英语专业02级02级于第一学年第一学期开设外语系英语专业英语口语1课程
到这里都ok,现在的问题是如何处理公共课这样一个概念(其实大家对这个应该都是有实际概念的), 大学英语是一门全校性公共课,虽归属于外语系门下,但并不属于其中的任何专业,这样一来就打破了一致性。 那怎么把这个概念融合到上面的设计中去呢? 不知道你是怎么考虑的,呵呵,不妨在纸上涂上两笔,看看有没有什么思路。
在我起初的考虑中,并没有太重视这个问题,只是通过在系下面加入一个特殊的专业--公共专业来考虑,这样一来保持了上面那个结构, 在实际操作中,这个设计上的小问题通过VO层,表现层逐步被放大,要知道这本身就是一个很mini的项目。 其实前面还存在一条非常明显的路,就是在专业上面加一个bool值以区分这个是否是公共专业,我个人认为是不可取的,为什么呢? 因为在领域这个层面上,不应该过早带入语法层面的判断,这样破坏整体感,实际操作上也很难区分是领域判断还是技术细节判断。 还有另一种观点,那就是把这个bool值加在课程上面,用以区别公共课还是专业课,除了上面说的过早带入了语法判断以外,还有一个问题就是 把不属于课程本身的东西带到课程中去。
你有很多衣服,你对每一件衣服都有不同的喜欢程度,从0-100,你是否认为这个值应该放在衣服对象上?
所以最后我得去的设计如下图,
从另一个角度来说,设计本身不存在一个唯一的正确答案,在不同的情形下有属于他们自己最适合的设计。 从前后两个设计来说,区别点也就在于多了一个类,但这一步是很难迈出去的,从一个角度来说,对于类直接的关系,领域内的问题就应该通过 他们的形式规则来解决,不需要语法层面的介入,其二,设计也是不断迭代的过程,你的设计能够抗的起领域对象的变化吗?
BTW:最后再对一些细节问题做一些补充, 你知道的,人的容错性是非常大的,当我们说软件专业我们可能理解的方式是非常多的,但要让程序的容错性增大无疑需要大大增大程序本身的 复杂度,结构上的复杂和一些冗余的目的就在于排除二义性,因为他毕竟不是人,我也没有能力给他加入人的智慧,说到底,我比较懒。 7月30日 变化中出对象过去一直以为抽象是面向对象中举重轻重的词语,后来才慢慢发现还存在一个更为重要的词语
变化
其实在explain DP中就反复强调这个词语,但我一直没吃透,我一直很难理解什么样的设计才能应对变化,一个抽象度相对高阶的设计可以应对更多的变化,容纳更复杂的结构。
但后来我也发现要在设计完后应对变化就如同让程序在能自动解决Exception一样,或者说更为复杂,其实我们更多需要应对的变化是在编码前以及编码时,是根据需求作出恰当灵活性,将变化列入设计内,而后根据恰当的灵活和变化才可以作出恰当的抽象用以搭建对象体系,否则的话抽象的标准是什么呢? 7月28日 Decorate or StrategyDecorate Style BlockDataSource = new BlockDateOrderFilter( new BlockDataSource( new SpecifyDateRangeEntryVODataSourceFilter( new SpecifyUserEntryVODataSourceFilter( new EntryVODataSource(SpringContext.getManagerFactory().getEntryManager()), SpecifyUser ), new Today() ) ), true );
Strategy Style
BlockDataSource = new BlockDataSource( new EntryVODataSource( SpringContext.getManagerFactory().getEntryManager() new SpecifyUser(SpecifyUser), new Today(), ), true );
从直觉上来说,上面显得更松,更易于测试。 问题在于对于FindAll这种Filter来说,N个Filter,复杂度就是N倍,我想这是一定不可以的 理性告诉我应该使用Strategy,但GOF上所举的Stream Decorate例子抑或JavaI/O一再用Decorate来对Stream Wrapper,复杂度同样也是N倍!
最后根据以下原则再次作出一个平衡
用一个Decorate你可以改变对象的外表,而Strategy使得你可以改变对象的内核。
如果以外表和内核来区分 Decorate or Strategy,抓住两者的动机,我想应该是下面这样的结果,
BlockDataSource = new BlockDateOrderFilter( new BlockDataSource( new EntryVODataSource( SpringContext.getManagerFactory().getEntryManager() new SpecifyUser(SpecifyUser), new Today(),
) ), true );
这里的排序功能以Decorate出现,而其他的作为Strategy,没有增加任何复杂度, 换句话说在不增加复杂度的情况下更倾向于Decorate。 再次体会模式本无所谓模式,是一个代码演化的过程,思想演化的自然过程,领会对象意图,抓住基本概念,结合具体问题作出恰当的选择折中和平衡,这可能就是最大的挑战!Fighting..YO 对象层面上的异常<< object design
结构工程师和历史学家Henry Petroski在谈到了解失败后果的必要性时说,"在核电站的设计过程中,结构上的失败其后果是致命的,因此核电站的设计过程包括了相当数目的冗余结构设置,也保留了相当大的安全余地。而在另一种极端情况下,某些脆弱的结构,如鞋带,灯泡等等,他们结构上的失败并不会带来多大的影响,因为他们都是便宜的物品,为了平衡成本,采用脆弱的结构是合理的。然而在这两种极端情况之间,大多数结构设计选择都不是显而易见的。没有设计者希望设计的结构是容易崩溃的,但是他们却又部位安全性考虑而做特别的结构设计。设计者、客户以及用户不可避免的要面临诸如,"到底多少冗余设置才是安全的?","所允许的最大开销是多少"等令人不快的问题。作为软件设计者,必须让设计的软件机制能够达到预期的效果。
信任域 异常和错误
对象异常和用例异常
你要知道,任何一个很正常的异常如果没有得到适当的处理,会导致整个系统的失败,就如不可处理的错误一般。这样的事情决不应该发生! 抛出异常就是一个寻求写作的过程,(如果你都能处理又何必抛出异常?!),其中包括抛出异常的对象,发送了引起异常请求的客户以及协作链上的一个或多个对象。 担任异常处理责任的对象要采取有效的处理就必须有足够的信息支持。 异常对象是一种信息持有者。 一些指导方针,
7月3日 DAO (3 entries)Core J2EE Patterns - Data Access Object
Advanced DAO programminghttp://www-128.ibm.com/developerworks/library/j-dao/
DAO @ sourceforge ? :) http://daoexamples.sourceforge.net/
enjoy ! 讨论interface在java编程中的作用 [Part.2]庄 said, 这篇文章非常重要,列位看官,打起精神了!
ajoo 反驳到, 引用: interface最大的作用,是提供对于一个类的多种可能的视角
我不认同这个说法。
这话没错是没错(当然,还得看你怎么定义"使用"这个词.没有实现类,我也可以写我的接口的使用类)
我理解的老庄的意思, 讨论interface在java编程中的作用 [Part.1]>> http://forum.javaeye.com/viewtopic.php?t=7776
...
ajoo said: 老庄: 我觉得可能是我的表达太过二义性了。造成你的理解和我说的意思不大对的上茬。 你看我最后回复的那篇了吗?你的思路始终还是在“实现者定义接口”这个基础上。 而我前面反驳你的论点,都是基于“使用者定义接口”这个前提。
一.所谓“接口是你自己定义的。反映你自己的需求。什么叫没有完成?”这句话说得不清楚,也难怪你不明白。 举个例子,我要实现一个功能A, 在实 现过程中,我发现我需要调用一个功能跟我自己正交的模块B。 此时,我第一步要作的就是,总结我对模块B的需求, 对吗? 怎么总结? 通过接口。我自己定义出模块B要给我提供的接口IB以及相关的语义。 然后,把IB ioc进来,直接就用了。 这个IB是否一定对应"class B implements IB"? 我不知道,我也不关心。
这里,我实现我自己的A的时候,可能已经有了接口IA,也可能没有。但是,无论如何我定义了接口IB。
二.关于单元测试,单独测试A,单独测试B, 联合测试A+B。都是少不了的。 不过,如果之间不是用接口耦合,你就只能联合测试了。我个人是认为单元测试是不可省略的。 我不希望A的作者有借口说我不能测试,因为B还没测完呢。
你的思路更象是造房子,地基打好之前别的都得等着,房子没造出来,屋内装修也是痴人说梦。 我的思路则象是计算机内部得各种插件。给每个插件定义好如何和别人联系的接口插槽,然后大家自己干自己的,互相之间不需要有其它依赖了。
三.你的例子还是围绕在实现功能A, 是否要先定义接口IA上。我对这个问题的回答是:不一定。看程序员自己了。
但是,我说得免费的情况是指“需求者定义接口”这种用法。也就是,实现功能A,发现需要功能B, 那么不要费神去找实现了B的类,直接就定义接口IB给自己用。工作量是不是最小?
忽然想起一个问题。不知道大家在写业务层,持久层,物理层的时候,是否让业务层直接依赖持久层的类,持久层直接依赖物理层的类? 这就是一种建造金字塔一样的方法。要测试业务层?必须等物理层写完了,并且测试好了,然后持久层写完了,测试好了,才能开始。
要是想从jdbc based向xml based的物理层迁移,整个金字塔就得重建。
相反,如果业务层依赖的仅仅是抽象的持久层的接口,持久层依赖的是物理层的接口。那么,迁移物理层,其它层并不需要动。
用“点菜”式的使用者定义接口的方式,业务层的接口是用户下的菜单。 持久层的接口是业务层实现者下的菜单。物理层的接口是由持久层实现者下的单。
实际上,如果面向接口,这个分层都不是绝对的。
对业务层的客户,我看见的是业务层的接口,你如果kiss,可以不搞那么多层,直接用jdbc实现业务层,并不影响我。
对持久层的客户(主要也就是业务层了),也是一样,我看见的就是接口,你的实现是通过调用间接的物理层还是直接用jaxp api写xml与我无干。要kiss就kiss好了。
这才体现出面向接口的好处。它给kiss提供了最大的可能。
嘿嘿,top down, bottom-up。 我前几天还在感慨fpl里面隐含着的bottom-up的思维方式和oo里面鼓励的top-down的区别,马上在oo里面看到这两个家伙又打起来了。
要我说,interface的一个好处是,它让你不用严格top-down,也不用彻底bottom-up。 用interface,你可以在问题的随便挑一个感兴趣的层次开始考虑。比如,我这人不懂业务逻辑,从top-down开始搞业务层比较麻烦。 我也不会jdbc,从物理层开始bottom-up也不可行。
没关系,用接口,我把两边都抽象起来,把问题拦腰一切,从中间开始着手做持久层。
你说这是top-down还是bottom-up呢?
这其实更符合人的思维方式的。 比如说,公司里,多数人都不会象总经理那样需要高瞻远瞩,运筹帷幄,但是也不是所有人都了解最基层的每个公司运营的细节。 但是,不妨碍每个人在自己的职责范围内给公司做出贡献。
公司可以换总经理,可以换底层的程序员,换了谁,公司都照样运行。为什么?就是因为这些上层啦,下层啦,都是按照一定的协议互相合作,并不是固定地依赖某个人。其实,所谓上层下层,主要是一种谁服从谁的行政关系(在oo里就是谁调用谁以及各个调用的语义),结构上只是各有分工,并不一定是严格的层次结构。
孔子说得好:只有分工不同,没有高低贵贱。
夫子真是大师啊。几万年前就把oo理论深入浅出地谆谆教导给了子孙。可惜我们这些不肖后代居然把淀积深厚的文化精华弃如敝履,反而去追捧浅薄的洋鬼子们的几孔之见。真是羞见夫子于地下呀。 7月1日 站在对象的角度上看测试,日志,持久化和错误机制我们说要做一个好的OO设计需要Thinking in OO
but 即使全副OO思想,问题在于你没有很好的Coding功底
一切还是浮云
对象给人一个很曼妙的幻想,使人孜孜不倦
我们关注了对象的职责,对象的设计,从对具体到抽象,最好去除所有的coupling
有时候会被单元测试,Spring,Hibernate带
都不知道自己在哪着走
难倒不觉得有点smell吗?
停下来,回到原点上,我们的目的是写出更优秀的代码
而不在乎是否使用了Spring,Hibernate,又或是TDD
问题在于我们观察的角度
如果OO可以让你很轻松的构建出一个Domain,但你的Domain又是否真的准备好了呢?
是否为每个对象准备了测试,书写了日志,以及设计了错误机制呢?
这些活是逃避不了的,勇士,站直了去面对,去战斗吧! 6月29日 迟到的测试namespace UnitTests { public interface IPerson { string Name { get;} }
public class Hello { IPerson person;
public Hello(IPerson person) { this.person = person; }
public String Greet() { return "Hello " + person.Name; } }
[TestFixture] public class GreetTest { private Mockery mocks; private IPerson mockPerson; private Hello hello;
[SetUp] public void setUp() { mocks = new Mockery(); mockPerson = mocks.NewMock<IPerson>(); hello = new Hello(mockPerson); }
[Test] public void test() { Expect.Once.On(mockPerson).GetProperty("Name").Will(Return.Value("nonocast")); Assert.AreEqual("Hello nonocast", hello.Greet());
mocks.VerifyAllExpectationsHaveBeenMet(); } } }
3月28日 reuse我们现在可以有很多组件拿来复用,有很多类拿来复用,希望拖拖控件就搞定一切
在oo的世界里,最大的复用度级别是思想的复用
模式在一定程度上也欺骗了很多人,认为有模式就ok,其实真正的人懂思想,其次才是懂模式
所以我要推荐分析模型,这就是思想上的复用的结晶,当然他也只是冰上露一小角。虽然有些晦涩,但不失为思想集。
还有就是uncle bob的几本书,就不介绍了吧 2月27日 MethodMissiing对于ruby的MethodMissing 这一下子就打破原有在C++/Java之上对对象的概念, 大凡OO理论都会腔调Message和Method之间的不同 但落实到具体,尤其是在强类型语言中message最终还是以method出现 太可怕了 要知道message和method概念上是有本质上区别的 就像一个人一样,是一个对象你在他1岁的时候给他一个脱衣服的概念,他懂个P啊,但随着长大就会了,但大到一定年纪以后上了岁数,自己知道怎么做却已经做不了了,这是同一个对象在不同时期对同一消息作出的不同反应。 其二我对一块石头大声说你TMD给我脱衣服,可能我出于某种情绪的发泄,别想歪,但绝对不应该限制我给石头发消息的权利,当然石头是完全不会睬我的。 我个人觉得很多人对 对象,面向对象的概念还是很不了解的。 以为 XXX.yyy() 这种形式就是OO了。 对于ruby中的消息在没有参数的时候是可以省略括号的,当然也完全可以在有参数的时候省略括号 puts "nonocast" 但这个时候就会有一个误区,不是ruby的错哦 比如说你看到 MyClass.options 如果仅凭这句你觉得options是一个消息呢?还是一个属性呢? 嘿嘿 这其实是一个挺重要的概念。 为什么只能def MethodMissing 而却没有def AttrMssing呢? 以对象的观点来说,对象应该只能接收Message,就像你自己知道23岁,别人要用的时候都是要问你小Y你几岁,你回答23这样子一个过程吧 他有什么权利直接用你的属性不是吗? 2月16日 面向对象模型之所以难在于动态平衡对象模型本身的难点不在得到对象
而是抽象程度的拿捏把握
是否要抽象,抽象到什么程度?
这个很难有一个标准,都是视情况而定的。
这是一个典型的balance。
第一步就要认识到这是一个balance,呵呵 1月20日 下一眼我们总说一俊遮百丑
但工程就是工程,不是一个方法就能解决所有问题
就像OO本身不能对软件的robust有所帮助
所以下一步将在robust上下一番功夫
最近在看robust java,think in java.etc
一直想看code complete,但还没机会
总是感觉这块是一个软肋,把握的不好
如何能有一套机制来控制OO,辅助OO这是现在的当务之急
很多内容都是在将如何使用exception,但真正说如何用的,介绍经验的缺又很少
hibernate从2.1到3.0很大的一个变化就体现在exception从checked到unchecked
看来这个问题不是那么容易解决的,或者说又是一次博弈
不管怎么说,这是一个很重要的事情. |
|
|