锁定老帖子 主题:讨论一下面向对象中的封装问题
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2004-10-10
引用 面向对象的关键思想之一就是将数据与对该数据操作的行为绑定在一起
英文原文是 引用 One of the key messages of object-orientation is to bundle together data with the behavior that uses that data.
我觉得这句话似乎有很多反例。 比如MVC就是一个例子——对M的显示的职能从M中剥离出来了。 同样,策略模式也是一个例子——针对同一数据的不同操作被分离出来,以提供不同的处理逻辑。 我觉得这么说或许比较妥当:“将一组相关的行为、以及这些行为的状态绑定在一起”。 因为类是因职责而划分,而不是因数据而划分的。 想请教一下大家的看法。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2004-10-11
再说一遍,MVC没有把数据和功能分开,而是把业务逻辑和显示逻辑分开。
Strategy是一种特例:只有操作而没有数据的对象。这种对象还算合理,Command(functor)也是这样的对象,但相反的、只有数据而没有操作的对象就很难说合理了。 |
|
返回顶楼 | |
发表时间:2004-10-11
to:gigix
这个问题看你怎么看,某些特殊情况下还是有相当的合理性。如果说只有数据没有操作不合理,那对于象javabean这样的只有get/set操作,不包含什么具体逻辑的对象又如何看待呢?甚至我记得Martin大叔曾提过:如果能确定后续操作都是只读的,可以直接把DTO的属性设为public(意思如此,原话记不得了)。 原则是用来指导的,不是用来拘泥的。 |
|
返回顶楼 | |
发表时间:2004-10-11
业务逻辑和显示逻辑的分离不正是数据与方法分离了么?
显示使用的数据是业务逻辑生成的,但是它没有跟显示逻辑邦定在一起。 不过,什么是“使用的数据”这个问题可能有歧义…… |
|
返回顶楼 | |
发表时间:2004-10-11
逻辑的划分并不是数据的划分那么简单.实际上同样的数据在不同的层是受到不同的对待的,而实际上由于这些数据只能来自业务层对其他层的调用,同一个数据其实在不同的层所代表的职责并不相同.而实际上这是一种数据并未划分,而行为划分在不同层的场景.
而实际上数据和行为邦定在一起,并不是说所有的行为邦定在一个地方,而是说数据应该和他们的行为邦定在数据出现的地方.由于数据会出现在多处(实际上这是数据本身的映射,而不是真正的数据本身),所以行为也就可以被绑定在多处,而按照行为的逻辑划分把他们分开邦定在不同的区域. 而类的职责实际上是其数据和操作的共同体现,可以说操作实际上也是一种特殊的数据.于是你对类的划分也会涉及到数据和操作. 至于只有数据没有操作的对象是不是合理,我想也不是什么大不了的事情,只要存在合理的场景,就存在合理的应用. 而实际上我最想说的是,最近论坛上经常讨论一些基础性的原则,比如OCP/比如IoC/比如DIP.实际上这些原则在实际的应用中都存在大量的例证和反证,如果不从一个高层的指导思想的角度研究,在细节上转,只能是越转越糊涂.我们大家应该明白,作为一种原则,只是粗糙的说了一些主要的内容,而实际上这些不同的原则在实际中会有相互的复杂作用,你很难说这个地方就OCP了.而违反这些原则其实也没有什么大不了,只要你觉得好用就完全可以.这些是原则,具体的使用需要你在现实中去权衡,而不是要你照搬. |
|
返回顶楼 | |
发表时间:2004-10-11
gigix 写道 但相反的、只有数据而没有操作的对象就很难说合理了。
记不清了,不知道是在《C++大规模编程》还是什么书里提过这么一句(大意如此):“其实有时候数据仅仅就是数据”。这里引用一下大师的话,目的只是为了增加说服力。 在某些特别需要灵活性的场合,赤裸的(不包含操作的)数据对象才能满足要求。这是因为在这些场合中你可能需要这样那样的继承或者组合,虽然他们的操作角度不同,但是其基础数据却是同一个,对这种问题,单纯的数据对象非常必要,尤其是对于继承,这种优点很明显:如果是纯数据对象,从其继承而来的继承体系会非常清晰(因为你的继承体系中只出现你需要的操作行为,这样会使继承体系的目的异常的清晰明了);但是如果这样的基类对象被设计者设计为与某种特定的操作捆绑在一起,后来的人在扩展继承体系的时候会非常别扭,继承体系丑陋臃肿包含着不和谐的杂音不说,更重要的是破坏了继续继承扩展的可能。 我手中的这个系统就存在这样的问题,它把基础业务数据和很多的显示操作捆绑在一起提供了一个巨大的“功能强劲的”基类——由于这个基类在这个大系统中使用是如此的广泛,想做任何一点灵活性方面的改动都是异常的伤筋动骨,胆战心惊,但是保留着这样的基础体系结构同样使人痛苦不堪:由于业务上经常会发生变动,一点点小小的修改都会让人痛苦不已(我曾经为了改变显示的顺序,花了两天的时间,是两天的时间啊!!!而且程序代码非常凌乱,有心无力的感觉让人很烦,经常是做完之后都不敢确定自己做的是对的)。而且当我想把业务数据仅仅做一些纯数据的操作时,却因为这些数据和显示对话框的操作捆绑在一起,你想要使用这些数据,就必然会弹出对话框(这些是捆绑在基类中的啊!避免不了。重起炉灶?疯了,有那时间吗?况且业务那么复杂(其实可能是设计的太复杂),想起就吐苦水,怎么重写?而且有时候对话框还需要正确的数据才能不出红叉叉,才能不导致整个系统崩溃),这简直就是梦魇啊!现在我看到这个系统就头痛,可是周围的同事似乎对此满不在乎(也许这样才会显得他们有事可做?反正很少有人去操心这方面的事,系统架构师吗?这么大的公司当然有,不过……)。可是如果业务数据仅仅作为数据对象存在,我要继承要组合随我的便,我要怎么私下操作都不会有问题——但是前面那个基类,带给我的只有恐慌。面对这样一个你们质疑其对象身份但是给你带来巨大利益的数据对象和符合你们心目中对象风范的魔鬼,你们会选择哪一个? |
|
返回顶楼 | |
发表时间:2004-10-11
yapex 写道 原则是用来指导的,不是用来拘泥的。 同意! |
|
返回顶楼 | |
发表时间:2004-10-11
youngS 写道 在某些特别需要灵活性的场合,赤裸的(不包含操作的)数据对象才能满足要求。这是因为在这些场合中你可能需要这样那样的继承或者组合,虽然他们的操作角度不同,但是其基础数据却是同一个,对这种问题,单纯的数据对象非常必要,尤其是对于继承,这种优点很明显:如果是纯数据对象,从其继承而来的继承体系会非常清晰(因为你的继承体系中只出现你需要的操作行为,这样会使继承体系的目的异常的清晰明了);但是如果这样的基类对象被设计者设计为与某种特定的操作捆绑在一起,后来的人在扩展继承体系的时候会非常别扭,继承体系丑陋臃肿包含着不和谐的杂音不说,更重要的是破坏了继续继承扩展的可能。
我手中的这个系统就存在这样的问题,它把基础业务数据和很多的显示操作捆绑在一起提供了一个巨大的“功能强劲的”基类——由于这个基类在这个大系统中使用是如此的广泛,想做任何一点灵活性方面的改动都是异常的伤筋动骨,胆战心惊,但是保留着这样的基础体系结构同样使人痛苦不堪:由于业务上经常会发生变动,一点点小小的修改都会让人痛苦不已(我曾经为了改变显示的顺序,花了两天的时间,是两天的时间啊!!!而且程序代码非常凌乱,有心无力的感觉让人很烦,经常是做完之后都不敢确定自己做的是对的)。而且当我想把业务数据仅仅做一些纯数据的操作时,却因为这些数据和显示对话框的操作捆绑在一起,你想要使用这些数据,就必然会弹出对话框(这些是捆绑在基类中的啊!避免不了。重起炉灶?疯了,有那时间吗?况且业务那么复杂(其实可能是设计的太复杂),想起就吐苦水,怎么重写?而且有时候对话框还需要正确的数据才能不出红叉叉,才能不导致整个系统崩溃),这简直就是梦魇啊!现在我看到这个系统就头痛,可是周围的同事似乎对此满不在乎(也许这样才会显得他们有事可做?反正很少有人去操心这方面的事,系统架构师吗?这么大的公司当然有,不过……)。可是如果业务数据仅仅作为数据对象存在,我要继承要组合随我的便,我要怎么私下操作都不会有问题——但是前面那个基类,带给我的只有恐慌。面对这样一个你们质疑其对象身份但是给你带来巨大利益的数据对象和符合你们心目中对象风范的魔鬼,你们会选择哪一个? 这只是说明:即使把操作和数据放在一起,你也未必就能得到良好的对象。这跟“只有数据可以成为良好的对象”,根本就是逻辑上无关的两个话题。由你举出的论据,得不到你想要的论点。 我想除了RPC时的DTO之外,恐怕很少有什么理由使用一个纯粹的数据对象。你不妨举个这样的例子来看看? |
|
返回顶楼 | |
发表时间:2004-10-11
gigix 写道 这跟“只有数据可以成为良好的对象”,根本就是逻辑上无关的两个话题。由你举出的论据,得不到你想要的论点。
哦,我的论点是这样的吗?没印象了 |
|
返回顶楼 | |
发表时间:2004-10-12
"MVC"是一种模式,更确切地说,是一种基于OO编程思想的模式。唯有基于OO——也既是完全符合“将数据与对该数据操作的行为绑定在一起”这样的规则,才可能套用MVC。所以从逻辑上讲,你绝不可能套用了MVC,却反而违反了OO编程思想。
OO说的是如何构筑对象,MVC描述的是一组对象之间的架构关系。MVC根本就不涉及到“对象的封装”——那是最基础的OO关系,你连那都没搞定,谈什么MVC。 |
|
返回顶楼 | |