请教建模的问题,如实客观世界时的性能问题

有一个建模的问题请教,看多了banq大哥的论坛,设计系统时就会想着面向对象而不是面向数据库,但每次都发现面向对象实现起来总是有很大的抗阻,担心性能和工作量的问题。
现在举个具体的例子,
给展会系统建模,主要有几个实例:展会定义,展会实例,展期,展馆,展区,公司。它们的关系可以从图1看出。
比如展会定义是广交会,展会实例是具体到某某届的广交会。

如果按照对它们关系的正确反映,我的分析是图3。

在真正的业务中,展会实例和公司是最重要的两个实例,其次是展区,再到展期, 展馆。
会有大量这样的操作:
1,通过展会实例找出公司,
2,通过展区找出公司

如果真的按照这样的关系建类,问题就来了,性能应该是比较差的,而且类与类的间接关系太多,查找起来比较费力,展会实例找出公司要先找出展期,再找展区,再找子展区,才到公司。
考虑到展会定义,展会实例,展期,展馆,展区,公司之间的关系基本上是最少改变(基本不会出现这个展期改到另一个展会实例,这个展区改到另一个展会),为了提高性能,加了几个关系的冗余,同时把展期, 展馆弱化,以增加维护它们之间关系的复杂度来换性能,同时,多对多的关系,用中间对象来拆分。如图2:


是不是又回到面向数据库的旧路了?其实我的困惑就是怎么样才算是面向对象,怎么样才算是面对数据库。虽然看了banq大哥很多的建模方面的文章,但真正实现起来却不是分析的那么简单,除非不考虑性能和工作量。
大家说说这个例子怎样设计最合理,当然要考虑性能的问题,希望能把复杂的问题简单化,忽略不会变的东西。





再补一张图



》其实我的困惑就是怎么样才算是面向对象,怎么样才算是面对数据库
这是很多人的困惑,因为我们教育背景中没有关于OO知识,就象没见过骡子的人,怎么知道骡子和马的区别呢?所以,必须深刻掌握丰富的OO知识,如模式 DDD等等。就象你对数据库知识那样深刻,甚至成了自觉。这是一个全新重新学习过程,而且必须排除以前数据库经验的干扰,更是难上加难。

OO建模是负责将客观世界模型映射到软件世界,至于软件世界的代码性能问题,则不属于OO建模问题,属于架构问题,这方面Java有足够丰富的架构技术来提升性能。

具体你这个案例,有几个OO建模要点需要掌握的是:
1.使用OO的目的是简洁直接,低关联是一个要点,多对多关系几乎毫无意义,关系多了就没有关系,所以,一看你的图如果是蜘蛛网,那就说明耦合难缠的种子就被种下了。

2.DDD建模建议结合设计模式来分析设计,明显,你这个应用中,展会 展区 展馆 公司是一个树形结构递归关系,这可以使用GOF模式中组合模式实现,具体案例可见 estore的演示效果,可以自定义类别节点,这是一个组合模式实现:
http://www.jdon.com:8080/estore/

3. 对于复杂项目,DDD建议我们找出核心子领域,那么展会实例和公司应该属于核心子领域,围绕这两个核心实体模型,找出其他实体,注意,在这个过程中,别范数据库的毛病,就是把本来表示关系的概念使用对象/数据表来表达.
你的图中展会定义 展会实例 展期 展区都要根据需求重新定义,是否需要这些对象,他们的性质是否都属于四色原型中的PPT,表示某个地方,如果是这样,围绕公司只需要一个位置对象来标识其展区位置即可,至于展区展馆之间的分类是一个树形结构,和核心模型没有关系。


划分出重点,找到核心,排除干扰,就能实现OO系统,这些都是很普通的做事方法。OO就是这样自然。

希望对你有帮助。

谢谢banq大哥的回答,

》至于软件世界的代码性能问题,则不属于OO建模问题

在OO建模是不是也要考虑代码性能问题呢?


有些原理还是知道的,因为看了不少banq大哥推荐的书和文章。但还是不能很正确地运用。之前的文章都是一些理论性的东西,没有一些比较复杂的例子的介绍。banq大哥能不能结合这个具体的例子给出一个比较具体的答案呢?就是类与类之间的关系。现在还是比较模糊。


我说的例子就是广交会的官方网站,
http://www.cantonfair.org.cn/

>在OO建模是不是也要考虑代码性能问题
建模和架构是两个方面,代码性能属于架构方面考虑的事情,可以通过适当框架来提供性能的可伸缩性。

>没有一些比较复杂的例子的介绍。banq大哥能不能结合这个具体的例子给出一个比较具体的答案呢

这方面Evans在其DDD书籍中比较多,其网站也有不少案例心得,我也可以企业上门进行培训咨询。

还是先把需求分析清楚吧,搞清楚有哪些概念并划分出重点核心概念,业务逻辑理清楚,然后再把这些概念和逻辑用我们面向对象的方式表达出来,这就是一个建模的过程。先从静态着手,把这些概念的静态结构理出来,这里并不是简单地把现实世界的实体一对一的映射为类,如果是这样的话仍然只不过是面向数据库的简单的变种,在适当的情况下我们要增加面向对象中的一些概念如服务等;然后我们要做的是为这些对象分配职责,这也是建模的一个难点,要让各个对象职责明确,不能越权。最后是协调这些对象之间的合作以完成业务逻辑。

对于广交会的例子,正如楼主所述,广交会实例和公司是最重要的两个概念,广交会其实就是主办方提供一个交流的平台,很多公司聚到这个平台上展示自己的产品。楼主也列出了这个例子的几个概念和分析图,图1是整个广交会实例的一个内容关系图,图2一看就关系凌乱,象蜘蛛网,而图3看似条理清晰,我觉得还是有所欠妥。

首先还是理一下概念,我觉得这个例子中展馆展区的概念不太明确,有点混淆,这里的展馆展区应该是逻辑地址上的一个划分,而所谓的工业类展区,纺织服装类展区其实应该是指这个展区所展示的产品的类别,所以这里应该独立出一个产品类别的概念,产品类别可以分大类小类,无限的分类下去,展馆展区其实也就是一个展区的概念,类似产品类别的概念,是一个大小类的所属关系,这种关系可以用一个典型的设计模式来解决,那就是组合模式。这里还有一个展期的概念,其实是一个起始时间范围。所以广交会实例描述的其实是“展期—展区—产品类别—公司”这么一个关系,即“在某一展期的某一展区展示什么产品,有哪些公司参展”的一个详细信息集合。所以我感觉关系图应该如下所示:

考虑到需求的变化,我们不能把需求看得太死,我们假设一个展区在不同的展会甚至同一展会的不同展期内可能展示不同类别的产品,一个产品类别也可能在多个展区同时展示,一个公司也可能同时在多个展区展示不同类别的产品,在不同的展期里在同一个展区也可能展示不同类别的产品。所以为了保证系统的扩展性,类与类之间的关联不能太多,没有本质关联的对象之间绝对不能加上不必要的关联。所以在这个例子中,展区不能直接和产品类别关联,也不能直接和公司关联,同样,产品类别也不能和公司直接关联。

楼主的图3看起来好象条理很清晰,用面向对象的方式可以描述为展会实例.get展期().get展馆().get展区().get公司(),而实际上展区本身是没有职责去知道展区之内有多少公司的。这样的逻辑也不是一个实质上的递归过程。广交会对象是有职责知道有哪些公司参会,但是要通过展区得到有哪些公司则必须给广交会实例分配按展区查找公司的职责,表达如:广交会实例.get公司by展区(展区:展区实例)。同理,也可以分配按产品类别查询的职责。

所以至于楼主提到的会有大量这样的操作:
1,通过展会实例找出公司,
2,通过展区找出公司
其实都是由广交会对象来完成,广交会对象是整个聚合的根,是核心对象。至于展区对象,它的职责只能是查找它的父展区或者是子展区,产品类别对象也是同样的道理。

以上是个人观点,仅供参考!



[该贴被killer于2007-11-17 16:55修改过]


晕,怎么图片传上来成了这样?

可以回复了?

我没有把具体需求说清楚,所以不存在答案,killer的分析给了我很大的帮助,经killer这么一说好象一些本来模糊的东西变得清晰了。

整个需求是通过这个网站,让去看展会的人能更好地了解到展商的信息,参加展会的人虽然最终目的是产品,但通过这个网站系统更多是想了解他感兴趣的产品的展商,而不是产品本身,当找到展商后,可能才会去找这个展商的产品或者是展商在某个展会的某个展区展示的产品。(可以去展示某类产品的展区找展商,很少是找展商下的产品然后找到展商),这是我对展会网站的理解,因为我觉得展会网站是不会替代展会本身的,展会网站只是对展会提供服务。

图2其实是我的设计图,可能不能表达我的思路,我不会画图,只是说明实例与实例之间的一对多或多对多等 关系,我只是简单的以为在实际操作中能从展会能找到展区和展期,所以展会与展区之间,展会与展期之间有关联。

其实一看,图2虽然是类图,却又是数据库设计的结果,正是killer 所说的“这里并不是简单地把现实世界的实体一对一的映射为类,如果是这样的话仍然只不过是面向数据库的简单的变种”,还是没走出数据库的影。

killer的图看得不清楚,是不是每个实例都是与展会关联?除此外其它实例间没有直接关联?
那么在操作中是怎样从展区找到展商,如果能找到,那不是展区和展商就有关联吗?在数据库上说就是展商中有个字段是放展区的主键。可能killer说的才是真正的领域图,请指点。

对killer的分析有以下几方面理解不透
1“展期—展区—产品类别—公司”怎么的理解呢,是说展区与公司没有直接的关联,是通过产品类别来找到
2.“我们假设一个展区在不同的展会甚至同一展会的不同展期内可能展示不同类别的产品”,我之前是想过在展区定义里要独立出展区实例这个概念,就好象展会与展会实例的关系,但又觉得这样复杂了(实现复杂,用户操作也复杂,要去建展区定义,而这个展区定义可能会很多),考虑到很少会说要找通过展区定义找所有这类展区实例,所以就把展区定义去掉了,其实这样也让展区实例之间失去了关联。为什么在区分展区实例呢,比如2007年上半年广交会的工业展区和2008年上半年广交会的工业展区不是同一个对象实例,它们有各自的展商,各自的展区图片,各自的介绍等等。如果是这样设计,那应该是不会存在“一个展区在不同的展会”在不同展会看作是不同展区了,展区与展会是一对多了。不是多对多。
3."所以为了保证系统的扩展性,类与类之间的关联不能太多,没有本质关联的对象之间绝对不能加上不必要的关联",怎样才算是有关联呢?在类与类之间的关联对应到数据库就是外键是吗?“类与类之间的关联不能太多”是说冗余关联吗?因为有些关联是必然的吧。如展会与展期的关联,展区与公司的关联。而展会与公司的关联和展会与展区的关联就是冗余关联。
4.“展馆展区其实也就是一个展区的概念,类似产品类别的概念。”要看业务要求了,如果对展馆展区要求不高时可以合成一个展区的概念,这样关联就简单多了,但如果从客观世界来说“展馆展区”本来不是同一类的东西,放在一起会不会违背某种思想?如果系统做大了,展馆展区是要独立出来的了,因为它们属性根本是不一样的。这个疑惑和“要不要增加冗余关系”一样,增加冗余关系会使对象关联变成蜘蛛网,但可能更符合某些业务要求(性能),当然这些冗余关系不是随便加的,是考虑到"展会实例,展期,展馆,展区,公司之间的关系基本上是最少改变"。象“合成一个展区”,“冗余关系”这类感觉违背某个思想的要怎么取舍呢。

OO思想都是从现实生活转换到软件世界的一个过程,正如killer所说的是一个抽象的过程,一个是怎么“抽”,抽出来怎么去判断“象”,而这个过程每个人的理解都不一样,到底去怎么定义?

现实生活与软件世界,个人认为是怎么抽象都是不会相等的。只有在这中间找到一个“度”,在领域设计过程可能偏向于现实,在代码与数据库实现则偏向与软件世界,到底怎么去掌握这个“度”?

5.产品类别是直接与展区关联,算是展区的一个属性,表明这个展区显示的类别(只是分类,不表示这个类别的展区一定不可以展示其它类别的产品,也就是展区中的产品类别与公司产品中的产品类别是两个不同的,没有关联的东西)。产品类别还与公司的产品有关联。

有个不清楚的问题,领域分析,oo思想,能不能解决以下问题,如果能,体验在哪方面:
1.系统前段要求不高,只是展示简单的展会信息,展会有什么展区,有什么公司参展。这时候分析出来的核心对象只是展会,公司等 。但系统后期,做大了,可能要求展期,展馆等都是系统中一个重要的模块,在展馆模块的展示页面,可以了解到某个展馆各方面信息,如在这个展馆中展出过的展会,展馆的图片,展馆的所在城市,展馆里的场馆,楼层,占用面积等。这时候,展馆就从之前的一个不核心的对象变成了一个核心的对象了。用了领域分析,oo思想后,这些的需求变化系统是怎样轻松应对?当然不可能在系统前段就做到系统后段的功能,成本的问题,而且系统也不一定做大。

看了killer的东西还有一种体会是能把一些东西用固定的思维模式来思维并表达。
现在我分析东西连自己也不敢肯定是对的或是全面的,正是想找这样的方法论。


看了展会实例职责分析后,对怎样区分对象的职责有了实质的头绪。从分析层面看,区分好职责能更能反映客观事物,从具体的实现层面来看,区分职责在是不是为了更好地放置代码吗?
但是要通过展区得到有哪些公司则必须给广交会实例分配按展区查找公司的职责,表达如:广交会实例.get公司by展区(展区:展区实例),如果从具体的实现来看,这句话可不可以理解为:如果我用贫血pojo,就是应该把 “get公司by展区(展区:展区实例)”放在展会实例的服务层,而不是放在公司或展区的服务层。从代码的放置来看,这样对吗?

再次多谢killer 和banq的回复,让我学到了很多东西。

楼主写了很多,对自己对大家都很有意义,不少问题还等killer来详细回答。我就回答几个宏观问题。

>系统前段要求不高,只是展示简单的展会信息..但系统后期,做大了,展馆就从之前
>的一个不核心的对象变成了一个核心的对象了。用了领域分析,oo思想后,这些的需
>求变化系统是怎样轻松应对?当然不可能在系统前段就做到系统后段的功能,成本的
>问题,而且系统也不一定做大。

领域分析设计是一种方法,就比喻成一个放大镜,客观世界比如是一张地图,我们需要关心哪块地方,就透过放大镜来看分析哪个地方。

OO精神之一是分离松耦合,一个一个去对付,这样,需求变化了,只要修改扩展相应的子领域模型就可以。

配合采取敏捷FDD等工程方法,分析出一个核心子模型就把相关功能模块完成。
http://www.jdon.com/jivejdon/thread/28312.html

>个人认为是怎么抽象都是不会相等的。只有在这中间找到一个“度”,在领域设计过
>程可能偏向于现实,在代码与数据库实现则偏向与软件世界,到底怎么去掌握这个>
>“度”?

这个问题其实就是过去分析和设计分裂导致的问题,虽然分析很偏重于现实,但是到了具体实现时,程序员在软件世界走偏方向。导致最后编出的软件和实际需求不符合,甚至偏离,也不能跟随需求变化。

所以,领域设计全名为领域驱动设计,增加了“驱动”两个字,就象发动机是汽车的驱动力,科学是生产力的驱动一样,领域模型是软件世界的驱动力,其他代码和数据库都必须围绕领域模型为核心,这些就要求一些具体技术保证:必须杜绝关系数据库和SQL对对象的影响,Evans DDD推荐使用专门的O/R 框架。当然如果能使用对象数据库db4O 则更好。所以,我一直说:不管什么语言(ROR/PHP/Java),都只有杜绝关系数据库的影响,才能更有效率发挥OO威力,目前只有Java完全做到了。

对象数据库db4O :
http://www.jdon.com/article/33074.html

[该贴被banq于2007-11-26 10:24修改过]

我个人认为,应该首先确定整个系统的基本实体构件。
在时间和空间上,它应具有完整性和独立性。
在时间上,在这里是展期,表现为实体的生命周期,在空间上,表现为展位。
作为展览方,它也有自己特殊的产品,就是这样的一个有时效性的展位,暂叫做展位实例。
在一般情况下,一个展位实例就对应一个厂商。一个厂商可以拥有多个展位实例。

至于一个展位被拆分成多个厂商占用的情况,可以用商务的方式去控制,尽量保证展位的完整性。
当然特殊情况,可以考虑当作例外去处理。


在静态结构上,构成展会,展馆,展区,展位四个层次。
一个展会在空间上有多个展馆组成,
一个展馆在空间上有多个展区组成,
一个展区在空间上有多个展位组成。

反过来,一个展位隶属一个展区,一个展馆,一个展会,这样的映射有利于查询。

还有这样的关系:一个展位对应着一个厂商,一种产品,一类产品, ...

提供一种思路,仅供参考

楼上从时间和空间两个点去考虑值得推荐。

关于楼主长贴中存在诸多疑问,我感觉总体是被广交会中几个分类给绕住了,必须脱离这些细节的分类,站到时间和空间的全局高度来分析需求;

另外因为你有数据库分析习惯,这些分类如展区、展位实际可能只是一种关联性质的表,而你却把他们当作实体,也就是有实质内容,看得见摸得着存在的物体,用数据库分析一个陌生领域时,就是无法分清楚试实体表和关系表,我个人认为:展区、展位都是人为给与的一种集合性质概念,就象论坛案例中Thread,Thread实际上是message集合,一个主题集合包含很多相关主题的帖子,Thread实质内容就是Message,Message实体是论坛案例的核心之领域,Thread则不是。:

>展期—展区—产品类别—公司
公司为核心,上面的分类可以有很多层,就象产品分类一样,产品分类层次很多,洗衣机上面有家用电器,家用电器上面有电器,电器上面生活用品等等。所以,这些都是在重复树形结构的关系,不要深入到这些分类层次中。

展会,展馆,展区,展位在空间上四个层次,实际可以用一个树形结构模型来代表就可以,这就是在静态空间上抽象。

再看看这些概念中,有无和时间概念有关的,和时间有关的就是活动,使用计算机就是来tacking跟踪的,这就能用上Martin Fowler的分析模式,如account等模式。
按四色原型来分析看,和时间有关的就是MI,MI我们可能需要在代码上通过服务来展现。

总之,和时间相关的就看成是记录跟踪,这样,就能实现楼主说的"2007年上半年广交会的工业展区和2008年上半年广交会的工业展区"。

关于楼主长贴中提出的'广交会'对象,我个人认为没有必要提炼这个对象,缺省业务领域就是广交会,除非你的软件可能用于华交会等其他展览,初期在没有搞定广交会这个展会情况下,不建议扩展到其他展会。

楼主提到:
>因为有些关联是必然的吧。如展会与展期的关联,展区与公司的关联。而展会与公司
>的关联和展会与展区的关联就是冗余关联。

有些关联不只是必然,而是一种强关联,是一种高度关联,整体和部分的关系或组成关系,缺了部分就不成为一个对象了,而且必须注意,这种关联是对象组成的时考虑的,是从空间静态上考虑的。这是第一点。比如楼主说展会和展期的关联,实际上,展期是展会的一个内聚字段,一个没有展期的对象能够叫展会吗?

第二点:关联是有顺序的,在"间接"帖子中killer说了,"上"和"海"和"海"和"上"顺序不一样,意思就不一样,因此关联分单向和双向,尽量用单向不用双向,双向实际没有意义,将问题复杂化,有数据库背景的人很容易忽视这一点。比如楼主说展区和公司关联,应该是公司和展区的关联(应该是上海,而不是海上),公司为主体。

间接:
http://www.jdon.com/jivejdon/thread/33066.html#23111535
[该贴被banq于2007-11-27 12:23修改过]

如果只是分析静态结构,没有类不类的概念,也没有数据库的概念,就纯粹指的是业务对象关系,如下图:




[该贴被apexCloud于2007-11-27 11:53修改过]


上述只是描述了业务对象的表象,进行提炼抽象后的概念应该为:


给特定产品展示产品的地方称之为产品展示区,在那个馆几楼那个区域只是表达它的位置的参数。其核心是要表达那个产品(确定供应商的产品)在哪个产品展示区展示


[该贴被apexCloud于2007-11-27 12:50修改过]


看了楼上apexCloud 的图,我发现之前分析没有提一个实体:产品,我前面提出公司(参展方)为核心模型,整个广交会需求可以概括下面一句话:

某个公司在某个时间(展期)在某个地方(某展会的某展区)展示它的产品。

广交会实际就是围绕众多公司发生一件事情,事情发生时间:“展期”,事情发生的地点:“展会展区”,事情内容:“展示产品”。如果知道四色原型,下面就更好分析了。

所以,这里产品看似和公司有关联,但不是高强度关联,公司和产品的关系是必须通过生产或展示等活动才发生的,而不是天然静态的。所以,公司和产品之间不建议给予任何关联关系。也就是不同意apexCloud图中将参展方和产品画上关联。

[该贴被banq于2007-11-27 13:12修改过]