Improve formatting of multidimensional arrays (#991)#1044
Improve formatting of multidimensional arrays (#991)#1044jnyrup merged 3 commits intofluentassertions:masterfrom DmitriyMaksimov:Improve-formatting-of-multidimensional-arrays
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 |
dennisdoomen
left a comment
There was a problem hiding this comment.
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.
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.
Can this ever be negative?
| } | ||
|
|
||
| /// <inheritdoc /> | ||
| public string Format(object value, FormattingContext context, FormatChild formatChild) |
There was a problem hiding this comment.
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.
Please put this directly below the test method that needs it.
Tests/Shared.Specs/FormatterSpecs.cs
Outdated
|
|
||
| [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.
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! |
jnyrup
left a comment
There was a problem hiding this comment.
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(); |
|
|
||
| var sb = new StringBuilder(); | ||
|
|
||
| var indecies = Enumerable.Range(0, arr.Rank).Select(dimention => arr.GetLowerBound(dimention)).ToArray(); |
| return sb.ToString(); | ||
| } | ||
|
|
||
| private bool IsFirstIteration(Array arr, int index, int dimention) |
| return index == arr.Rank - 1; | ||
| } | ||
|
|
||
| private bool IsLastIteration(Array arr, int index, int dimention) |
| return index == arr.GetLowerBound(dimention); | ||
| } | ||
|
|
||
| private bool IsMostInnerLoop(Array arr, int index) |
There was a problem hiding this comment.
IsMostInnerLoop -> IsInnerMostLoop
| return index >= arr.GetUpperBound(dimention); | ||
| } | ||
|
|
||
| private bool IsNotLastIteration(Array arr, int index, int dimention) |
There was a problem hiding this comment.
🙃 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.
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.
Please put comments right above the statement.
| if (currentLoopIndex < 0) | ||
| break; | ||
|
|
||
| // update loopValue and loopMaxValue |
There was a problem hiding this comment.
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.
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 😄 |