Architecture 从逻辑中分离数据
假设我有一个具有“xp”值的用户对象。现在假设我有一个XPLevelsModel,其中包含一个XPLevels数组,它定义了该级别需要多少个点(除其他外): 好的,现在假设我有很多方法,比如“getCurrentLevel()”“getPercentProgressThroughLevel()”等等。这些方法应该放在哪里 我可以将它们放在用户对象上:Architecture 从逻辑中分离数据,architecture,Architecture,假设我有一个具有“xp”值的用户对象。现在假设我有一个XPLevelsModel,其中包含一个XPLevels数组,它定义了该级别需要多少个点(除其他外): 好的,现在假设我有很多方法,比如“getCurrentLevel()”“getPercentProgressThroughLevel()”等等。这些方法应该放在哪里 我可以将它们放在用户对象上: class User { constructor(levelsModel:XPLevelsModel) : {} xp : in
class User
{
constructor(levelsModel:XPLevelsModel) : {}
xp : int;
getCurrentLevel() : int {}
getPercentProgressThroughLevel() : Number {}
...
}
但是,随着我们添加更多的数据,如“生命”、“健康”等,用户将开始增加很多功能(对SoC来说不是很好)
我可以尝试将这些东西组合成组件,例如“XPComponent”,它是用户界面上的一个对象:
class User
{
xp : UserXPComponent;
}
class UserXPComponent
{
constructor(levelsModel:XPLevelsModel) {}
points : int;
getCurrentLevel() : int {}
getPercentProgressThroughLevel() : Number {}
...
}
但是问题是,从游戏的其他部分访问这些数据现在意味着user.xp.getCurrentLevel(),它违反了德米特定律,加上它的丑陋、难以测试,那么如果你深入到更高的级别,会发生什么呢
我还想到了另一个选择,比如:
class User
{
xp : int
}
class UserXPHelpers
{
constructor(levelsModel:XPLevelsModel) {}
getCurrentLevel(user:User) : int {}
getPercentProgressThroughLevel(user:User) : Number {}
}
在这里,我们分离出了逻辑和数据,并通过这些方法将其传递给用户。唯一的问题是,这不会破坏封装吗?由于所有这些方法都依赖于将用户传递给它们,它们不应该与用户生活在一起吗
如果这是正确的解决方案,“Helpers”是正确的名称吗
我希望你能帮助我解决一个一次又一次地向我提出挑战的问题,直到现在你才能够把它表达成一个问题
Mike如果更好的选择取决于内聚性,则可以使用这三种情况。换句话说,它取决于
xp
与User
的关系(它是属性还是聚合域实体,甚至它属于其他域)。其他值,如生命
,健康
等,可以有不同的解决方案。因此,您不必对所有内容应用相同的方法,而且,我确信它们在您的域模型中扮演不同的角色
1。高内聚性(属性),该值是父对象结构的一部分,没有它,父对象就无法存在。然后它应该是一个字段(属性)和/或一组方法,如第一个示例中所示
尽管如此,xp
似乎并非如此
2。聚合实体,该值与父级(聚合根)高度连接,但可以单独使用。这是XPComponent
的第二个示例。因此,您可以决定XPComponent
是否为域的聚合实体。这里我看不出德米特定律有什么大麻烦,因为它在更高层次的系统架构上是有意义的
3。单独的实体。它只引用父实体。这不是xp
的情况
4。服务功能。因此它既不是实体,也不是域模型的一部分。在这种情况下,您可以使用实际上是域服务的
帮助解决方案。您使用的是什么语言?如果您只关心第一个选项的类大小,那么就使用它吧。我尽量让它尽可能抽象,语言并不重要。这更像是一个一般性的问题
class User
{
xp : int
}
class UserXPHelpers
{
constructor(levelsModel:XPLevelsModel) {}
getCurrentLevel(user:User) : int {}
getPercentProgressThroughLevel(user:User) : Number {}
}