{agregados}
La última frontera
Evolución
ValueObjects
Objetos de valor inmutables que se identifican por el contenido.
1.
2.
Entidades
Objetos que se diferencian por un identificador único. Pueden ser mutables. Suelen estar construidas mediante ValueObejcts.
3.
Agregados
Objetos que representan el modelado de nuestro dominio y sus reglas de consistencia. Pueden estar formados por varias entidades y ValueObjects
# CHAPTER 2
Value Object
class VehicleColor {
private readonly _color: string
public get value(): string {
return this._color
}
constructor(color: string) {
this._color = color.toLowerCase()
this._ensureColorIsValid()
}
private _ensureColorIsValid(): void {
if (!['red', 'white', 'black'].includes(this._color)) {
throw new Error(`El color ${color} es muy feo, escoge otro`)
}
}
}
# PRESENTING CODE
Entity
class SubscriptionContractFile {
private readonly _id: IdValueObject
private _isSigned: BooleanValueObject
private _createdAt: DateValueObject
private _signedAt: Nullable<DateValueObjec>
private _signedBy: Nullable<IdValueObject>
private readonly _category: ContractFileCategory
public get id(): string {
return this._id.value
}
static create(data: SubscriptionContractFileCreateDefinition): SubscriptionContractFile {
return new SubscriptionContractFile({
...props,
isSigned: false,
createdAt: new Date(),
signedAt: null,
signedBy: null,
})
}
constructor(data: SubscriptionContractFileDefinition) {
this._id = new IdValueObject(data.id)
this._isSigned = new BooleanValueObject(data.isSigned)
this._createdAt = new DateValueObject(data.createdAt)
this._signedAt = data.signedAt ? new DateValueObject(data.signedAt) : null
this._signedBy = data.signedBy ? new IdValueObject(data.signedBy) : null
this._category = new ContractFileCategory(data.category)
}
/**
* Mark this contract as signed if it is not already signed
**/
sign(signedBy: IdValueObject) {
if (this._isSigned.isTrue) {
return
}
this._signedBy = signedBy
this._signedAt = new DateValueObject()
}
toPrimitives(): SubscriptionContractFileDefinition {
return {
id: this._id.value,
isSigned: this._isSigned.value,
createdAt: this._createdAt.value,
signedAt: this._signedAt?.value ?? null,
signedBy: this._signedBy?.value ?? null,
category: this._category.value,
}
}
}
# PRESENTING CODE
Aggergate
class Subscription extends AggregateRoot {
private readonly _id: IdValueObject
/* ....*/
private _contracts: SubscriptionContractFile[] = []
private _isFinished: BooleanValueObject
private _isDiscarded: BooleanValueObject
constructor(data: SubscriptionContractDefinition) {
this._id = new IdValueObject(data.id)
this._contracts = data.contracts.map((c) => new SubscriptionContractFile(c))
this._isFinished = new BooleanValueObject(data.isFinished)
this._isDiscarded = new BooleanValueObject(data.isDiscarded)
}
private _ensureCandEdit() {
if (this._isFinished.isTrue) {
throw new Error(`Can't edit a finished subscription`)
}
if (this._isDiscarded.isTrue) {
throw new Error(`Can't edit a discarded subscription`)
}
}
addContract(id: string, category: string) {
this._ensureCanEdit()
this.contracts.push(SubscriptionContractFile.create({ id, category }))
}
signContract(id: string, signedBy: string) {
this._ensureCanEdit()
this.contracts.map(c => {
if (c.id === id) {
c.sign(signedBy)
}
return c
})
}
toPrimitives(): SubscriptionContractDefinition {
return {
id: this._id.value,
/* ... */
contracts: this.contracts.map((c) => c.toPrimitives()),
isFinished: this._isFinished.value,
isDiscarded: this._isDiscarded.value,
}
}
}
# PRESENTING CODE
Agregados
By Daniel Cañada García
Agregados
- 73