Git Product home page Git Product logo

Comments (1)

stemmlerjs avatar stemmlerjs commented on May 20, 2024 2

Yeah, that's definitely been something I've been tip-toeing around a little bit.

I think we should be adhering to the fail fast principle here. While it might not be perfect, I think we should explicitly throw an error here.

 public static toDomain (raw: any): User {
    const userEmailOrError = UserEmail.create(raw.user_email);
    const userPasswordOrError = UserPassword.create(raw.user_password); 
    const combinedPropsResult = Result.combine([userEmailOrError, userPasswordOrError]);
    
    if (!combinedPropsResult.success) {
       throw new Error(combinedPropsResult.message)
    }

    const userOrError = User.create({
      email: userEmailOrError.getValue(),
      password: userPasswordOrError.getValue(),
      firstName: raw.first_name,
      lastName: raw.last_name,
      isEmailVerified: raw.is_email_verified,
      username: raw.username
    }, new UniqueEntityID(raw.base_user_id))

    return userOrError.isSuccess ? userOrError.getValue() : null;
  }

I'll explain why.

In this article, I said:

Typically, we should aim to reserve try-catch blocks for operations that interact with the outside world (ie: we're not the ones throwing errors), like:

Operations against a database
Operations utilizing an external service (API, etc)

My rationale for this refactoring is because we're treating working against something volatile, like the shape of the database table, we're already mistrusting what could come back.

Here's an example of failing fast that I did in the DDDForum app.

export class MemberRepo implements IMemberRepo {
  private models: any;

  constructor (models: any) {
    this.models = models;
  }
... 
  public async getMemberIdByUserId (userId: string): Promise<MemberId> {
    const MemberModel = this.models.Member;
    const baseQuery = this.createBaseQuery();
    baseQuery.where['member_base_id'] = userId;
    const member = await MemberModel.findOne(baseQuery);
    const found = !!member === true;
    if (!found) throw new Error('Member id not found');
    return MemberIdMap.toDomain(member);
  }
}

In this example, the MemberRepo.getMemberIdByUserId will throw an error instead of returning null, because it's not helpful to return null. That means the calling code needs to know that the API could return null or it could return a MemberId.

My personal preference here is to treat anything that interacts with infrastructure as volatile and throw errors when we get undesirable behavior, and functionally handle typed errors within the application and domain layer, since it encapsulates critical business logic where the absence of a Member might actually be relevant business logic. Like:

export namespace GetMemberByUserNameErrors {

  export class MemberNotFoundError extends Result<UseCaseError> {
    constructor (username: string) {
      super(false, {
        message: `Couldn't find a member with the username ${username}`
      } as UseCaseError)
    }
  }
}

I don't think this is perfect, but it's adequate and backed by what I think is reasonable logic.

from white-label.

Related Issues (16)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.