-
-
Notifications
You must be signed in to change notification settings - Fork 541
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
Improve formatting of multidimensional arrays (#991) #1044
Improve formatting of multidimensional arrays (#991) #1044
Conversation
DmitriyMaksimov
commented
May 13, 2019
- Implemented formatting of multidimensional arrays (MultidimensionalArrayFormatter)
- Added unit test for the formatter
- Supported formatting of multidimensional arrays with bounds
- Supported formatting of n-ary dimensional arrays
Test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the work you've done. IMHO, it needs a bit of cleaning. I hope you're willing to spend a bit more time on this.
|
||
var indecies = Enumerable.Range(0, arr.Rank).Select(dimention => arr.GetLowerBound(dimention)).ToArray(); | ||
|
||
bool IsFirstIteration(int index, int dimention) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't use local functions. This method is already extremely long and quite difficult to follow.
{ | ||
var arr = (Array)value; | ||
|
||
if (arr.Length <= 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this ever be negative?
} | ||
|
||
/// <inheritdoc /> | ||
public string Format(object value, FormattingContext context, FormatChild formatChild) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any chance you can break it down into smaller methods so that the algorithm is more clearer?
Tests/Shared.Specs/FormatterSpecs.cs
Outdated
result.Should().Match("{{{'1-5-7', '1-5-8', '1-5-9', '1-5-10'}, {'1-6-7', '1-6-8', '1-6-9', '1-6-10'}, {'1-7-7', '1-7-8', '1-7-9', '1-7-10'}}, {{'2-5-7', '2-5-8', '2-5-9', '2-5-10'}, {'2-6-7', '2-6-8', '2-6-9', '2-6-10'}, {'2-7-7', '2-7-8', '2-7-9', '2-7-10'}}}".Replace("'", "\"")); | ||
} | ||
|
||
public static IEnumerable<object[]> MultiDimentionalArrayData => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please put this directly below the test method that needs it.
Tests/Shared.Specs/FormatterSpecs.cs
Outdated
@@ -748,6 +748,65 @@ public void When_formatting_a_completion_source_it_should_include_the_underlying | |||
result.Should().Match("*TaskCompletionSource*Task*System.Int32*Status=WaitingForActivation*"); | |||
} | |||
|
|||
[Theory] | |||
[MemberData(nameof(MultiDimentionalArrayData))] | |||
public void When_formatting_a_multi_dimentional_array_it_should_show_structure(object value, string expected) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please move these into a dedicated specs class? Most of what's here is pretty old and still needs to be split.
* Unit tests moved into a dedicated specs class * MemberData moved directly below the test method that needs it * Use private methods instead of local functions
@dennisdoomen Thanks for your code review! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The implemented algorithm and tests looks good to me.
I especially liked that you cover the case, where the array does not start at index 0.
I've given some comments which I think could help making the intent of the algorithm more clear.
|
||
var sb = new StringBuilder(); | ||
|
||
var indecies = Enumerable.Range(0, arr.Rank).Select(dimention => arr.GetLowerBound(dimention)).ToArray(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about dimensionIndices
?
|
||
var sb = new StringBuilder(); | ||
|
||
var indecies = Enumerable.Range(0, arr.Rank).Select(dimention => arr.GetLowerBound(dimention)).ToArray(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dimention
->dimension
return sb.ToString(); | ||
} | ||
|
||
private bool IsFirstIteration(Array arr, int index, int dimention) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dimention
->dimension
return index == arr.Rank - 1; | ||
} | ||
|
||
private bool IsLastIteration(Array arr, int index, int dimention) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dimention
->dimension
return index == arr.GetLowerBound(dimention); | ||
} | ||
|
||
private bool IsMostInnerLoop(Array arr, int index) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IsMostInnerLoop
-> IsInnerMostLoop
return index >= arr.GetUpperBound(dimention); | ||
} | ||
|
||
private bool IsNotLastIteration(Array arr, int index, int dimention) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🙃 I would leave out that function and just use !IsLastIteration
directly.
// Emulate n-ary loop | ||
while (currentLoopIndex >= 0) | ||
{ | ||
var loopValue = indecies[currentLoopIndex]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would currentDimensionIndex
be a more describing name for loopValue
?
sb.Append(formatChild(string.Join("-", indecies), enumerator.Current)); | ||
if (IsNotLastIteration(arr, loopValue, currentLoopIndex)) | ||
sb.Append(", "); | ||
++indecies[currentLoopIndex]; // Increment loop variable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please put comments right above the statement.
if (currentLoopIndex < 0) | ||
break; | ||
|
||
// update loopValue and loopMaxValue |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
loopMaxValue
does not exist.
From CSharpGuidelines
Try to focus comments on the why and what of a code block and not the how. Avoid explaining the statements in words, but instead help the reader understand why you chose a certain solution or algorithm and what you are trying to achieve. If applicable, also mention that you chose an alternative solution because you ran into a problem with the obvious solution. ...
|
||
var sb = new StringBuilder(); | ||
|
||
var indecies = Enumerable.Range(0, arr.Rank).Select(dimention => arr.GetLowerBound(dimention)).ToArray(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We prefer not using var
, unless the type is explicitly specified.
https://github.com/dennisdoomen/CSharpGuidelines/blob/master/_pages/1500_MaintainabilityGuidelines.md#-only-use-var-when-the-type-is-very-obvious-av1520-
* Renamed variables * Removed redundant comments * Use explicit type instead of `var`
@jnyrup Thanks for your comments! |
@DmitriyMaksimov Thanks for the contribution - Fluent Assertions just got one tad better. |
Happy to contribute 😄 |