Skip to content

Commit 71c2e25

Browse files
author
Brian
committed
Continued to refine the API based on real-world usage.
- <experimental> Added IOutcome.Failure as an alternate and perhaps more expressive way to say If(!outcome.Success) - Removed a few method signatures that just seem to generate ugly code. There are better ways. - Added the ability for a failure to have a value. Turns out it happens sometimes. - Added some methods for rolling up outcomes that only appeared on failures previously. Sometimes you need them for successes too.
1 parent 9255423 commit 71c2e25

10 files changed

+268
-97
lines changed

Outcomes.Tests/Ether.Outcomes.Tests.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@
5252
</Choose>
5353
<ItemGroup>
5454
<Compile Include="FailureTests.cs" />
55-
<Compile Include="FailureFormatTests.cs" />
5655
<Compile Include="Helpers\StatusCodes.cs" />
5756
<Compile Include="SuccessFormatTests.cs" />
5857
<Compile Include="MultiLineFormatterTests.cs" />

Outcomes.Tests/FailureFormatTests.cs

Lines changed: 0 additions & 45 deletions
This file was deleted.

Outcomes.Tests/FailureTests.cs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,11 @@ public void Failure_FromException_Works()
6969
{
7070
var exception = new InvalidOperationException("test message");
7171

72-
var outcome = Outcomes.Failure().FromException(exception, "prefix message");
72+
var outcome = Outcomes.Failure().FromException(exception);
7373

7474
Assert.IsFalse(outcome.Success);
75-
Assert.IsTrue(outcome.Messages.Count == 2);
76-
Assert.IsTrue(outcome.ToMultiLine("<br>") == "prefix message<br>Exception: test message<br>");
75+
Assert.IsTrue(outcome.Messages.Count == 1);
76+
Assert.IsTrue(outcome.ToMultiLine("<br>") == "Exception: test message<br>");
7777
}
7878

7979

@@ -90,19 +90,6 @@ public void Failure_FromException_Chaining_Works()
9090
Assert.IsTrue(outcome.ToMultiLine("<br>") == "prefix<br>Exception: test<br>suffix<br>");
9191
}
9292

93-
94-
[TestMethod]
95-
public void Failure_FromOutcome_Works()
96-
{
97-
var previousOutcome = Outcomes.Failure().WithMessage("test");
98-
99-
var outcome = Outcomes.Failure().FromOutcome(previousOutcome, "prefix");
100-
101-
Assert.IsFalse(outcome.Success);
102-
Assert.IsTrue(outcome.Messages.Count == 2);
103-
Assert.IsTrue(outcome.ToMultiLine("<br>") == "prefix<br>test<br>");
104-
}
105-
10693
[TestMethod]
10794
public void Failure_FromOutcome_Chaining_Works()
10895
{
@@ -149,6 +136,19 @@ public void Failure_StatusCode_WithStatusCode_Works()
149136
.WithStatusCode(200);
150137

151138
Assert.IsTrue(outcome.StatusCode == 200);
152-
}
139+
}
140+
141+
[TestMethod]
142+
public void Failure_WithValue_Works()
143+
{
144+
var outcome = Outcomes.Failure<Decimal>()
145+
.WithValue(23123.32M);
146+
147+
Assert.IsTrue(!outcome.Success);
148+
Assert.IsTrue(outcome.Messages.Count == 0);
149+
Assert.IsTrue(outcome.Value == 23123.32M);
150+
Assert.IsTrue(outcome.ToString() == string.Empty);
151+
Assert.IsTrue(outcome.ToMultiLine("<br>") == string.Empty);
152+
}
153153
}
154154
}

Outcomes.sln

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ether.Outcomes", "Outcomes\
77
EndProject
88
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ether.Outcomes.Tests", "Outcomes.Tests\Ether.Outcomes.Tests.csproj", "{08B07FB9-E8D7-4F4E-B5A1-9E6D98738998}"
99
EndProject
10+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{34E8307F-3A0B-4148-9CA4-88B999A9C8F0}"
11+
ProjectSection(SolutionItems) = preProject
12+
WebEssentials-Settings.json = WebEssentials-Settings.json
13+
EndProjectSection
14+
EndProject
1015
Global
1116
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1217
Debug|Any CPU = Debug|Any CPU

Outcomes/Builder/FailureOutcomeBuilder.cs

Lines changed: 16 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,8 @@ internal FailureOutcomeBuilder(bool success) : base(success)
1616
/// Adds messages from the specified exception. Internally, Outcome.Net calls exception.Message to generate the messages.
1717
/// </summary>
1818
/// <param name="exception">Exception used to generate the message.</param>
19-
/// <param name="message">Optional message that will appear after the exception's messages.</param>
20-
/// <param name="paramList">Shorthand for String.Format</param>
21-
public IFailureOutcomeBuilder<TValue> FromException(Exception exception, string message = null, params object[] paramList)
19+
public IFailureOutcomeBuilder<TValue> FromException(Exception exception)
2220
{
23-
if (message != null)
24-
{
25-
message = string.Format(message, paramList);
26-
Messages.Add(message);
27-
}
28-
2921
base.Messages.Add("Exception: " + exception.Message);
3022
return this;
3123
}
@@ -34,17 +26,9 @@ public IFailureOutcomeBuilder<TValue> FromException(Exception exception, string
3426
/// Adds messages from the specified outcome.
3527
/// </summary>
3628
/// <param name="outcome">Source outcome that messages are pulled from. If there are no messages, execution continues.</param>
37-
/// <param name="message">Optional message that will appear after the specified outcome's messages.</param>
38-
/// <param name="paramList">Shorthand for String.Format</param>
39-
public IFailureOutcomeBuilder<TValue> FromOutcome(IOutcome outcome, string message = null, params object[] paramList)
29+
public new IFailureOutcomeBuilder<TValue> FromOutcome(IOutcome outcome)
4030
{
41-
if (message != null)
42-
{
43-
message = string.Format(message, paramList);
44-
Messages.Add(message);
45-
}
46-
47-
base.WithMessage(outcome.Messages);
31+
base.FromOutcome(outcome);
4832
return this;
4933
}
5034

@@ -72,18 +56,16 @@ public IFailureOutcomeBuilder<TValue> FromOutcome(IOutcome outcome, string messa
7256
/// Alternate syntax for FromOutcome. Adds messages from the specified outcome, if any.
7357
/// </summary>
7458
/// <param name="outcome">Source outcome that messages are pulled from.</param>
75-
/// <param name="message">Optional message that will appear after the specified outcome's messages.</param>
76-
/// <param name="paramList">Shorthand for String.Format</param>
77-
public IFailureOutcomeBuilder<TValue> WithMessagesFrom(IOutcome outcome, string message = null, params object[] paramList)
59+
public new IFailureOutcomeBuilder<TValue> WithMessagesFrom(IOutcome outcome)
7860
{
79-
FromOutcome(outcome, message, paramList);
61+
base.FromOutcome(outcome);
8062
return this;
8163
}
8264

8365
/// <summary>
8466
/// Alternate syntax for WithMessage. Adds a collection of messages to the end of the outcome's message list.
8567
/// </summary>
86-
public IFailureOutcomeBuilder<TValue> WithMessagesFrom(IEnumerable<string> messages)
68+
public new IFailureOutcomeBuilder<TValue> WithMessagesFrom(IEnumerable<string> messages)
8769
{
8870
base.WithMessage(messages);
8971
return this;
@@ -94,5 +76,15 @@ public IFailureOutcomeBuilder<TValue> WithMessagesFrom(IEnumerable<string> messa
9476
base.WithStatusCode(statusCode);
9577
return this;
9678
}
79+
80+
/// <summary>
81+
/// Sets the value for a failure outcome. The outcome object is just a wrapper for the value.
82+
/// </summary>
83+
/// <param name="value">Specifies the value to wrap.</param>
84+
public new IFailureOutcomeBuilder<TValue> WithValue(TValue value)
85+
{
86+
base.WithValue(value);
87+
return this;
88+
}
9789
}
9890
}

Outcomes/Builder/IFailureOutcomeBuilder.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,16 @@ public interface IFailureOutcomeBuilder<TValue> : IOutcome<TValue>
99
/// Adds an exception's message to the outcome's message collection.
1010
/// </summary>
1111
/// <param name="exception">The exception to record.</param>
12-
/// <param name="message">Optional note that will show up before the exception's message.</param>
13-
/// <param name="paramList">Shorthand for String.Format</param>
1412
/// <returns></returns>
15-
IFailureOutcomeBuilder<TValue> FromException(Exception exception, string message = null, params object[] paramList);
13+
IFailureOutcomeBuilder<TValue> FromException(Exception exception);
1614

1715
/// <summary>
1816
/// Add an outcome's message to the message list.
1917
/// Useful for unwinding deep calls where several methods have something to add about the failure.
2018
/// </summary>
2119
/// <param name="outcome">A failure outcome.</param>
22-
/// <param name="message">Optional message to add before the source outcome's message.</param>
23-
/// <param name="paramList">Shorthand for String.Format</param>
2420
/// <returns></returns>
25-
IFailureOutcomeBuilder<TValue> FromOutcome(IOutcome outcome, string message = null, params object[] paramList);
21+
IFailureOutcomeBuilder<TValue> FromOutcome(IOutcome outcome);
2622

2723
/// <summary>
2824
/// Add a string to the end of the outcome's message collection.
@@ -43,15 +39,19 @@ public interface IFailureOutcomeBuilder<TValue> : IOutcome<TValue>
4339
/// Alternate syntax for FromOutcome. Adds messages from the specified outcome (if any).
4440
/// </summary>
4541
/// <param name="outcome">Source outcome that messages are pulled from.</param>
46-
/// <param name="message">Optional message that will appear after the specified outcome's messages.</param>
47-
/// <param name="paramList">Shorthand for String.Format</param>
48-
IFailureOutcomeBuilder<TValue> WithMessagesFrom(IOutcome outcome, string message = null, params object[] paramList);
42+
IFailureOutcomeBuilder<TValue> WithMessagesFrom(IOutcome outcome);
4943

5044
/// <summary>
5145
/// Alternate syntax for WithMessage. Adds messages to the end of the message collection.
5246
/// </summary>
5347
IFailureOutcomeBuilder<TValue> WithMessagesFrom(IEnumerable<string> messages);
5448

5549
IFailureOutcomeBuilder<TValue> WithStatusCode(int? statusCode);
50+
51+
/// <summary>
52+
/// Sets the value for a failure outcome. The outcome object is just a wrapper for the value.
53+
/// </summary>
54+
/// <param name="value">Specifies the value to wrap.</param>
55+
IFailureOutcomeBuilder<TValue> WithValue(TValue value);
5656
}
5757
}

Outcomes/Builder/SuccessOutcomeBuilder.cs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,25 @@ public SuccessOutcomeBuilder<TValue> WithMessage(IEnumerable<string> messages)
4242
return this;
4343
}
4444

45+
/// <summary>
46+
/// Alternate syntax for FromOutcome. Adds messages from the specified outcome, if any.
47+
/// </summary>
48+
/// <param name="outcome">Source outcome that messages are pulled from.</param>
49+
public SuccessOutcomeBuilder<TValue> WithMessagesFrom(IOutcome outcome)
50+
{
51+
FromOutcome(outcome);
52+
return this;
53+
}
54+
55+
/// <summary>
56+
/// Alternate syntax for WithMessage. Adds a collection of messages to the end of the outcome's message list.
57+
/// </summary>
58+
public SuccessOutcomeBuilder<TValue> WithMessagesFrom(IEnumerable<string> messages)
59+
{
60+
WithMessage(messages);
61+
return this;
62+
}
63+
4564
/// <summary>
4665
/// Sets the value for a success outcome. The outcome object is just a wrapper for the value.
4766
/// </summary>
@@ -54,12 +73,23 @@ public SuccessOutcomeBuilder<TValue> WithValue(TValue value)
5473
}
5574

5675
/// <summary>
57-
/// (optional) Sets the StatusCode, which is an additional piece of metadata you can use for your own purposes.
76+
/// (optional) Sets the StatusCode, which is an additional piece of metadata you can use for your own purposes.
77+
/// This is handy when there could be, for instance, multiple failure modes.
5878
/// </summary>
5979
public SuccessOutcomeBuilder<TValue> WithStatusCode(int? statusCode)
6080
{
6181
base.StatusCode = statusCode;
6282
return this;
6383
}
84+
85+
/// <summary>
86+
/// Adds messages from the specified outcome.
87+
/// </summary>
88+
/// <param name="outcome">Source outcome that messages are pulled from. If there are no messages, execution continues.</param>
89+
public SuccessOutcomeBuilder<TValue> FromOutcome(IOutcome outcome)
90+
{
91+
WithMessage(outcome.Messages);
92+
return this;
93+
}
6494
}
6595
}

Outcomes/IOutcome.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ public interface IOutcome
1111
{
1212
int? StatusCode { get; }
1313
bool Success { get; }
14+
bool Failure { get; }
1415
List<string> Messages { get; }
1516
string ToMultiLine(string delimiter = null);
1617
string ToString();

Outcomes/OutcomeResult.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,10 @@ public string ToMultiLine(string delimiter = null)
4545
{
4646
return MultiLineFormatter.ToMultiLine(delimiter, Messages);
4747
}
48+
49+
public bool Failure
50+
{
51+
get { return !Success; }
52+
}
4853
}
4954
}

0 commit comments

Comments
 (0)