-
Notifications
You must be signed in to change notification settings - Fork 76
Align SharedKernel with CleanArchitecture's Result Pattern #12
Copy link
Copy link
Open
Description
Hi @ardalis,
I've created a PR #13 that introduces the Ardalis.Result into the ICommand and IQuery interfaces directly in Ardalis.SharedKernel. The goal is to provide a standardized way to handle operation using Result Pattern in CQRS-based workflows, improving consistency and readability. I have already implemented this approach in several SharedKernel projects.
Why This Change?
- Since
Ardalis.SharedKernelis meant to serve as a reference implementation (copied/modified rather than used directly), it should demonstrate best practices. The Result pattern is widely adopted for clear error handling and richer return types. - As seen in the CleanArchitecture repo, handlers often return
Result<T>. By baking this into theICommand/IQueryinterfaces, we:- Eliminate repetitive
Result<YourType>declarations. - Make the intent immediately clear in derived handlers.
- Encourage consistent error handling.
- Eliminate repetitive
Drawbacks
- Had to remove the
outkeyword fromICommandwhich was originally added for covariant purposes. I attempted to modifyArdalis.Resultto includeIResult<out T>interface, but that didn't work well - if implemented, it would requireIResult<T>to be used consistently across all extension methods in additional packages.However, this change would allow automatic casting to base types, providing a potential benefit. - Currently, developers are forced to use .Map() or .Bind() extension methods, if I'm not mistaken.public interface IResult<out T> : IResult { T Value { get; } }
- Had to introduce the
ICommandwith no return type (only theResult), andICommand<T>which allow you to return value wrapped withResult. Personally, I don't like the idea to return more than created entity Id or domain concept struct, so I have another suggestion to consider. The idea is to have 2 different types of commands: those that return created entity identification information and empty one, returning only the result information:public interface ICommand : IRequest<Result>; // TId should be the strongly typed domain concepts // representing the ID of the entity, so it needs to have constraints public interface ICreatedCommand<TId> : IRequest<Result<TId>> where TId : struct, IComparable, IComparable<TId>, IConvertible, IEquatable<TId>, IFormattable;
Things To Discuss
- Does this align with the library's direction?
- Do you think if is worth to consider alternative approaches for covariance using
IResult<out T>and what are the main drawback in this approach? - Do you think the approach with the separate
ICreatedCommand<TId>andICommandcan be discussed further and added as an example of more "clear" CQRS pattern?
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels