{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
Made with Slides.com