-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add OnSuccess
and OnFailure
fluent extensions
#12
base: master
Are you sure you want to change the base?
Conversation
Hey @GoodeUser, thanks for the contribution and the kind words! Async support is indeed something that is not well handled by Outcomes currently and I would love to fill that hole. It touches on another issue... I've been playing with a bunch of approaches for cleaner handling of some common patterns. I sometimes end up with a lot of code like:
It's a net win because you can roll up messages in useful ways, but the code feels a little verbose. I would love something like, perhaps as an optional additional package:
Curious if you also run into that situation, and if so, how you feel about it? I'm currently thinking the semantics you're using are on the right track, but if I do something like that, I want to try and address these other issues at the same time. I will check your code out in more detail early this week. So far I've only looked at your actual message, and I skimmed enough to see that you added some unit tests, etc, which is great. |
Yes, the kind of code where I find myself writing those chained It's pretty much always one-sided though. I either want to make sure all operations are successful (probably the most common scenario) or I want to continue through failure cases until I get to a successful one. These extension methods let me do precisely that. For the scenario where you want to continue on ensuring all the operations are successful and want to stop at the first failure(like some validation on a field, verifying that a user is active, etc.): return doStep1()
.OnSuccess((step1Value) => doStep2(step1Value))
.OnSuccess((step2Value) => doStep3(step2Value)); OR more concisely: return doStep1()
.OnSuccess(doStep2)
.OnSuccess(doStep3); There is also the scenario where you want to find an operation that is successful (such as API validation where you have different methods and want to get to the first working one to prove that a user can access a resource). return TryBasicTokenAuth(httpContext)
.OnFailure(() => TrySecretKeyAuth(httpContext))
.OnFailure(() => TryPostBodyAuth(httpContext))
.OnFailure(() => TrySecretQueryStringParam(httpContext)); I also program in F# and when I'm in F# land I can use the Feel free to check out the code and let me know what you think. I love feedback and would be more than happy to make any changes you'd like done here. |
Was buried today, but I wanted to check in and say that I really like your thoughts on this. I want to make sure the common cases I'm aware of are handled and see what they will look like... Maybe look at a few slight variations on word choice and see how they feel, to be diligent. There's also a situation where if anything fails, I want to get access to the failure outcome and maybe have a chance to format it, but I also don't want to create an overly complicated API, so that might be best handled outside of this... Requires a little thought with a clearer mind than I have right now, at 2am. :) There's another semi-related pattern that comes up sometimes, especially in validation scenarios, where you want to roll up a bunch of messages, like this:
Curious if you ever run into this one? |
I have run into that one a few times actually but never noticed the pattern there. Interesting. Yeah, I've used this pattern to validate user input before running it through some sort of business logic. The code sample you wrote with I'm super interested to see what you come up with and am more than happy to help so let me know if there is anything you'd like me to help implement. |
Still haven't forgotten about this. I had a huge release at Roster and then I needed to recover a little. I'm going to try and dive into this next week. |
@GoodeUser It has been a long time, and all I can say is that Covid was rough. Do you still have any interest in working on this? |
These extension methods let you chain Outcomes together in a fluent manner. For example:
The fact that they are extension methods and not a part of the
IOutcome
interface lets you work withTask<IOutcome>
much like you wouldIOutcome
which really simplifies the interface for doing async validations. I'm very curious on your thoughts for these - do you think they belong here/would benefit the users of this package?P.S. Thanks for this library. I use this library in practically all of my projects (along with my extension methods of course). It's a great way to encapsulate the logic for some computation to fail.