ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

java – DDD:如何从Kotlin中的集成层隐藏特定的聚合根构造函数

2019-06-27 11:47:24  阅读:158  来源: 互联网

标签:java domain-driven-design kotlin


我对DDD有点新意,甚至在阅读了蓝色和红色书后,我仍然有一些关于如何将一些原则转换为代码的问题,特别是使用Kotlin和Java.

例如,我标识了一个客户端聚合根,它接收一些参数需要它来创建,如名称和地址:

class Client: AggregateRoot {

    var clientId: ClienteId
    var name: Name
    var address: Address

    constructor(name: Name,address: Address) : super(){
        // validations ....
        this.name = name
        this.address = address
    }

简单部分:
要创建一个新客户端,我在RS服务中接收一个DTO,并尝试创建一个传递上述参数的新Client类,大小写一切都很可靠,所有规则都已完成我将Client的新实例发送到存储库,非常直接.

clientRepository.store(client)

其他部分:
我需要搜索我的客户端来更改地址,以便我将id发送到存储库并在数据库中找到Client然后我需要将数据库实体转换为聚合根并返回给调用者.

override fun getById(id: Long): Client {
  val clientEntity = em.find(...)
  val client: Client(.....) //But I need another constructor with ClientId
  return client
}

然后我将需要一个新的构造函数,它接收更多的参数,如ClientId

constructor(clientId: ClienteId,name: Name,address: Address) : super(){

问题是每个服务都可以调用这个新的构造函数并创建一个不正确的聚合根实例,所以我的问题是:

>有没有办法隐藏完整的构造函数,只是为了查看存储库或特定层.就像在C#中你可以使用内部.
> Java或Kotlin是否有任何解决方案不公开应该仅用于测试和集成的构造函数?

另一个例子是,如果我不是每次创建客户端时都需要传递地址,而是在另一个方法之后传递,例如:

client.addAddress(address)

但在这两种情况下,我都需要从数据库中完成整个Client,所以我需要第二个带有address参数的构造函数.

解决方法:

因此,问题是如何通过将错误的接口暴露给客户端代码(即应用层或表示层)来从持久性中重新水合聚合而不破坏其封装.

我看到两个解决方案:

>使用反射填充字段.这是大多数ORM使用的解决方案,也是最通用的.它适用于大多数持久性类型,即使存在阻抗不匹配.一些ORM需要注释字段或关系.
>向客户端代码公开不同的接口.这意味着您的Aggregate实现比接口更大,并包含仅由基础结构使用的其他初始化方法.

作为伪代码的示例,您可以:

// what you want the upper layers to see
interface Client {
    void addAddress(address);
}

// the actual implementations
public class ClientAggregate implements Client 
{
    void rehidrate(clientId,name,address){...}
    void addAddress(address){...}
}

public class ClientRepository
{
    // this method returns Client (interface)
    Client getById(id){
        val clientEntity = em.find(...)
        val client = new ClientAggregate()
        client.rehydrate(clientEntity.id, clientEntity.name, clientEntity.address)
        return client //you are returning ClientAggregate but the other see only Client (interface)
    }
}

作为旁注,我不公开构造函数以从Domain的角度创建聚合.我喜欢使用空的构造函数和一个以无处不在的语言命名的专用方法来创建聚合.原因是不清楚构造函数是否创建了新的Aggregate.构造函数实例化一个类的新实例;它更像是一个实现细节而不是域关注.一个例子:

class Client {
    constructor(){ //some internal initializations, if needed }
    void register(name){ ... }
}

标签:java,domain-driven-design,kotlin
来源: https://codeday.me/bug/20190627/1304649.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有