浅谈GRASP软件开发模式
你是一个优秀软件开发人员吗?你知道GRASP吗?GRASP软件开发模式,全称通用职责分配软件模式(General Responsibility Assignment Software Patterns),是与著名的软件模式GoF(Gang of Four,即我们常说的那23种软件开发模式)齐名的另一种软件开发模式。但是与GoF不同的是,它并不是提出一些具体的软件组织结构,而是提出,在将现实世界的业务功能抽象成软件开发中具体对象的过程中,我们应当遵循的一些基本原则。遵循这些基本原则,我们才可以开发出高质量的软件出来。对于我们要开发的软件项目,我们可以不使用工厂模式、可以不使用单例模式、我们也可以不使用观察者模式,但是我们不可能不将现实世界的业务功能抽象成软件开发中具体对象。从这个角度说,我们要提高自己的软件开发质量,深入理解GRASP比深入理解GoF更重要。但是我看到现在介绍GoF的文章多,介绍GRASP文章少。正因为如此,我现在把GRASP介绍给大家。
GRASP包含了9个模式,也就是9个基本原则。这在软件设计大师Craig Larman的经典著作《UML和模式应用》中进行了深入地讲解。GRASP叫通用职责分配软件模式,要理解GRASP,我们首先必须理解的一个问题是,我们在对象分析和设计过程中为什么要进行职责分配。
一.职责分配和职责驱动设计
在一个软件项目开始的时候,我们通常需要进行需求分析,了解客户需要设计一个什么样的软件,这个软件中应当有什么功能。需求分析了解到的是现实世界中客户需求的业务功能,每个业务功能往往是一个业务流程,即客户在日常工作中不断在完成的业务流程。同时,在用户的问题世界中,必然有一些东西或者说事物,它们之间存在着相互的关联。
拿一个软件评审管理系统作为一个例子吧。评审管理系统的业务需求如下:
1.评审组织者制订评审计划,提交领导审批,然后通过邮件通知评审者。
2.评审者接到通知,分别对评审对象进行评审,填写评审表,并可以对评审对象提出疑问。
3.评审组织者汇总评审者的疑问,召开评审会议讨论这些疑问。在会上,有些疑问变为问题,有些疑问不是问题,有些则依然不能够确认。
4.会后,评审组织者整理疑问,形成评审报告,然后由评审者分别表决该评审是否通过。最后评审组织者汇总表决结果,形成评审结论。
5.评审组织者跟踪问题的解决。
通过以上需求的描述,我们不难发现整个问题世界中的相关事物:评审组织者、评审计划、评审者、评审对象、评审表、疑问、评审报告、评审结论、问题。我们也不难分析出这些事物相互关系,比如评审计划与评审者是一对多,而评审报告与评审结论是一对一。
在RUP中,业务需求将形成用例模型及其描述文档中的用例,事物及其关系将形成领域模型中的对象,当然如何制作用例模型和领域模型超出了本文讨论的范围,有兴趣的朋友可以看看相关文章。
领域模型中的对象将成为软件开发中形成具体对象的基础(软件开发中形成什么对象是根据软件开发的具体需求而定的,并不一定要与领域模型的对象一致)。用例模型中的用例,将通过赋予这些对象行为而得以实现。现在的问题就出来了,用例模型中的功能,或者说一系列行为,应当如何分配给这些对象呢。也就是说,为了完成同一个任务,我可以将行为A交给对象X,也可以交给对象Y。虽然交给对象X与交给对象Y,我对行为A的具体实现不一样,但是都可以完成行为A的任务。那么,我到底应当交给对象X还是对象Y呢?有没有一个基本原则呢?有,那就是按照职责分配任务。虽然从理论上说,我可以任意定义对象,可以让对象没有任何意义,或者去完成任意的工作,但是通常我们不会这样去设计。通常我们会将对象与现实世界的对象联系起来,比如设计一个评审计划对象、评审者对象。并且我们在设计对象的时候应当做到“低表示差异”。低表示差异就是我们设计的对象应当与现实世界的对象尽量一致。比如说我们设计一个对象叫“评审者”,是因为我们在现实世界中有评审者。同时,我们为评审者对象赋予的行为也应当尽量与现实世界一致,比如增加评审者、修改评审者、得到评审者信息。那么哪些是这个对象应当赋予的行为呢,这应当由职责来决定。
我们通过对现实世界的分析,或者说对于领域模型的分析,设计出了软件系统中的对象,这时候我们应当为每一个对象分配职责。什么是对象的职责呢,当然是通过对现实世界的分析,定义的这个对象应当完成的任务。比如评审者对象的职责是存取与评审者相关的数据。当然对象的职责不一定是一个,比如评审计划包含了评审对象和评审者的子项,所以它在工作不繁忙的情况下可以代理处理评审对象和评审者的信息存取。但是一个对象的职责不应当过多(也就2、3个就行了)并且高度相关。比如评审表对象如果分配职责处理评审表的同时,又去处理评审计划的数据,这就叫职责无关。
职责分配现在已经被普遍认为是一个优秀的软件设计应当遵循的原则,它有以下好处:
1.低表示差异使软件结构清晰,易于理解,因为软件开发并不是一个人的事情。在多人共同开发的软件项目中,一目了然的软件结构可以避免开发人员因误解而造成的不必要错误。
2.易于维护和变更。假如评审计划出了问题或需要修改,我们就去找评审计划,如果是评审者的问题我们就去找评审者,而绝对不会与其它对象有关。
这种通过考虑对象、职责、协作的对象设计及构件方式,被称为“职责驱动设计(RDD,Responsibility Drive Design)”。职责驱动设计是通过先设计用例模型、用例模型描述、操作契约、系统顺序图、领域模型、词汇表,再一步步制作分析模型、设计模型,写出每个功能的交互图、类图的很复杂的过程,我在这里就不再详述了。但是请大家注意一个非常重要的细节,前面我们说,软件系统中的对象是根据现实世界抽象得到,对象职责的分配是根据对象的定义,分配一些不多并且高度相关的任务。然而我们即使遵照这些原则,也有相当大的设计弹性空间,不同人根据自己的理解,对于同一个功能依然有各自不同的设计。GRASP中文译为“通用职责分配软件模式”,就是对对象分析和设计中职责分配问题提出数个基本原则。同时,这几个基本原则也应当掌握一个度,即并不是所有情况下都适用,也不是一个绝对的指标。比如低耦合,并不是绝对的不耦合,不耦合软件就没法设计了;高内聚也不能无限度地高内聚,否则系统就繁复异常了。
二.GRASP模式挨个析
GRASP软件设计模式包括9个模式:创建者、信息专家、低耦合、控制器、高内聚、多态性、纯虚构、间接性、防止变异。
以上是浅谈GRASP软件开发模式的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

C语言中通过转义序列处理特殊字符,如:\n表示换行符。\t表示制表符。使用转义序列或字符常量表示特殊字符,如char c = '\n'。注意,反斜杠需要转义两次。不同平台和编译器可能有不同的转义序列,请查阅文档。

在 C 语言中,char 类型在字符串中用于:1. 存储单个字符;2. 使用数组表示字符串并以 null 终止符结束;3. 通过字符串操作函数进行操作;4. 从键盘读取或输出字符串。

C 语言中符号的使用方法涵盖算术、赋值、条件、逻辑、位运算符等。算术运算符用于基本数学运算,赋值运算符用于赋值和加减乘除赋值,条件运算符用于根据条件执行不同操作,逻辑运算符用于逻辑操作,位运算符用于位级操作,特殊常量用于表示空指针、文件结束标记和非数字值。

在 C 语言中,char 和 wchar_t 的主要区别在于字符编码:char 使用 ASCII 或扩展 ASCII,wchar_t 使用 Unicode;char 占用 1-2 个字节,wchar_t 占用 2-4 个字节;char 适用于英语文本,wchar_t 适用于多语言文本;char 广泛支持,wchar_t 依赖于编译器和操作系统是否支持 Unicode;char 的字符范围受限,wchar_t 的字符范围更大,并使用专门的函数进行算术运算。

多线程和异步的区别在于,多线程同时执行多个线程,而异步在不阻塞当前线程的情况下执行操作。多线程用于计算密集型任务,而异步用于用户交互操作。多线程的优势是提高计算性能,异步的优势是不阻塞 UI 线程。选择多线程还是异步取决于任务性质:计算密集型任务使用多线程,与外部资源交互且需要保持 UI 响应的任务使用异步。

在 C 语言中,char 类型转换可以通过:强制类型转换:使用强制类型转换符将一种类型的数据直接转换为另一种类型。自动类型转换:当一种类型的数据可以容纳另一种类型的值时,编译器自动进行转换。

char 数组在 C 语言中存储字符序列,声明为 char array_name[size]。访问元素通过下标运算符,元素以空终止符 '\0' 结尾,用于表示字符串终点。C 语言提供多种字符串操作函数,如 strlen()、strcpy()、strcat() 和 strcmp()。

C语言中没有内置求和函数,需自行编写。可通过遍历数组并累加元素实现求和:循环版本:使用for循环和数组长度计算求和。指针版本:使用指针指向数组元素,通过自增指针遍历高效求和。动态分配数组版本:动态分配数组并自行管理内存,确保释放已分配内存以防止内存泄漏。
