FluentResults in the Domain layer
Hi everyone, in the API I am currently trying to develop with Clean Architecture, I would like to use FluentResults library to avoid throwing and processing exceptions in situations where errors are not unexpected. So in this case it seems reasonable to also have custom Errors defined in the Domain layer. In this case, there is an issue that in order to use FluentResults throughout the whole application, it will require to add this package to the Domain layer also which is considered a bad practice since we want to make independent of any other packages and self-sufficient. In this case, I see only the option to create some custom Result and Error types, create specific Errors and then map them to the FluentResults types in the upper layers, but this approach seems to add a lot of unnecessary complexity.
So in this case is it a valid approach to just add the package to the Domain layer or is it rather really better not to do that? And maybe there are better options to handle this situation? Using custom Result and Errors in other layers too to resolve this seems like avoiding the final choice because I can't see any proper reasons of using custom types when there is a well tested library for it.
Thank you for answering.
11 Replies
Sounds like your problem stems from CA, are you free to choose the architecture of this project?
If so, maybe give $vsa a try
why would Domain need this library, tho
FluentResult should be something services keep between themselves
errors would not be part of domain/model
It's kinda of my desire in order it more properly since it is highly required in the job descriptions. Also, it seems that it is kind of a standard nowadays.
As per my understanding, Domain layer has to signal somehow that business rules are not followed and this validation logic should be encapsulated inside this layer. So it is either throwing exceptions or returning Results objects. And I really seem to prefer the second approach in this case and this leads me to a problem with either custom implementation or depdning on the package for consistency throughout the whole solution and avoiding additional complexity.
Package references are transient, so any layer depending on your domain layer will of course also depend on your result types.
Personally, I use result types also (lots of custom ones, too), albeit without 3rd party libraries. I associate them to the service/operation that produces them; general result types usually land in
Common
.
What is the specific functionality you require from FluentResults?I have already used my custom simpler implementations of this and it worked. So theoretically there is no issue at all since there is no issue at this point. But I just started a new project and I knew about a pretty popular library and wanted to use it since it just seems that it is more preferable to use well-tested library with a lot of functionality rather than recreating the wheel. And since for sure this library is used with Clean Architecture in some production environments, I am curious how people usually do that.
I also found now such thing as raising Domain Events and handing them with MediatR which seems like a potential solution in this case, but I am not sure yet.
At this point, as I see, Domain Events will require either custom handlers in the Application layer, or wrappers, or Domain layer dependency on MediatR so it's kind of the same situation.
Don't overcomplicate simple things.
KISS is a good friend you should seek.
The way I see it, FluentResults is a cross-cutting dependency so having it referenced where needed is preferable to whatever complicated solution might remedy this apparent "problem".
if there really are some reused result types (and there is an isolation between data model and objects used for interaction between services) then i would make a specific namespace for it, but since these tends to be pretty custom i would pay attention to not reused these types too much (to the point it can be a hindrance to developing new behaviors because of inheritance)
@SleepWellPupper @ffmpeg -i me -f null - Ok, I think I got the idea, Huge thank you for your advices.
If you're interested, I use a source generator so I don't have any external runtime dependencies for my projects. But that SG doesn't generate the FluentResults API, only union types so it might not exactly fit your need.
Thanks, I'll give it a look.