我有一个数据类,它封装了相关的数据项。这些数据项在需要时由用户逐一设置和获取。
我对设计的困惑与哪个对象应该负责处理该数据对象的多个属性的更新有关。有时会执行更新操作,这会立即影响许多属性。
那么,哪个类应该有update()
方法?它是数据类本身还是其他经理类? update()
方法需要与许多不同的对象进行数据交换,所以我不想让它成为数据类的成员,因为我相信它应该对更新所需的其他对象一无所知。我希望数据类只是一个数据结构。我错了吗?什么是正确的方法?
我的代码:
class RefData
{
Matrix mX;
Vector mV;
int mA;
bool mB;
getX();
setB();
update(); // which affects almost any member attributes in the class, but requires many relations with many different classes, which makes this class dependant on them.
}
,或者
class RefDataUpdater
{
update(RefData*); // something like this ?
}
答案 0 :(得分:5)
罗伯特·C·马丁(Robert C. Martin)的书Clean Code中有一个非常棒的部分,直接说明了这个问题。
答案是取决于。这取决于你想要在你的设计中完成什么 - 和 如果您可能有多个表现出类似行为的数据对象。
首先,您的数据类可以被视为数据传输对象( DTO )。因此,它的理想形式只是一个没有任何公共方法的类 - 只有公共属性 - 基本上是一个数据结构。它不会封装任何行为,它只是将相关数据组合在一起。由于其他对象操作这些数据对象,如果要向数据对象添加属性,则需要更改具有现在需要访问该新属性的函数的所有其他对象。但是,另一方面,如果向管理器类添加了新函数,则需要对数据对象类进行零更改。
因此,我认为您经常想要考虑有多少数据对象可能具有直接与该类属性相关的更新函数。如果您有5个包含3-4个属性但都具有更新功能的类,那么我倾向于将更新功能作为“数据类”(更多是OO设计)的一部分。但是,如果你有一个数据类,将来很可能会添加属性,那么我会倾向于 DTO 设计(对象作为数据结构) - 更程序化(需要其他函数来操作它),但仍然可以是面向对象的体系结构的一部分。
正如罗伯特·马丁在书中指出的那样,所有这一切都在说:有很多方法可以让人知道 面向对象的设计者:例如VISITOR或双调度。 但是这些技术带来了他们自己的成本并且通常会返回 结构与程序性程序的结构。
现在,在你展示的代码中,你有类型为Vector和Matrix的属性,它们可能比简单的DTO包含的类型更复杂,所以你可能想要考虑那些代表什么以及它们是否可以移动到单独的类 - 具有不同的操作函数 - 因为您通常不会直接将Matrix或Vector作为属性公开,而是将它们封装起来。
答案 1 :(得分:2)
正如已经写好的,这取决于,但我可能会选择处理更新的外部支持类。
有一次,我想知道你为什么要使用这种方法?我相信可以安全地假设该类不仅为它收到的参数列表调用setter方法,而且我也会考虑这种情况
1)简单的更新程序方法
在这种情况下,我的意思是这样的:
public update(a, b, c)
{
setA(a);
setB(b);
setC(c);
}
在这种情况下,我可能根本不会使用这样的方法,我要么为它定义一个宏,要么我自己调用setter。但如果它必须是一个方法,那么我将它放在数据类中。
2)复杂的更新程序方法
在这种情况下,该方法不仅包含对setter的调用,还包含逻辑。如果逻辑是某种简单的属性更新逻辑,我会尝试将该逻辑置于setter中(这首先是它们的用途),但如果逻辑涉及多个属性,我会把这个逻辑放在外部支持类(或者业务逻辑类,如果已经存在的话),因为将逻辑驻留在数据类中并不是一个好主意。
开发易于理解的清晰代码非常重要,我相信通过在数据类中放置任何类型的逻辑(除了setter逻辑),都无法帮助您实现这一目标。
修改强>
我只是想添加别的东西。在何处放置此类方法也取决于您的课程及其实现的目的。如果我们正在谈论业务/域对象类,并且我们没有使用Anemic Domain Model
这些类被允许(并且应该包含)行为/逻辑。
另一方面,如果这个数据类是Entity
(持久性对象),而Domain Model
中也没有使用(复杂Domain Model
),我强烈反对将逻辑放在其中。对于“感觉”像纯数据对象(更像结构)的数据类来说,同样适用,不要污染它们,将逻辑保持在外面。
我想在软件中无处不在,没有灵丹妙药,正确的答案是:它取决于(在类上,这个update
方法正在做什么,应用程序背后的架构是什么以及其他特定于应用程序的考虑因素)