1

Question context

So I organized my application into bounded contexts (Eric Evans' "domain-driven design"). One of the bounded contexts is the "gameplay context." It, for instance, contains an interface Gamer

public interface Gamer {
    void setFriends(Set<Gamer> friends);
    Set<Gamer> getFriends();
    ....
}

There is also an implementation that is able to persist a Gamer's state to a database.

@Entity
public class JpaGamer implements Gamer {
    private String someData;
    private String someSensitiveData;

    public setFriends (Set<Gamer> friends) {
        ...
    }

    ...
}

Far, far away, inside another bounded context called "accounts context," I have classes and interfaces that deal with the users of my application. For instance, there is an interface called Account.

public interface Account{
    boolean isSignedUp();
    ....
}

So a user / Account can be signed up or not. For any Account, there exists a corresponding Gamer.

Challenge

I have a business rule: Never persist sensitive data anyhow related to a non-signed-up Account.

For example, this means that some non-signed-up Account's JpaGamer instance cannot write data to the someSensitiveData field. You could informally say that this JpaGamer is a "non-signed-up JpaGamer".

I don't want to hardcode any accounts-related logic into anything gameplay-related (and the same the other way around).

How can I implement such business rules in Java without tainting either bounded context with concepts from the other bounded context?

To fulfill the business rule, I have the idea that whenever there is a "non-signed-up JpaGamer", I wrap that JpaGamer inside a SparsePersistingGamer. The SparsePersistingJpaGamer would simply not forward to the underlying JpaGamer any method that could potentially tamper with someSensitiveData.
But now I have a problem with the someGamer.getFriends() method. For the SparsePersistingGamer, it would lazily load all that gamer's friends from JPA, returning a set of plain JpaGamers that are not aware of the (and any other) business rule, therefore persisting someSensitiveData for potentially "non-signed-up JpaGamers".

Which strategies do you apply to tackle similar and related situations?

4

1 回答 1

2

永远不要保留与未注册帐户相关的敏感数据。

该规则表明Gamer实体需要了解其帐户状态。我不熟悉您的域,因此我无法评论边界,但让我们假设确实有两个不同的 BC:游戏玩家和帐户。这表明需要某种同步 - 来自 Accounts BC 的信息需要到达 Gamers BC。信息可以通过多种方式传递。

一种方法是使用事件驱动架构 (EDA) 对每个 Gamer 实体中的帐户状态进行非规范化。这不会污染 Gamers BC,因为帐户状态是影响实体行为的适当信息。可以设置 EDA,以便 Account BC 发布有关状态更改的事件,并且 Gamers BC 订阅这些更改并更新 Gamers 实体中的非规范化数据。这里的优点是两个 BC 将是自治的。然而,需要考虑的一个因素是最终一致性- Account BC 中的更改不会与 Gamers BC 在事务上保持一致。这通常是可以接受的,因为延迟可以变得越来越小。

另一种方法是将帐户状态数据提供给使用该信息的 Gamers 实体上的所有行为。此信息将由实现与玩家实体相关的用例的应用程序服务检索。他们GamerApplicationSerivce会打电话给Accounts BC。这种方法的优点是简单——无需设置事件处理。缺点是自主性降低 - Accounts BC 必须可用于Gamer需要帐户状态信息的用例。

另外,我建议您避免使用不同的实体实现,从而避免使用实体接口。这增加了不必要的复杂性,并使推理行为变得更加困难。相反,在实体中明确表达所有领域逻辑,并通过环境应用程序服务或通过事件驱动的非规范化提供所需的数据。

于 2013-01-12T19:41:51.300 回答