Comments (1)
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)
- Sequelize with TypeScript
- Implementing Jwt Token jsonwebtoken as AuthProvider
- No activity HOT 1
- Race condition
- AggregateRoot constructor HOT 2
- What is the difference between id & userId? HOT 1
- why it is not strict ? HOT 8
- Using the same controller for multiple requests
- Why underscore private `_domainEvents` in AggregateRoot? HOT 3
- is this code base build properly HOT 1
- Use default parameters instead of thernary operator HOT 1
- [Golang] Implement one Bounded Context using Golang HOT 2
- Remove secret keys from repo. HOT 1
- How to apply common access control rules to many routes
- Question: Should Mappers returns Result<T> signature? HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from white-label.