我正在开发电动汽车充电站管理系统,该系统连接到几个Charging Station
,但我陷入僵局。在这个领域中,我为Charging Station
提出了一个聚合,其中包括Charging Station
的内部状态(无论它是否连接,它的连接器的内部状态(。
它有一个UnlockConnector
方法,为了准确地尊重它的名称(而不是贫血(,它将请求发送到相应的Charging Station
,因为它是我的域的中心,以了解Charging Station
的连接,并向物理Charging Station
:发送请求
type Connector struct {
Status string
}
type ChargingStation struct {
Connected bool
Connectors []Connector
URL string
...
}
func (station *ChargingStation) UnlockConnector(connectorID int, stationClient service.StationClient) error {
if !station.Connected {
return errors.New("charging station is not connected")
}
connector := station.Connectors[connectorID]
if connector.Status != "Available" {
return errors.New("connector is not available to be unlocked")
}
err := stationClient.SendUnlockConnectorRequest(station.URL, connectorID)
if err != nil {
return errors.New("charging station rejected the request")
}
station.On(event.StationConnectorUnlocked{
ConnectorID: connectorID,
Timestamp: time.Now(),
})
return nil
}
我提出了另一个表示Charging Session
的聚合,即用户和Charging Station
的Connector
之间的交互。Charging Session
的创建与Connector
的状态完全耦合,即,如果用户已解锁Connector
,则创建会话,如果Connector
的能量流已停止,则Charging Session
已结束。
无论两者多么耦合,Charging Session
实体似乎不属于Charging Station
聚合,因为它没有回答主要问题:当一个站点被删除时,它的Charging Session
也应该被删除吗?(此外,当我为这个会话中消耗的能量付费时,它与Station Aggregate上下文无关。
我想创建一个SessionCreator
域服务,以确保当Charging Station
的Connector
解锁时,也要创建一个Charging Session
:
type SessionCreator interface {
CreateSession(station *station.Station, connectorID int, sessionID int) error
}
type sessionCreator struct {
stationClient StationClient
}
type (svc sessionCreator) CreateSession(station *station.Station, connectorID int, userID string, sessionID int) error {
err := station.UnlockConnector(connectorID, svc.stationClient)
if err != nil {
return err
}
session.Create(sessionID, station.ID, connectorID, userID)
return nil
}
然而,这感觉有点奇怪,并且不能完全满足其他不变量(当连接器的能量流停止时,它必须结束会话(,我认为这也是一个侦听StationConnectorUnlocked
事件的事件侦听器,但我只是不知道哪种方式是理想的。
根据我对这个问题的理解,我认为您的聚合Charging Station
和Charging Session
是正确的。你说他们都是耦合的,但在我看来,Charging Station
不需要知道Session的存在,Session也不需要知道任何关于Station内部的信息,所以对我来说耦合度很低。
关于你关于当车站发生事情时如何创建和修改会话的问题,根据你的措辞,我似乎很清楚解决方案:
如果连接器已被用户解锁,则创建会话;如果Connector的能量流已停止则充电会话已结束。
突出显示的单词是业务事件。你可以这样画:
- 连接器解锁-->已创建充电会话
- ConnectorEnergyFlowStopped-->充电会话结束
我实现这一点的方式是使用发布/子系统,因此在状态更改后聚合发布事件,订阅者触发用例,用例可能会对聚合执行操作,最终可能会发布事件。
这种方法的分布式性质使得跟踪整个系统上发生的事情变得有点困难,因为解锁连接器和创建会话不是在一个地方发生的。它们可能发生在系统的两个不同部分。好处是,随着时间的推移,利益相关者可以在连接器解锁时想出许多需要发生的事情,而您只需要不断向现有事件添加订阅者。