当前位置: 首页 > 后端技术 > PHP

剖析微聚合——事件追踪

时间:2023-03-30 02:20:46 PHP

本文转载自【WhyDecoupling】:https://codedecoupled.com/php...聚合是DDD(领域驱动设计)中一个比较复杂的概念。作为DDD战术设计中举足轻重的工具,我们很有必要去了解它。一般来说,聚合(Aggregate)是指一组密切相关的类,它们自己形成一个有界的组织。边界外的对象只能通过AggregateRoot与这个聚合交互:聚合经常和泛型集合混淆交互,它们的区别在于聚合是相对于领域模型而言的,而集合是一个广义的概念。那么具体来说,除了聚合根之外,聚合内部还有哪些类呢?本文描述了事件源架构中常见的几个重要组件(类)。Entities实体是独立事物的建模工具,每个实体都有一个唯一的标识,比如ID、UUID、Username等。在大多数情况下,实体是可变的,它们的状态会随着时间而改变。实体很容易理解。如果我们用DDD来分析ORM业务,那么ORM中的Model可以理解为实体。数据库中的每条数据都有自己的ID(唯一标识符),每条数据的内容也是易变的。使用实体对用户建模:classUserextendsModel{privateint$id;公共函数__construct(int$id){$this->id=$id;}publicfunctionchangePassword(string$password){//域代码}}$user=newUser(1);$user->changePassword();ValueObjectValueObject是用于描述、量化或度量领域中实体的模型。与实体不同,值对象没有唯一标识符,两个等价的值对象是可以互换的。值对象具有不变性(Immutability)。一旦创建,值对象的属性就确定了并且不能更改。值对象是一种功能强大但经常被忽视的建模工具。使用值对象建模可以大大简化我们的代码。下面分析一下值对象的几个特点。无标识符的值对象不能有ID、UUID等标识符。不变性值对象初始化后,其值不能更改。我们在对值对象进行建模时需要特别注意。不应赋予值对象更改其内部属性的能力。如果需要变异方法,则此方法必须创建一个全新的值对象(请参阅下面的Money::add())。金钱类{privateint$amountInCent;私有字符串$currency;公共函数__construct(int$amountInCent,string$currency){$this->amountInCent=$amountInCent;$this->currency=$currency;}publicfunctiongetAmountInCent():int{return$this->amountInCent;}publicfunctiongetCurrency():string{return$this->currency;}publicfunctionadd(Money$money):Money{if($this->currency!==$this->getCurrency()){thrownew\Exception('你不能添加两种不同的货币');}returnnewMoney($this->amountInCent+$money->getAmountInCent(),$this->currency);}}可替换性值对象的不变性为其可替换性奠定了基础。如果两个值对象的值相等,我们就可以放心地替换两个值对象。我们可以这样理解这个概念:如果A有一张10元人民币纸币,B也有一张10元人民币纸币,他们可以进行点对点交换,不会引起利益纠纷。领域中的许多模型都可以使用值对象来建模,它的特性为我们提供了一个安全灵活的环境来管理我们的代码。例如,上一节中的$password可以使用值对象来完成。类密码{私有字符串$value;公共函数__construct(string$value){$this->guard($value);$this->value=$value;}publicfunctiontoString(){return$this->value;}privatefunctionguard($value){if(empty($value)){thrownew/Exception('无效密码值');}}}$user=newUser(1);$password=newPassword($passwordStr);$user->changePassword($password);初始化成功后的$password一定是有效的,因为我们在初始化的时候做了防御。值对象为我们提供了一个安全的模型,我们在后面的代码中不用担心$password是否满足业务需求。聚合根的本质是一个实体,或者聚合根是一个特殊的实体。聚合根的特殊性体现在它在聚合中的位置,是聚合的唯一对外接口。如果我们把聚合看成是户口簿,那么聚合根就好比是户主,对户口簿的任何操作都需要经过户主。领域事件领域事件是与领域内的业务密切相关的业务事件。它们与基础设施和代码框架无关,因此领域事件不应该是非常广泛的框架事件,例如EmailSent和RecordUpdated。域事件在聚合根中生成,然后存储和持久化。领域事件持久化是保证所有领域事件正确性的最后一步。如有异常,领域事件不会被错误保存。总结在事件源架构中,一个聚合必须由一个聚合根和一个或多个上述组件组成。本文转载自【WhyDecoupled】:https://codedecoupled.com/php...,如果你也对TDD、DDD和简洁代码感兴趣,请关注公众号【WhyDecoupled】,一起探讨一起软件开发的方式。