UML软件工程组织 |
面向对象设计的新视角 |
gigix翻译(转载自ULMChina) 2002年09月16日 |
Alan Shalloway是Net Objectives的创建者和总裁,自1981年起,为工业界提供面向对象和软件开发的指导和培训,如Attachmate, Avaya, Boeing, IBM, Microsoft, Phillips Medical Systems, Price Waterhouse Coopers, QWest等,Alan的研究范围包括:design patterns, Java, C++, XML, XP和敏捷软件开发。他的书"Design Patterns Explained: A New Perspective on Object-Oriented Design"(中译本《设计模式精解》即将发行,由透明(gigix)翻译)被《设计模式》的作者John Vlissides称为最好的设计模式入门书籍。Alan曾在MIT获得计算机科学硕士学位。以下是交流实录。由gigix翻译。 模式矩阵 gigix:最近好象你快变成一个XPer了,是不是?最近你最喜欢的方法学是什么? shalloway:SCRUM也有很多精彩的思想。 gigix:那你还喜欢模式矩阵吗? shalloway:我正在重新写模式矩阵,我打算再把它扩展一些。 gigix:你现在怎么看待模式矩阵呢?使用模式矩阵来做预先设计,这样的方法好吗? shalloway:模式矩阵是学习模式的好工具,我想它的主要优点是能够用来进行模式之间的比较和对比。对模式矩阵的研究仍在进行之中。另外,我认为预先的设计和渐进的设计都是有必要的。当你对问题领域非常熟悉时,你可以在预先的设计中留下扩展的空间。但是,扩展的空间不能留得太多,我们不想实现不需要的东西。另一方面,我很赞赏XP中“简单”的原则。除非需要,否则不要实现任何东西。我的原则是: 1、测试优先(并保证测试的自动化); 2、切实遵循松耦合、高内聚、无冗余的原则,用代码表明自己的意图。 gigix:我觉得模式矩阵和敏捷方法是冲突的,是吗? shalloway:为什么你会这么想呢? gigix:因为它提倡使用模式预先做设计。 shalloway:让我来解释一下:也许XP的确说过“不要预先做任何设计”,但是其他敏捷方法通常不会这样。敏捷方法的基础是迭代式开发、每天至少构建一次、经常听取客户的反馈、重视人的价值、自动化测试和及时的重构。“不做预先设计”和“成对编程”是XP的实践,但不是所有敏捷方法的实践。我不相信只要使用模式就会造成过分设计。但是,也不要想当然地去使用模式。只有当你看到问题领域的状况和某个模式完全符合时,才能应用这个模式。我经常听见人们问:“我的Strategies在哪里?”这就是误用了模式:当你手上只有锤子时,你就想把所有的问题都当成钉子。模式实际上是事物之间的关联。比如说,Strategy模式就描述了“可能使用不同规则的事物”之间的关联。模式教给我们一种看待问题领域的新视角。 设计模式 xlp223:你认为新手应该从哪些模式开始学习呢? shalloway:入门的模式:Strategy、Abstract Factory、Composite、Bridge、Factory Method、Proxy、Decorator、Observer、Iterator、Adaptor、Facade和Template Method。就算你不用它们做设计,这些模式包含的概念也是开发者需要知道的。 gigix:您看了最近Joshua Kerievsky在SDMagazine上发表的文章吗?他认为模式很容易造成过分工程。 shalloway:只有当你用错了模式的时候,它们才会造成过分工程。可惜,大半的人都会用错。不过,正如我经常说的--模式是用来描述问题领域中事物的关联的。只要我们不想当然地虚构一些不存在的东西,模式就不会伤害我们。 crystal_y:大量的领域知识→倾向于提前设计→可能过分工程,到什么时候算完?要知道“什么时候该停”,我们需要什么呢?经验吗?更多的领域知识吗?更多的计算机科学知识吗? shalloway:在预先做设计的时候,只需要表现出问题领域的概念就可以了,不要操心特定的实现方法。敏捷方法会强迫你这样做,因为它要求你在一定的时间内实现一定数量的功能。 crystal_y:领域知识可以帮助我们更好地理解问题,而模式则可以帮助我们理解问题的抽象。敏捷方法则可以帮助我们更快地得到反馈,以改进我们的理解。对吗? shalloway:实际上,模式会从分析、设计和实现的角度来告诉我们问题。比如说,在分析阶段,我可能会发现我有几种不同的文档,需要支持不同的输出设备。所以,我看到系统中有文本、图片……它们使用激光打印机、绘图仪、点阵等等作为输出设备。这正是Bridge模式的场景。所以,我可以用一个抽象(不同的文档类型)来定义问题领域,然后给它以不同的实现(点阵、绘图仪等等)。现在我不必担心如何实现,因为我对Bridge模式很有把握。要求更快得到反馈则使你不得不对开发过程进行调整,因为你不能再等待完整的需求,也不能再希望做完整的系统设计,也不能先做完所有的编码工作再测试。 xlp223:关于模式的好处,您已经谈了很多。我想知道,您认为设计模式有什么缺陷? shalloway:我想设计模式最大的问题就是“设计”这个词,它让人们会觉得模式就是关于设计的。实际上,模式并不仅仅限于设计阶段,之所以它会叫“设计模式”,是因为Gamma他们研究的主要是可复用的设计方案。在分析阶段和实现阶段,都有相关的模式。 面向对象设计 zergo:您能告诉我设计对象时的一些原则吗? shalloway:对象是负有责任的事物。它们对自己负责。你通过接口来与它们交谈。你只管它们"做什么",而不用管它们"怎么做"。 yhufo:类的接口总是比较难设计,您能告诉我一些接口设计的技巧吗? shalloway:当你设计接口时,不要只想到手上的情况,还要想到现在的情况可能发生哪些变化,这是很重要的。但是,为了保持开发过程的敏捷,在你考虑其他情况时,不要对接口做不必要的扩展。不过,有时候通过展望未来的需求,你可以得到一个比较具有普遍意义的解决方案。 Charity_Zhou:您怎么看待软件设计中复用性和复杂性的关系? shalloway:在面向对象设计中有一种不好的倾向:从一开始就强迫可复用的代码。这本来不是一种好的想法,但我们却经常这样做。我们设计超类的时候很注意复用性,然后在需要变化的时候就在子类中覆盖超类的方法。问题是,这常常会导致不相关的概念之间产生耦合。比如说吧,假设你要创建一个销售定单系统,你用超类来表现相似的概念(税费、运费等等"费用"),然后在子类中来区分它们。结果,你就在税费和运费之间造成了耦合。一段时间里,这不成问题,但是它终究会出问题。它会使你的系统难以理解。在编程的时候,我们需要注意松耦合(以避免副作用)和高内聚(为了让代码清楚易读),还要避免冗余(出于效率的考量)。我们能够把握自己这边出现的复杂性--把它们藏在接口或者抽象类的后面。而对于问题领域出现的事物,我们就应该问问自己:它是做某一件事的特定方法吗?还是做某一类事情的普遍方法?《设计模式》这本书告诉了我们如何寻找可能发生变化的东西,如何封装变化点:找到普遍的概念,为普遍概念定义接口,让客户调用该接口;对于特定的方法,实现该普遍接口。 gigix:我认为面向对象设计的原则(例如开放-封闭原则)比具体的模式更重要,是吗? shalloway:我同意。模式只是一种具体的解决方案。不过,XP认为:根本不要管OCP(开放-封闭原则)。 gigix:啊?如果不遵循OCP,又怎么保证代码的质量呢? shalloway:你根本不可能写出永不修改的代码,而这正是OCP的目标。但是,请问问你自己,为什么要避免修改代码呢?当然,理由会有很多。比如说,好多代码都很脆弱--如果修改了一个地方,就会破坏另一个地方。但是,如果你一开始就想着降低代码的耦合程度,那么修改就不会造成副作用。你可能又会找出另一个理由:如果我修改了代码,就必须重新做测试。但是,如果你预先准备好了自动化测试,那么系统测试的代价也不会很高昂。软件开发者中流传着一个说法:我们用了大量的时间来修复错误。是吗?有多少人这样想?想想你最难的问题,最难的错误。现在,想想你用了多少时间来找到代码中的错误?如果代码结构良好,你能节约多少时间?如果代码中保持松耦合,又能节约多少时间?不管怎么说,大半的时间都不是耗在修复上面。错误的修复耗费的时间是比较少的,发现错误所需的时间要多得多。 gigix:同意。 shalloway:在80年代,我把一半的编码时间(也就是全部时间的10%)用在了我写的一个系统上。那时我的编码技巧还很不成熟,代码里有很多耦合,内聚程度也不好。这是一次很好的体验。 gigix:那么它肯定很难维护。 shalloway:对。如果没有强内聚、耦合又紧密、测试又少,那么系统的确很难维护。 gigix:我还有个问题。在OOD中,哪些原则是最重要的? shalloway:我无法说哪些原则是“最重要”的,但是我可以列举出一些重要的原则。你应该把对象看成定义良好的责任;对象应该对自己负责;封装是某种形式的隐藏:隐藏数据、实现或者是类;让事物之间的耦合明确化(松耦合);每个方法做一件事、也只做一件事;类只包含相关的方法;尽量避免冗余。 outmyth:我要怎么达到“低耦合”这个目标呢? shalloway:“低耦合”意味着要这样定义你的接口:让调用对象正好可以送出服务对象需要的所有信息。私有数据和私有方法可能会有帮助。 crystal_y:抽象、共同点/变化点分析,这些是得到松耦合的核心吗? shalloway:这些东西可以帮助你以一种更好的方式来看待问题领域。如果你这样编程,那么要处理的东西就少得多了。设计接口的时候只需要考虑如何表现变化事物之间的共同点就行了。 agilemind:粒度适当的、松耦合的设计模式真正的价值是什么,您能告诉我吗? shalloway:松耦合的事物可以发生变化而不引起副作用,也不至于造成很多代码修改。 敏捷方法和XP leohoo:敏捷方法和XP之间有什么区别,您能告诉我吗? shalloway:XP是一种敏捷过程。它有四种价值:勇气、简单、诚实和交流。它有12条实践。它是进行敏捷开发的一种方法。当然,也有其他的敏捷方法,SCRUM就很不错。就连RUP,你也可以按照敏捷的方法来使用它。敏捷是一种方法,它认为你不可能一开始就知道所有的需求,起码在大多数的项目中是这样。如果你能够提前知道所有的需求,那么你就不需要敏捷方法。 simaetin:"诚实"?还是"反馈"? shalloway:"诚实"是XP的一种价值,"反馈"则是你需要得到的东西。所有的敏捷方法都要求尽量听取用户的反馈,所以你应该少做早期准备工作。早期准备越少,你就能越快地给用户看一些原型产品,并得到反馈。当然,每个人都应该根据自己的需要而取舍XP的价值。就我个人而言,我不一定会从XP开始。我会从这些实践开始:预先准备自动化测试、每天构建、迭代。也许SCRUM会更容易实现。不过,如果你喜欢成对编程--那就去做吧。我觉得成对编程很不错,但是也有些人不喜欢它,这多半是因为美国人崇尚西部牛仔式的个人英雄主义。 flyingsaucer:有人说XP适用于有经验的开发者,而不适合新手,您怎么看呢? shalloway:我想,在XP的项目中的确需要一些高级开发者。但是,任何没有高级开发者的项目都肯定会遇到麻烦。如果没有很好的编码技巧,持续的重构也会让人觉得不舒服,但是,如果使用XP,起码你只需要让一半的开发者知道自己要做的事,而另一半的人可以先坐在一边学习。 其他技术 flyingsaucer:Shalloway先生,您对AOP(Aspect-Oriented-Programming)怎么看?它未来的发展会如何? shalloway:我没有研究过。不过,一些我很尊敬的人说它很不错。如果有时间,我会多学习一些的。 sinba72:您能给我推荐一本好的UML书吗?我是个UML的初学者。 shalloway:Martin Fowler的UML Distilled不错。 pplove.shao:您能告诉我一些OR映射的模式吗? shalloway:我没研究过OR映射,不过我可以告诉你到哪儿去找这些资料。Scott Ambler已经做了很多这方面的研究,但是还没有完成,你可以到www.ronin-intl.com去看看。另外,他也够有名了,在Yahoo!上就能搜索到他。 cajan2:您能告诉我如何在实时系统中应用模式吗? shalloway:对于实时系统,我没有多少经验。不过,关于这个主题,最好的书就是Schmidt的Pattern Oriented Software Architecture Volume 2。 banq:在EJB中有多少设计模式? shalloway:有一本关于EJB模式的好书:EJB Design Patterns。可惜据我所知,这本书只有英文版本。EJB之所以很有用,是因为通过EJB我们可以把特定的功能放进一个对象里面,然后再也不必担心对象的生存周期、存储之类的事情。即使不使用EJB,这些设计思想也是很重要的。 告别 shalloway:有件事我得声明一下:我参加今天的交流,不光是为了宣传我们的书,还因为我有可能到中国来做培训。我希望有人能帮助我安排到中国的行程。如果你能够帮忙,请和我联系:alshall@netobjectives.com。 gigix:欢迎来中国。 shalloway:夜已经很深了。很高兴今天和大家交流,我希望过几个月能再有这样的活动。再见,各位。感谢UMLChina主办今天的交流。感谢所有人的参与。 cajan2:Shalloway先生,很高兴今天能和您交流。再见。 注: 模式矩阵(Pattern Matrix)是Alan Shalloway在Design Patterns Explained中提出的一种分析、设计方法。 XP中的价值的确是"反馈(feedback)"而非"诚实(honesty)",Shalloway先生可能记忆有误。 用成对编程的方法,初级开发者可以向同组的高级开发者学习,并尽量作出自己的贡献。
|
版权所有:UML软件工程组织 |