领域驱动设计 CQRS 与多个聚合和界限上下文
我正在尝试结合命令和事件,以及领域驱动设计,但不太确定如何处理涉及多个聚合的命令。
假设我有一个使用场景,一个新客户选择了一个计划,这时需要为这个客户创建一个账户,并将客户添加为该账户的成员。同时,这个账户还需要加载通过购买所选计划获得的套餐详情,比如用户限制和总座位数。
为此,我定义了一个账户聚合,其中成员是账户上下文中的本地实体,计划聚合则在订阅上下文中包含套餐值对象。我会触发CreateAccountCommand,传入plan_id、customer_name和account_name,然后我需要从计划聚合中获取与plan_id相关的套餐详情,并用这些信息来创建新的账户和成员。
那么,处理这种情况的有效方法是什么呢?根据我所读到和理解的,我认为获取计划详情的过程应该分开处理,查询的结果应该传递给CreateUserCommand,以便执行相应的操作。但我不太确定如何做到这一点,以创建一个松耦合和灵活的设计。
#Account aggregate with Members - Account Context
class Account(AggregateRoot):
plan_id: uuid
name: str
credit: Money
total_seats = AllocatedTotal
user_limit: AllocatedUsers
members: list[Member]
def __init__(self, name: str, plan_id: uuid):
self.name = name
self.plan_id = plan_id
self.members = []
self.user_limit = AllocatedUsers(0)
self.total_seats = AllocatedTotal(0)
self.credit = Money(0)
def add_member(self, member_name: str)
pass
class Member(Entity):
name: str
role: Role
#other member related stuffs
# Plan aggregate with Package - Subscription Context
class Plan(AggregateRoot):
name: str
type: str
package: Package
class Package(ValueObject):
total_seats: AllocatedTotal
user_limit: AllocatedUsers
#command
@dataclass
class CreateAccount(Command):
account_name: str
user_name: str
plan_id: uuid
#command_handler
class CreateAccountHandler(CommandHandler):
def __init__(self, uow: AbstractUnitOfWork,
account_service: 'AccountService'):
self.uow = uow
self.account_service = account_service
def handle(self, command: SubscribeUser) -> None:
with self.uow:
self.account_service.create_account(plan_id=command.plan_id, account_name=command.account_name,
member_name=command.user_name)
self.uow.commit()
def __enter__(self):
return self
#domain_service
class AccountService(AccountServicePort):
def __init__(self, account_repository: AccountRepository,
plan_service: PlanService):
self.account_repository = account_repository
self.plan_service = plan_service
def create_account(self, plan_id: UUID, account_name: str, member_name: str) -> None:
plan = self.plan_service.get_plan_by_id(plan_id)
if not plan:
raise ValueError("Plan not found")
account = Account(name=account_name, plan_id=plan_id)
member = Member(name=member_name, role=Role.ADMIN)
account.add_member(member.id, member)
account.load_total_users(plan.package.user_limit.count)
account.total_seats(plan.package.total_seats.total)
self.account_repository.add(entity=account)
0 个回答
暂无回答