OOA/D 01
建筑师一般不会为一栋100层的楼添加一个新的地下室,因为成本太高无疑会失败,但软件系统里提出类似改动需求时,他们通常都不会多想一下,相反他们会说:这只是一个简单的编程问题
可总会有一些看似极难完成、但却是市场所需的的需求,它可能会让你感觉需要推倒重来,这是我们不得不面对的问题
如果我们能在建造之初就预料到以后的“地下室需求”,或者希望对以后未知的需求有丰富的扩展体系,这就是OOA OOD的价值。举一个不切实际的例子,按照对建筑行业的通用认知,建造时先挖个3层高的洞放在那,先不管以后用作什么,未来是不是就可以很轻易的添加地下室或其他东西呢?
当然了,如果要把地下室改成飞机跑道那就还是无解,这属于畸形业务、畸形需求,并且已经跨领域了,经验再丰富的分析师也没有办法解决,只能推倒重来
顺带一提,OOA ,OOD,OOP,他们正是DDD的基础支撑,不严谨的说,DDD是他们落地方法论的一种,但OO最大的问题在于一股脑去体现 "结构"的表达,而DDD丰富了他们,其中最主要的是丰富了 "行为"的表达
复杂性
人在处理复杂事物时有自身的能力局限,如航空交通控制系统,必须同时处理不同飞机的状态、面对相当大的、交错的、非确定性的等等状态空间,一个人绝对没有办法跟踪所有细节
一些心里学家实验表明,人能同时理解的额最大信息数量是7个左右,大脑需要大约5秒才能接受一组新的信息,并不仅仅只有程序员是金鱼的记忆,所有人都是如此
工业级软件所涉及的问题域本身太大,单个开发者要理解它设计的所有方面太困难,甚至可以说这些系统的复杂性超出了人类智能范围,虽然我们可以掌握这种复杂性,但无法消除它
现状
简单的系统不谈,基于复杂系统的层面上,开发初期
需求方很难用开发者容易理解的方式对需求给出准确的表述,常见的方式是用一大段文字描述、偶尔配有草图,这样的文档难以理解,因为双方都缺少另一个领域的经验,双方完全站在了不同角度看待问题。甚至有时候连文档都没,仅凭需求方短短几十分钟的口诉,换来的就是程序员的胡乱猜测
还一个问题是,程序员缺少了系统的、合理的分析与设计方法,只将看到的东西如实反映在程序中,虽然头几个版本也许美食,但经过多个版本迭代后,代码的混沌也就慢慢显露了,这是没有对未来进行预判的结果,或者进行了预判但没有使用正确的设计方式
结果就是,当程序员开发完成后,用户、需求方在经过使用之后会对需求有更好的理解和表述,同时这个过程也帮助开发者了解了问题域,使他们能问出更好的问题,从而发掘出隐藏着的、需求方没有表露出来的真实需求、隐藏需求,然后程序员再对系统进行不堪入目的改造
这种改造的过程是一直循环的,企业成本明显提升,老板抱怨程序员任务完成周期太长。程序员自己也痛苦,抱怨需求变态。当然,这种问题无关某一方的对错,需要天时地利人和(愿意花时间沟通业务、愿意给时间做设计等),才能在最少的改造次数下完成
一般来来说,修正错误是维护,应对改变是演化,而当我们使用一些极端手段来保持系统能继续工作时,这是保护,目前看来大部分开发者在面对修正或改变时,不得不同时进行保护
分而治之
分解系统的空间状态,可以直接解决软件的复杂性,更好的理解与设计系统
目前的分解方式有两种,一种是算法分解,一种是面向对象分解,不能说哪种好哪种不好,在不同的阶段不同的场景都有各自的重要性
对于一个系统,最开始能接收到的信息只有一份基本需求,里面有所需的业务描述,下手的地方就是阅读,找出各种名词、动词等词语
算法分解
算法分解强调事件的顺序,围绕业务的动词建立起来,它是一种自顶向下的结构化设计,这导致了程序具有树的形态,面向了过程
当系统代码数量太多,比如超过10万行时,这种方式似乎就不行了,因为各处耦合而不利于伸缩,尤其是对于复杂系统
但用于某一具体场景时,却可以很直观的看出各流程节点逻辑、关系
面向对象分解
面向对象分解强调了代理,根据问题领域中的关键抽象概念对系统进行分解,每个对象都是真实世界某个对象的模型,它们要么发出动作要么就是这些操作执行的对象
通过复用共同的机制得到一些较小的系统,提供了更加低成本的表达性,作为真实世界实体的抽象,语义上也更加贴近业务,自身又代表了一块密集又内聚的信息,将巨大的状态空间进行关注点分离,直接关注了软件的内在复杂性
并且,对象模型在规模上可以扩展,一组抽象可以构建在另一组抽象之上,可以用更加宏观的视角来观察分析
它围绕各种类型的词语建立起来,具体说来,比如名词代表某一对象,动词代表对象的行为,动词词组代表关联并可能引申出场景,对象又需要分析它的结构,对象与对象之间可能又共享某一场景,这又需要合理的组织,等等等等
结构
植物包含三种主要结构,根、茎、叶,他们各自又拥有不同的特有的结构。例如根包含支根、根毛、根冠,叶有表皮、叶肉、纬管束
这些结构又由一些细胞构成,每个细胞内还可以发现另一层的复杂度,如细胞核等
他们的各个部分组成了一种层次结构,层次结构中的每一层又都有着各自的复杂性
植物细胞由刚性的细胞壁包围,但动物细胞却不是如此,尽管存在着差异,但不管怎么说这些结构都是细胞,这是跨领域共性的一个简单例子
组织
发现共同的抽象和机制可以促进对复杂系统的理解,一个有经验的飞行员,可以很快学习驾驶一架从未驾驶过的飞机,因为飞行员在学习之初就已经了解了他们的共同抽象:舵、节流阀等,只需要花点时间去学习这架飞机的特有特性:比如哪个按钮发射导弹之类
其实这说明层次结构的使用方式是很宽泛的,复杂系统往往有许多不同的层次结构
分析PC主机时,我们可以将它分解为主板、显卡、CPU等,这是一种结构上的层次结构,或者说组成部分的层次结构
而换一种方式分析,GTX980与HD4600都是一种具体的显卡,显卡代表了他们的共同抽象,这代表了"是一种( is a )"的层次结构,他们又有一些独有特征,比如GTX980可以运行很多大型游戏而HD4600却不能,这能帮助我们进一步掌握它们内在的复杂性
我们可以把这些结构分别称为"类结构" 和 "对象结构"(并非具指代码中的类和对象)
( 面向对象分解的建模 )
(附加了四色原型模式的对象建模)