Replies: 1 comment 3 replies
-
Yes, errors as "privileged" DTOs make sense. I used this approach in production for some time (returning errors everywhere instead of throwing). It sounds great in theory, but in practice has serious downsides. Here is what I've learned: Languages like TypeScript (and Java, in your case), don't have native support for this. Meaning that:
async handle(event: UserCreatedDomainEvent): Promise<any> {
const wallet = WalletEntity.create({
userId: event.aggregateId,
});
await this.walletRepo.insert(wallet);
} If this method throws an exception, you will see it in your logs. But if this is a Result object returned, and you forgot to do something with it (at least unwrap it), the error will be invisible, it just won't show up in your logs because it's not handled. Your compiler/IDE won't tell you that you have to assign it to a variable and do something with it. You may spend days fixing this because you won't know where the error is. I've seen this a lot in production. People forget that they need to handle the error, probably because they are too used to exceptions that log the error regardless, or they let the exception propagate and be handled up the stack. Or they just lack discipline to handle this kind of errors properly. I've spent weeks fixing invisible errors like these just because people ignore them and do not handle/unwrap results, hoping it will be propagated and handled by your framework like a regular exception (especially new devs) and language does not do anything to warn you about it.
const user = await this.repo.findUser(userId);
if (user.isErr) {
return new UserNotFoundError();
} The snippet of code above is what I've seen a lot in production apps. Because 99% of the errors in findUser(userId: string): Result<User, NotFoundError>; Indicating that
In Java you at least have checked exceptions that give you some guarantees and IDE support to prevent issues described above, but with Result objects / Either monads you lose it all and open endless possibilities to shoot yourself in the foot. For these reasons I stopped using In conclusion: be careful when using monads to return your errors in languages that don't support it natively, you may shoot your self in the foot in the long run. |
Beta Was this translation helpful? Give feedback.
-
In software architecture, Data Flow refers to the way in which data is passed between the different components or layers of the software architecture. It defines how data is transformed, stored, and accessed. Brought to the scope of the Hexagonal Architecture (HexArch), these flows can be managed and controlled in a more efficient and explicit way. HexArch's approach of separating the core business logic and data flow from external systems allows for clear boundaries and interfaces between different components, making it easier to understand and manage the different flows within the system.
Using a Data Transfer Object (DTO) to hand data over to the outer layers is generally recommended, thus bringing back the benefits of clear separation of concerns, loose coupling, and more flexibility and testability. That means that we must choose upfront from one of the different strategies to map data between boundaries based on the affordable level of acceptance with respect to coupling; mainly I see three:
Needless to say, the 3rd strategy is the preferred one in terms of coupling.
Accordingly, I was wondering if Error Values (when we don't want to work with Exceptions to control our flow) can be considered DTOs in the sense that:
However, whilst Error Values seem to have the same responsibilities as DTOs, they differ in terms of the origin of their definition:
If all this reasoning makes sense, then that's why I consider them "privileged" DTOs and I was wondering what your take is on this matter.
Notice that I intentionally want to avoid throwing Exceptions (I may be ok with using Exceptions as Error Values, though) to drive the flow of my application and instead, I want to use monadic types such as Try, Either, or Validation from vavr.io (for me in Java).
Beta Was this translation helpful? Give feedback.
All reactions