In order to clarify the concept, I have created this aggregate and this value object. Please note that my value object currently does not have any validations implemented.
Aggregate:
export class Person extends Entity<{name: PersonName}> {
private constructor(name: PersonName, id?: string) {
super({name}, id)
}
public static build(
name: PersonName, id: string
): Either<IErrorModel[], Person> {
const person = new Person(name, id)
return right(person)
}
}
Value-Object:
export class PersonName extends ValueObject<IName> {
public static maxLength: number = 30;
public static minLength: number = 4;
private constructor(props: IName) {
super(props)
}
public get fullName(): string {
return `${this.props.firstName} ${this.props.lastName}`
}
public get firstName(): string {
return this.props.firstName
}
public get lastName(): string{
return this.props.lastName
}
public static build(props: IName): Either<IErrorModel[], PersonName> {
const name = new PersonName(props)
return right(name)
}
}
I am unsure about where to create my factory in my aggregate. For example, should I create and validate my value object "Name" within the factory of my aggregate, or should I do it elsewhere?
Below is an example of how it could be done in the aggregate factory:
export class Person extends Entity<{ name: PersonName }> {
private constructor(name: PersonName, id?: string) {
super({ name }, id)
}
public static build(
{ lastName, firstName }: { firstName: string; lastName: string },
id: string,
): Either<IErrorModel[], Person> {
let errors = [] as IErrorModel[]
// other validations
const name = PersonName.build({lastName,firstName})
if(name.isLeft()) errors.push(...name.value)
const person = new Person(name.value as PersonName, id)
return right(person)
}
}
Alternatively, it could also be done in the person service like so:
Aggregate Factory:
public static build(
name: PersonName, id: string
): Either<IErrorModel[], Person> {
const person = new Person(name, id)
return right(person)
}
Service:
export class PersonService{
execute(req: any) {
let errors = [] as IErrorModel[]
const {lastName, firstName} = req
const name = PersonName.build({lastName,firstName})
if(name.isLeft()) errors.push(...name.value)
const person = Person.build(name.value as PersonName, v4())
}
}
My question remains: Should I create my value objects within the aggregate factory, or is there a better approach?