建模:是指通过对客观事物建立一种抽象的方法用以表征事物获得对事物本身的理解,同时把这种理解概念化,将这些逻辑概念组织起来,构成一种对所观察的对象的内部结构和工作原理的便于理解的表达。简单来说建模就是解决两个问题:怎么建?模是什么?
先做一个小测验:请在30秒内说出尽可能多的筷子、勺子和盘子的相同点和不同点。
这个问题没有标准答案,这个看似简单的问题其实反映了你是否习惯以抽象的方法去看待事物。在不知不觉中,每一组相同点和不通电都来自于你的一个抽象角度。例如,当从用途角度去抽象时,他们的相同点可能是三者都是餐具,而不通电是筷子是用于夹的,勺子是用于舀的,盘子是用于盛的;从用法角度去抽象,他们的相同点都是需要用手拿的,不同的手的动作不同;甚至可以从字面上理解,它们的相同点是都带了一个“子”字……同样这三个东西,从不同的角度可以得出不同的结果。
抽象角度的不同决定了建模方向的不同。当你试图为现实世界建模的时候,首先要决定的是抽象角度,即建立这个模型的目的是什么。
在实际项目中,当我们试图去分析需求、面对大量资料时,是否有时感觉无从下手?当试图去做一个设计,是否有时感觉到力不从心?此时说设计能力不够或经验不足,不如说你还没有找到明确的抽象角度。面向对象与面向过程不同的地方是;面向过程希望你通盘考虑,这时问题变得复杂化;而面向对象希望你把事情通过抽象角度分解成小块,问题就变得简单化。如同上面的小测试,在没有明确抽象角度之前,大部分面试者都会很慌张,不明白面试官为什么要问这样的为,不知该从哪里回答,也不知道回答得是否准确。如果加一个条件,变成请在30秒内说出在使用上筷子、勺子和盘子有什么相同点和不同点,这个问题就变得很容易回答了。
道理很简单,但很实用。不论在需求分析、系统分析还是系统设计上,读者一定要学会采用面向对象的方法,在面对问题领域时,首先不要决定去通盘考虑,而是找出问题领域里包含的抽象角度。如果你把抽象角度都找全了,并且这些角度都分析清楚了,问题领域也就解决了。
模是什么,则依赖于确定了抽象角度下的场景模拟。场景模拟帮助我们找出抽象的对象,而场景本身则是这些对象在一定条件下交互的一个特定的结果。当条件变化的时候,场景就会随之变化,我们并不试图控制这个场景。
一个由抽象角度确定了的目标需要由静态的事物加上特定条件下产生的一个特定的场景来完成,即静态的事物(物)+特定的条件(规则)+特定的动作(参与者的驱动)=特定的场景(事件)。
抽象角度:
抽象层次:抽象层次是面向对象中极其重要,但是又非常难以掌握的技巧。学会站在不同的抽象层次考虑问题是建立好模型的基础。
抽象层次越高,具体信息越少,但是概括能力越强;反之,具体信息越丰富,结果越确定,但相应的概括能力越弱。从信息的表达能力上说,抽象层次越高表达能力越丰富,越容易理解。举例来说:人们觉得一块石头很容易认识,因为他有颜色,有大小,有硬度。科室你有没有想过这些用来描述石头的概念都是具象的还是抽象的?何为硬度?是手摸上去的感觉?还是一个数字后面跟个物理学单位?你不会想这些,但你不会感觉石头是硬的这个概念难于理解。你觉得他们容易理解是因为经过多年的积累,这个抽象的概念被你消化和吸收了。这个看起来很具体的硬度是你从感觉、视觉、听觉、数字等综合起来后得出的一个抽象概念。如果说它的硬度是摩氏5级,非常具体,你反而不容易理解了。人脑对信息的处理能力是有限度的,如果信息量超过了人脑的处理能力,人就会失去对这个事物的理解能力。因此,越是具体的表达信息量越大,越接近人脑的处理极限,人们的理解能力越是下降(这也是面向过程方法为什么困难的原因之一)对面向对象方法来说,这时就需要提高抽象层次,用一个新的概念来概括一部分相关的信息,一旦人们像接受了光年这个概念一样消化了这个新的概念,理解起来就变得容易了。同时,这个新的概念就屏蔽了(或者说封装了)更多具体的信息。
如果 抽象层次太高,信息量太少,实施起来又有困难。在面向对象的分析过程中,适当时候采用合适的抽象层次是十分重要的。几乎所有用过UML的朋友都会觉得选择用例的粒度是一件很困难的事,实际上用例粒度选择的困难本质上是没有找准抽象层次而已。
抽象有两种方法:一种是自顶向下,另一种是自底向上。自顶向下适用于让人们从头开始认识一个事物。自底向上的方法适用于在实践中改进和提高认识。在软件开发过程中,主体上应当采用自顶向下的方法,用少量的概念覆盖系统需求,再逐步降低抽象层次,直到代码编写。同时应当辅以自底向上的方法,通过总结在较低抽象层次的实践经验来改进较高层次的概念以提升软件质量。
视图:视图的准确应用是建立好模型的一个重要组成部分。每个事物都有很多不同属性,每个属性都属于这个事物并仅能表达这个事物的一部分。仅仅给出所有属性的视图并不足够,观察者会抱怨视图表达的信息不是很清晰,希望从更多角度来查看事物的信息。这就引出了视图中另一个被忽视的重要概念:视角。不同的视角展示了同样信息的不同认知角度以便于理解。例如外观是汽车属性的一部分,那么外观是不是一个视图就足够了呢?不是的,同样是查看外观,有的人喜欢从前面看汽车前脸,有的人关注从侧门看车身流线。每个不同的观察角度都展示了整体信息的一个部分,这个部分也满足了观察者的某一个审视要求。
回到建模中,UML定义了用例图、对象图、类图、包图等等不同的视图,这些视图从不同方面描述了一个软件的结构和组成,所有这些视图的集合表达了一个软件的完整含义。由于软件的干系人有很多,不同人对同样信息的审视角度是不同的。在于需求人员沟通时,错误的视角选择,既费力又不讨好,常常导致需求改来改去难以确定。
对象分析放方法:
1)一切都是对象
2)对象都是独立的。对象与对象之间天然独立,只是在某个特定的场景下,他们的某一个特定的实例才相互联系在一起。要深入了解对象,我们经常需要分析很多个该对象的实例所参与的场景,以获得对象的多个侧面,再通过归纳整理这些对象的多个实例抽象出对象的一般特性。这就是对象的分析方法,同时也是使用UML来为对象建模时所采用的的方法。对象的产生、抽象并不是拍脑袋得来的,对象来源于场景分析,场景分析越多,我们对对象的了解越多,越精确。对象的独立性带来的正是对象的可抽象能力和可扩展能力。
3)对象都具有原子性
无论什么时候,在同一抽象层次上,在分析过程中都应当将对象视为一个不可分割的原子,哪怕这个对象的规模很大。原子性是抽象层次有意义的重要保证,一旦破坏了原子性,则表示在同一抽象层次上的对象不具备同样的粒度,这使得分析工作陷入混乱。在分析过程中,永远不要打破边界去窥探对象的内部。
4)对象都是可抽象的。对象参与的场景越多,对象越有抽象价值,反之则越没有抽象价值。因此在分析过程中,应当关注那些参与了很多场景的对象,它们往往是分析设计中的重点以及成败关键。
5)对象都有层次性。
对象分析方法总结:独立性、原子性、抽象性和层次性是面向对象分析时应当遵循的一些原则和方法。如果分析中遇到某个对象是一个关键对象,则尽量说明下图中所示各方面的内容:(P39)