Architecture 从逻辑中分离数据

Architecture 从逻辑中分离数据,architecture,Architecture,假设我有一个具有“xp”值的用户对象。现在假设我有一个XPLevelsModel,其中包含一个XPLevels数组,它定义了该级别需要多少个点(除其他外): 好的,现在假设我有很多方法,比如“getCurrentLevel()”“getPercentProgressThroughLevel()”等等。这些方法应该放在哪里 我可以将它们放在用户对象上: class User { constructor(levelsModel:XPLevelsModel) : {} xp : in

假设我有一个具有“xp”值的用户对象。现在假设我有一个XPLevelsModel,其中包含一个XPLevels数组,它定义了该级别需要多少个点(除其他外):

好的,现在假设我有很多方法,比如“getCurrentLevel()”“getPercentProgressThroughLevel()”等等。这些方法应该放在哪里

我可以将它们放在用户对象上:

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 {}
}