空间站

北极心空

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  15 Posts :: 393 Stories :: 160 Comments :: 0 Trackbacks
 

你是一个优秀软件开发人员吗?你知道GRASP 

一.职责分配和职责驱动设计

在一个软件项目开始的时候,我们通常需要进行需求分析,了解客户需要设计一个什么样的软件,这个软件中应当有什么功能。需求分析了解到的是现实世界中客户需求的业务功能,每个业务功能往往是一个业务流程,即客户在日常工作中不断在完成的业务流程。同时,在用户的问题世界中,必然有一些东西或者说事物,它们之间存在着相互的关联。

拿一个软件评审管理系统作为一个例子吧。评审管理系统的业务需求如下:

1通过以上需求的描述,我们不难发现整个问题世界中的相关事物:评审组织者、评审计划、评审者、评审对象、评审表、疑问、评审报告、评审结论、问题。我们也不难分析出这些事物相互关系,比如评审计划与评审者是一对多,而评审报告与评审结论是一对一。

RUP领域模型中的对象将成为软件开发中形成具体对象的基础(软件开发中形成什么对象是根据软件开发的具体需求而定的,并不一定要与领域模型的对象一致)。用例模型中的用例,将通过赋予这些对象行为而得以实现。现在的问题就出来了,用例模型中的功能,或者说一系列行为,应当如何分配给这些对象呢。也就是说,为了完成同一个任务,我可以将行为A我们通过对现实世界的分析,或者说对于领域模型的分析,设计出了软件系统中的对象,这时候我们应当为每一个对象分配职责。什么是对象的职责呢,当然是通过对现实世界的分析,定义的这个对象应当完成的任务。比如评审者对象的职责是存取与评审者相关的数据。当然对象的职责不一定是一个,比如评审计划包含了评审对象和评审者的子项,所以它在工作不繁忙的情况下可以代理处理评审对象和评审者的信息存取。但是一个对象的职责不应当过多(也就2职责分配现在已经被普遍认为是一个优秀的软件设计应当遵循的原则,它有以下好处:

1这种通过考虑对象、职责、协作的对象设计及构件方式,被称为“职责驱动设计(RDD

二.GRASP模式挨个析

GRASP(原创)一个优秀软件开发人员的必修课:GRASP(2)低耦合

(原创)一个优秀软件开发人员的必修课:GRASP(3)高内聚

一个对象撕心裂肺的怒吼:谁来创建我!GRASP(4)创建者模式

(待续)



以下是原博客的讨论:[建议到员博客阅读]
最后更新:2007-02-04 15:24
14:11  |   永久链接  |   浏览 (5801)  |   评论 (13)  |    收藏  |   进入论坛  |  
评论    共 13 条 发表评论
amigobot     2007-01-20 13:08

没有下文了? 期待中。GRASP和GoF是不同类型的模式, 出发点不同。 GRASP是解决类之间如何交互, 如何设计合理, 和具体问题无关。

galaxystar     2007-01-20 13:50

感觉是一种综合体!

zuly     2007-01-20 14:08

知道名字就可以!其他的可以google!

what we need is the name , add others to google!

fangang     2007-01-22 08:46

zuly 写道
知道名字就可以!其他的可以google!

 

what we need is the name , add others to google!

我写这篇文章的起因是因为我偶然在google或yahoo这样的搜索引擎搜索GRASP发现,除了国外的网站,国内网站多介绍和讨论GoF而很少介绍GRASP,即使这少量的文章也讲解非常粗略。个人认为作为优秀的开发人员,理解GRASP比GoF更重要,故写此文章。此文章后面的内容我会不断添上,谢谢支持

 

fangang     2007-01-22 09:15

amigobot 写道
没有下文了? 期待中。GRASP和GoF是不同类型的模式, 出发点不同。 GRASP是解决类之间如何交互, 如何设计合理, 和具体问题无关。

我同意。GRASP与GoF最大的区别,本人认为GoF往往是解决一些具体的问题,比如类的具体创建方式等等,而GRASP是解决对象分析的一些基本原则,即你如何去设计你的问题空间中的类和它们的行为,是原则性的东西。后面我会一个一个分析GRASP的9个模式,也就是9个基本原则,谢谢支持

 

newman     2007-01-24 10:36

有点意思。不过从fangang朋友对grasp的介绍,我得到的印象是grasp跟gof作为比较有些不当,可能是我的理解有误。希望能看到fangang朋友对grasp给出一个比较明确的定义,以及适用范围,比如在软件开发生命周期中,grasp在什么阶段用合适?有哪些效用。。。等等,期待中。

fangang     2007-01-24 13:46

谢谢指教,grasp和gof都是称为软件开发模式,只是描述的内容和角度不同,这相关的问题Craig Larman在《UML和模式应用》的第17章中有详细描述

fly_ever     2007-01-24 15:55

有一本书阐述了GRASP,《深入浅出设计模式 C#/JAVA版》,06年出版的。
感觉跟GOF相比,GRASP主要是用来指导面向对象的分析和设计。

fangang     2007-01-24 16:23

newman 写道
有点意思。不过从fangang朋友对grasp的介绍,我得到的印象是grasp跟gof作为比较有些不当,可能是我的理解有误。希望能看到fangang朋友对grasp给出一个比较明确的定义,以及适用范围,比如在软件开发生命周期中,grasp在什么阶段用合适?有哪些效用。。。等等,期待中。

grasp(General Responsibility Assignment Software Patterns),它往往适用于对象分析和设计中,即在RUP的制作分析模型和设计模型阶段。grasp有9种模式,是用于解决软件设计中的9种常见的问题,因此其效用各不一样,不能一概而论。

 

fangang     2007-01-25 09:51

非常感谢newman给我提的数个问题。GRASP虽好,GoF虽好,最关键是我们怎么用和啥时候用,这两个问题一直是我反复思考的问题。我正在筹划写一篇关于软件开发过程,特别是分析和设计这个阶段,如何运用GRASP和GoF的一点儿认识,期望和大家切磋切磋

posted on 2007-10-16 11:22 芦苇 阅读(1018) 评论(3)  编辑  收藏 所属分类: 其他

Feedback

# re: [转]一个优秀软件开发人员的必修课:GRASP软件开发模式浅析 2007-10-16 11:27 芦苇
一个优秀软件开发人员的必修课:GRASP(2)低耦合
我偶然在google或yahoo这样的搜索引擎搜索GRASP发现,除了国外的网站,国内网站多介绍和讨论GoF而很少介绍GRASP,即使这少量的文章也讲解非常粗略。个人认为作为优秀的开发人员,理解GRASP比GoF更重要,故写此文章。前面我在《  1.           “低耦合”这个词相信大家已经耳熟能详,我们在看spring哪些是耦合呢?

 

1幸运的是,目前已经有大量的框架帮助我们降低我们系统的耦合度。比如,使用struts但是,作为优秀的开发人员,仅仅依靠框架提供的降低软件耦合的方法是远远不够的。根据我的经验,以下一些问题我们应当引起注意:

1)   根据可能的变化设计软件

我们采用职责驱动设计,设计中尽力做到“低耦合、高内聚”的一个非常重要的前提是,我们的软件是在不断变化的。如果没有变化我们当然就不用这么费劲了;但是如果有变化,我们希望通过以上的设计,使我们在适应或者更改这样的变化的时候,付出更小的代价。这里提供了一个非常重要的信息是,我们努力降低耦合的是那些可能发生变更的地方,因为降低耦合是有代价的,是以增加资源耗费和代码复杂度为代价的。如果系统中某些元素不太可能变更,或者降低耦合所付出的代价太大,我们当然就应当选择耦合。有一次我试图将我的表现层不依赖于struts2)   合理的职责划分

合理的职责划分,让系统中的对象各司其职,不仅是提高内聚的要求,同时也可以有效地降低耦合。比如评审计划BUS

3)   使用接口而不是继承

通过对耦合的分析,我们不难发现,继承就是一种耦合。如果子类A《如何在 struts + spring + hibernate
aaa1.JPG
 描述:  
 文件大小:  21 KB
 看过的:  文件被下载或查看 676 次

aaa1.JPG
下载

最后更新:2007-01-31 08:47
14:51  |   永久链接  |   浏览 (4062)  |   评论 (8)  |    收藏  |   进入论坛  |  
评论    共 8 条 发表评论
silentlakeside     2007-01-22 16:51

支持一下,我也觉得GRASP很重要,我是在《应用UML与模式》这一书中看到GRASP,从此后我的设计思路基本上就是参照这几个原则了。我觉得很多设计模式都是从GRASP发展而来。

fangang     2007-01-22 17:02

是的,正因为它的重要,我希望通过这篇文章,提供一个话题,大家都谈谈这方面的体会,共同进步

daoger     2007-01-22 17:53

文章很好,地方不对!
发在敏捷开发板块才合适!

fangang     2007-01-22 18:57

daoger 写道
文章很好,地方不对!
发在敏捷开发板块才合适!
谢谢指教
Uranus     2007-05-11 09:28

说真的,我觉得你这篇文章才是写得最好的(和你的create模式相比,因为create模式中,你可能脑子很清楚,但是写的语句让初学者很摸不到头脑),我个人感觉好像设计模式都是国外人的提出来我们用,我们就缺乏提出思想的人,我们好多同志都是看这个好就拿过来用,根本说不出好在哪。你这个能力很强,希望将来在你的文章里面能多看到这种模式这样做的理由是什么

Uranus     2007-05-11 18:00

对了,我还想请教你一个问题呢,我之前听一个人说过,不管是gof的设计模式还是GRASP设计模式,最终的目的就是解耦合,不知道你怎么看这句话的,是否可以据个例子?

fangang     2007-05-14 10:06

谢谢Uranus的支持,实际上我们学习设计模式就是要思考它为什么好,我们为什么要用它,它还有没有问题需要修改。最近我正在着手写《“单例”改变了我们的设计模式》,详细描述在单例模式大行其道的今天,GoF中的许多模式都需要改改了。至于你的那个问题,我已经写到我的博客《设计模式GRASP和GoF是怎样解决耦合的问题》中了。

JavaVM     2007-05-14 11:54

期待你的《“单例”改变了我们的设计模式》

  回复  更多评论
  

# re: [转]一个优秀软件开发人员的必修课:GRASP软件开发模式浅析 2007-10-16 11:27 芦苇

关键字:   高内聚 Java 软件工程 软件模式    
在上一章(原创)一个优秀软件开发人员的必修课:GRASP(2)低耦合中我聊了聊低耦合,今天我想再聊聊与低耦合休戚相关、GRASP的另一个重要的模式:高内聚。

2.           高内聚是另一个普遍用来评判软件设计质量的标准。内聚,更为专业的说法叫功能内聚,是对软件系统中元素职责相关性和集中度的度量。如果元素具有高度相关的职责,除了这些职责内的任务,没有其它过多的工作,那么该元素就具有高内聚性,反之则为低内聚性。高内聚要求软件系统中的各个元素具有较高的协作性,因为在我们在完成软件需求中的一个功能,可能需要做各种事情,但是具有高内聚性的一个元素,只完成它职责内的事情,而把那些不在它职责内的事情拿去请求别人来完成。这就好像,如果我是一个项目经理,我的职责是监控和协调我的项目各个阶段的工作。当我的项目进入需求分析阶段,我会请求需求分析员来完成;当我的项目进入开发阶段,我会请求软件开发人员来完成;当我的项目需要测试的时候,我会请求测试人员。。。。。。如果我参与了开发,我就不是一个高内聚的元素,因为开发不是我的职责。

 

我们的项目为什么要高内聚呢?我觉得可以从可读性、复用性、可维护性和易变更性四个方面来理解。

1一个人写文章、讲事情,条理清晰才能易于理解,这同样发生在读写软件代码上。如果一堆代码写得一团乱麻,东一个跳转西一个调用,读它的人会感觉非常头疼。这种事情也许一直在写程序的你我都曾经有过经历。如果一段程序条理非常清晰,每个类通过名称或说明都能清楚明白它的意义,类的每个属性、函数也都是易于理解的它所应当完成的任务和行为,这段程序的可读性必然提高。在软件产业越来越密集,软件产业中开发人员协作越来越紧密、分工越来越细的今天,软件可读性的要求相信也越来越为人们所重视。

2在软件开发中,最低等级的复用是代码拷贝,然后是函数的复用、对象的复用、组件的复用。软件开发中最懒的人是最聪明的人,他们总是想到复用。在代码编写的时候突然发现某个功能是曾经实现过的功能,直接把它拷贝过来就ok在前面《如何在struts+spring+hibernate的框架下构建低耦合高内聚的软件》中我提到,我们现在的软件是在不断变更的,这种变更不仅来自于我们的客户,更来自于我们的市场。如果我们的软件通过变更能及时适应我们的市场需求,我们就可以在市场竞争中获胜。如何能及时变更以适应我们的市场呢,就是通过调整软件的结构,使我们每次的变更付出的代价最小,耗费的人力最小,这种变更才最快最经济。高内聚的软件,每个系统、模块、类的任务都高度相关,就使每一次的变更涉及的范围缩小到最小。比如评审表发生了变更,只会与评审表对象有关,我们不会去更改其它的对象。如果我们能做到这一点,我们的系统当然是可维护性好、易变更性好的系统。

那么,我们如何做到高内聚呢?就拿前面我提到的评审项目举例。我现在要为“评审表”对象编写一段填写并保存评审表的代码。评审表对象的职责是更新和查询评审表的数据,但是在显示一个要填写的评审表的时候,我需要显示该评审计划的名称、该评审计划有哪些评审对象需要评审。现在我如何编写显示一个要填写的评审表的代码?我在评审表对象的这个相应的函数中编写一段查询评审计划和评审对象的代码吗?假如你这样做了,你的代码就不是高内聚的,因为查询评审计划和评审对象的数据不是它的职责。正确的方法应当去请求“评审计划”对象和“评审对象”对象来完成这些工作,而“评审表”对象只是获取其结果。

另外,如果一个对象要完成一个虽然在自己职责范围内,但过程非常复杂的任务时,也应当将该任务分解成数个功能相对独立的子函数来完成。我曾经看见一个朋友写的数百行的一个函数,让人读起来非常费劲。同时这样的函数中一些相对独立的代码,本可以复用到其它代码中,也变成了不可能。所以我给大家的建议是,不要写太长的函数,超过一百行就可以考虑将一些功能分解出去。

与“低耦合”一样,高内聚也不是一个绝对,而是一个相对的指标,应当适当而不能过度。正如我们在现实生活中,如果在一个十来人的小公司,每个人的分工可能会粗一些,所分配的职责会广一些杂一些,因为其总体的任务少;而如果在一个一两百人的大公司,每个人的分工会细一些,所分配的任务会更加专一些,因为总体任务多,更需要专业化的分工来提高效率。软件开发也是一样,如果“评审计划”对象完成的业务功能少,并且不复杂,它完全可以代理它的子表“评审对象”和“评审者”的管理。但是“评审计划”对象需要完成的“对评审计划表的管理”这个基本职责包含的业务功能繁多或者复杂,它就应当将“对评审对象表的管理”交给“评审对象”对象,将“对评审者表的管理”交给“评审者”对象。同样,高内聚的可维护性好、易变更性好只能是一个相对的指标。如果一个变更的确是大范围的变更,你永远不可能通过内聚就不进行大范围的变更了。同时内聚也是要付出代价的,所以你也不必要去为了一个不太可能的变更去进行过度设计,应当掌握一个度。过度的内聚必将增加系统中元素之间的依赖,提高耦合度。所以“高内聚”与“低耦合”是矛盾的,必须权衡利弊,综合地去处理。综上所述,“高内聚”给软件项目带来的优点是:可读性强、易维护和变更、支持低耦合、移植和重用性强。

  回复  更多评论
  

# re: [转]一个优秀软件开发人员的必修课:GRASP软件开发模式浅析 2007-10-16 11:28 芦苇

关键字:   GRASP Java 软件模式    
 

当我们分析清楚客户需求设计出用例模型以后,当我们分析清楚客户的业务环境制作出领域模型以后,当我们综合用例模型、领域模型和我们的聪明才智设计出一个又一个的类和它们各自的方法以后,当就在一切都准备就绪只欠东风的关键时刻,一个对象发出了撕心裂肺的怒吼——谁来创建我?!!!一个对象,不管拥有多么强大的功能,不管进行了多么精巧的设计,如果不能被创建,就如同韩信不能做将军,孙膑不能当军师,勾践不能回越国,刘备不能得荆州,一切一切的雄才武略都如废纸一张。既然“创建”对于对象如此重要,我们就来好好探讨一下GRASP3.           当我们完成了用例模型、领域模型、对象分析的设计,初步完成了对象设计和职责分配的工作,开始进一步细化的时候,一个我们不得不考虑的问题就摆在我们的面前——谁来创建这些对象?也许现在的你会觉得好笑,这也是问题吗?在软件实际开发过程中,谁需要使用某个对象,就去创建它就行了,有什么好讨论的。但是,我不得不说的是,如果你只是漫不经心地想要随意开发一套软件系统,仅仅是完成自己工作而已,你完全不用考虑创建对象的问题。然而如果你希望开发一套高质量的、低耦合的、封装性和复用性高的软件系统,你必须得认真考虑这个问题。为什么呢?因为系统中如果一个对象A那么为了降低系统耦合,提高系统的清晰度、封装性和可复用性,应该有一些通用的原则,以用于对象职责分配中,关于“创建对象”这类职责的分配。这些原则的描述就在GRASP1)   创建者模式的描述

如果以下条件之一为真(越多越好),则将创建类A如果有以上多个选项适用,通常首先条件1

2)   何时使用

在理解创建者模式的时候,我认为一个首先必须理解的问题是,在软件项目的整个过程中,它应该是在什么阶段使用。一个网友曾经发帖问我,他不清楚GRASP3)   为什么

我们做事往往有个习惯,凡事问个为什么。前面我提到,使用创建者模式的主要目的是可以降低系统的耦合。那么,我们在使用创建者模式的这几个建议的时候是如何降低耦合的呢?这一直是困扰了我很久的一个疑问,Craig Larman创建者模式告诉我们,如果系统中存在包含者容纳被包含者,或整体聚集部分,则包含者往往是被包含者的最佳创建者,整体往往是部分的最佳创建者。为什么呢?首先,这样的设计易于理解,可读性强。为什么这么说呢,我们用我们常见的单据与单据明细来说明吧。一张单据有多条单据明细,这些单据明细聚集于单据中,是单据的一个部分。对于某张单据,我们只有去填写这张单据,才会去填写它的明细。同样,我们要查看和修改这张单据的明细,首先肯定是找到这张单据。以上这些是我们在实际生活中大家都认同的管理单据的方式。GRASP尽管包含者往往是被包含者的最佳创建者,整体往往是部分的最佳创建者,但是在一个软件系统中,并不是所有类都有它的包含者或者整体。如果没有,谁应当创建它呢?记录者当然是另一个可以考虑的人选。仓库管理员管理进出库是ERP如果我们正在设计的软件类也没有记录者,这可如何是好?具有创建这个类所需数据的那个类可以考虑,那个类就是信息专家(什么是“信息专家”,我会在以后对信息专家模式的文章中详细描述)。在我们的设计过程中,很多类的创建是需要一些初始化数据的。最典型的就是我们的vo如果以上方法还不行,那我们就只有找使用者了。寻找使用者是我们创建类最常用的一种方法,但它的缺点也非常明显。正如前面我描述的,我们系统中对某个软件类的使用可能分布到系统的各个角落。当我们因为某个需求需要修改这个类的时候,我们根本不知道谁在使用它。正因为如此,这样的修改变得如梦魇一般,不断地搜索,不断地修改。我们前面说过,合理的软件构造是为了使我们的变更代价最小,而这样的变更将使我们的代价太大了,也许一个不经意的变更错误将造成我们的系统中一个意想不到的地方发生异常。故我们变更后测试的代价也就因此而增大。总之,寻找使用者作为创建者是我们业务分析阶段最后的终极选择。

4)   创建者模式是原则,不是准则

“创建者模式是原则,不是准则”难道“原则”和“准则”还有不同吗?当然。创建者模式是原则,所以我们在业务分析阶段应当尽量遵守。但创建者模式不是准则,因为并非我们的所有软件类都必须遵守。为什么这么说呢?随着项目的进行,我们的分析设计就不再停留在业务的分析上,各种具体的框架和技术将不断引进项目中,这时对象的创建就不一定符合创建者模式。比如,为了提高系统的性能和可维护性、更好地处理对象的创建与回收等复杂的问题,我们常常把对象的创建交给工厂,如spring

总之,合理地创建对象可以有效的提供可读性、降低耦合度、提高系统的封装性和可移植性,我们应当引起重视。

  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: