0

I am writing my first application using DDD (in Node with TS) and I started writing all the domain first -- before starting the repositories/DB and then the application, while writing unit tests for each entity. As my domain developed, I started to have more doubts about my business logic. I'll give examples below.

One of my business logic states that a "requester" can create and delete tags. So, becuase I am writing all the domain first, I created a method createSectorTag inside my Requester entity. The method is defined below as follows:

  public createSectorTag(data: ISectorTagData): number {
    this.checkIfIsActive()
    const sector_tag = new SectorTag(data)
    return this.sector_tags.push(sector_tag)
  }

As you can see, the method creates a SectorTag entity and adds it to a private array in my Requester entity. Since there's a bit of logic in this method, the this.checkIfIsActive(), I think it makes sense for this piece of code exist inside my domain. But, at the same time, I think if it isn't too much work for a simple thing: I mean, every time my application calls my domain for a requester to add a tag, it'll have to create a Requester entity, and then add it to requester.sector_tags; and after, I'll have to get the new SectorTag and persist it to the DB with a repository.

Another example is the deleteSectorTag method. This action has a logic that should validate if any of the request inside a requester have that tag, and if any has, an exception should be raised. The method's definition:

  public deleteSectorTag(index: number): void {
    /**
     * Here I'll have to check if any of the requests inside the Request entity have
     * the tag specified by the index in the parameter, and if so, raise an exception
     */
    this.sector_tags.splice(index, 1)
  }

But again, I believe that all this business logic adds a bit too much weight on processing. I'll have to get all the requests of a requester from the DB, create a Requester entity, add the requests inside the entity and then make the validation. But it all seems like it could be a query in the DB for the validation.

Well, I really like the idea of putting all logic inside the domain; it makes me happy because it seems like my code gets closer and closer to reallity. It adapts to the way I think, but at the same time I am worried about performance.

If anyone can give me hints on this, I'd be very thankful.

Here is the full Requester entity:

import { BudgetRequest, SectorTag, BudgetEstimator } from '@/domain/BudgetRequest/entities'
import { RequesterIsInactiveError } from '@/domain/BudgetRequest/exceptions'
import {
  IBudgetRequestData,
  IRequesterData,
  ISectorTagData,
} from '@/domain/BudgetRequest/interfaces'

export class Requester {
  private readonly active: boolean
  private readonly name: string
  private readonly cnpj: number
  private budget_requests: Array<BudgetRequest> = []
  private sector_tags: Array<SectorTag> = []
  private budget_estimators: Array<BudgetEstimator> = []

  constructor(data: IRequesterData) {
    this.active = data.active
    this.name = data.name
    this.cnpj = data.cnpj
  }

  get budgets_list(): Array<BudgetRequest> {
    return [...this.budget_requests]
  }

  get sector_tags_list(): Array<SectorTag> {
    return [...this.sector_tags]
  }

  public createBudgetRequest(data: IBudgetRequestData): number {
    this.checkIfIsActive()
    const budget_request: BudgetRequest = new BudgetRequest(data)

    return this.budget_requests.push(budget_request)
  }

  public createSectorTag(data: ISectorTagData): number {
    this.checkIfIsActive()
    const sector_tag = new SectorTag(data)
    return this.sector_tags.push(sector_tag)
  }

  public deleteSectorTag(index: number): void {
    /**
     * Here
     */
    this.sector_tags.splice(index, 1)
  }

  public bindSectorTagToBudgetRequest(i: number, j: number): void {
    this.budget_requests[i].addSectorTag(this.sector_tags[j])
  }

  private checkIfIsActive(): void {
    if (!this.active) {
      throw new RequesterIsInactiveError()
    }
  }
}

2
  • 3
    My best advice about performance concerns is to measure a problem first before worrying about performance. Commented Nov 15, 2023 at 18:40
  • 1
    And not just measure a difference. Is the difference in performance big enough to justify a change in the design of your codebase? Even if you decide a different design is justified, we cannot provide any general concrete advice. Commented Nov 15, 2023 at 18:43

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.