snippetcsharpMinor
Convert an object to an ordered by SemVer Markdown list
Viewed 0 times
semverconvertmarkdownlistobjectordered
Problem
For a small personal project, I am looking to convert an object to an ordered by SemVer Markdown list. You can find the original code for the sort logic here and here for the writing into Markdown logic. I merged them to a full working snippet. I am using C# 5 in .NET 4.5.1.
Basically, the goal is to transform this:
into that:
I wrote the code to do it but I am not very proud of it. It smells not right. I am sure I can clear it and use betters way to achieve what I want. You can try the whole program in .NETFiddle.
What do you think of it? How can I improve it?
```
using System;
using System.Linq;
using System.Text;
using System.Collections.Generic;
public class Program
{
public class Version
{
public string Name { get; set; }
public string[] Evolutions { get; set; }
}
public static void Main()
{
var versions = new[]
{
new Version { Name = "v0", Evolutions = new[] { "Add foo 8", "Add bar 9" }},
new Version { Name = "v2", Evolutions = new[] { "Add foo 0", "Add bar 1" }},
new Version { Name = "v1", Evolutions = new[] { "Add foo 6", "Add bar 7" }},
new Version { Name = "v1.1", Evolutions = new[] { "Add foo 4", "Add bar 5" }},
new Version { Name = "v1.2-alpha", Evolutions = new[] { "Add foo 2", "Add bar 3" }}
}
Basically, the goal is to transform this:
var versions = new[]
{
new Version { Name = "v0", Evolutions = new[] { "Add foo 8", "Add bar 9" }},
new Version { Name = "v2", Evolutions = new[] { "Add foo 0", "Add bar 1" }},
new Version { Name = "v1", Evolutions = new[] { "Add foo 6", "Add bar 7" }},
new Version { Name = "v1.1", Evolutions = new[] { "Add foo 4", "Add bar 5" }},
new Version { Name = "v1.2-alpha", Evolutions = new[] { "Add foo 2", "Add bar 3" }}
};into that:
## Evolutions
### v2
* Add foo 0
* Add bar 1
### v1.2-alpha
* Add foo 2
* Add bar 3
### v1.1
* Add foo 4
* Add bar 5
### v1
* Add foo 6
* Add bar 7
### v0
* Add foo 8
* Add bar 9I wrote the code to do it but I am not very proud of it. It smells not right. I am sure I can clear it and use betters way to achieve what I want. You can try the whole program in .NETFiddle.
What do you think of it? How can I improve it?
```
using System;
using System.Linq;
using System.Text;
using System.Collections.Generic;
public class Program
{
public class Version
{
public string Name { get; set; }
public string[] Evolutions { get; set; }
}
public static void Main()
{
var versions = new[]
{
new Version { Name = "v0", Evolutions = new[] { "Add foo 8", "Add bar 9" }},
new Version { Name = "v2", Evolutions = new[] { "Add foo 0", "Add bar 1" }},
new Version { Name = "v1", Evolutions = new[] { "Add foo 6", "Add bar 7" }},
new Version { Name = "v1.1", Evolutions = new[] { "Add foo 4", "Add bar 5" }},
new Version { Name = "v1.2-alpha", Evolutions = new[] { "Add foo 2", "Add bar 3" }}
}
Solution
OrderByVersion
ExtractSemVer
-
I would seriously consider introducing a
You could give a nice
WriteVersions
- You've taken the time to add doc comments, but a vital piece of info is missing. The enumerable is sorted in descending order. That should be there in the doc comments.
- It would be nice to have an option to sort ascending. (It's also an interesting problem to solve. =;)-
- The mixture of query and lambda syntax seems a bit strange to me. I'd pick one and stick with it. I don't necessarily mean use just one style everywhere, but you should probably stick to just one of the two within a statement/method.
ExtractSemVer
- There's no reason to abbreviate. This method should be named
ExtractSemanticVersion.
-
I would seriously consider introducing a
SemanticVersionNumber struct. public struct SemanticVersionNumber
{
public int Major { get; }
public int Minor { get; }
public int Patch { get; }
public string Build { get; }
....
}You could give a nice
ToString method and a constructor that turns a string into an instance of this struct. Nicely tucking away the logic to do so, with the added benefit of possibly simplifying the ordering logic. You'd probably want to implement IComparable. Yes. I like that idea. You could take all of this logic out of your console class and put it in here where it probably belongs. You could also possibly make it part of your existing Version class, replacing Name with the ToString method that I mentioned. WriteVersions
- You never really use the index of the loop, so it will be cleaner to just use a
foreachloop.
- Use the AppendLine method to append new lines to the string instead of awkwardly formatting them in.
- Only set the
lengthvariable once, outside of the loop.
public static string WriteVersions(IList versions)
{
Func lineOrEmpty = b => b ? Environment.NewLine : String.Empty;
Func isLimit = (n, limit) => n + 1 line = n => lineOrEmpty(isLimit(n, versions.Count));
var stringBuilder = new StringBuilder("## Evolutions");
stringBuilder.AppendLine()
.AppendLine();
foreach (var version in versions)
{
stringBuilder.AppendFormat("### {0}", version.Name)
.AppendLine()
.AppendLine();
var length = version.Evolutions.Length;
foreach (var evolution in version.Evolutions)
{
stringBuilder.AppendFormat("* {0}", evolution)
.AppendLine();
}
stringBuilder.AppendLine();
}
return stringBuilder.ToString();
}Code Snippets
public struct SemanticVersionNumber
{
public int Major { get; }
public int Minor { get; }
public int Patch { get; }
public string Build { get; }
....
}public static string WriteVersions(IList<Version> versions)
{
Func<bool, string> lineOrEmpty = b => b ? Environment.NewLine : String.Empty;
Func<int, int, bool> isLimit = (n, limit) => n + 1 < limit;
Func<int, string> line = n => lineOrEmpty(isLimit(n, versions.Count));
var stringBuilder = new StringBuilder("## Evolutions");
stringBuilder.AppendLine()
.AppendLine();
foreach (var version in versions)
{
stringBuilder.AppendFormat("### {0}", version.Name)
.AppendLine()
.AppendLine();
var length = version.Evolutions.Length;
foreach (var evolution in version.Evolutions)
{
stringBuilder.AppendFormat("* {0}", evolution)
.AppendLine();
}
stringBuilder.AppendLine();
}
return stringBuilder.ToString();
}Context
StackExchange Code Review Q#106660, answer score: 5
Revisions (0)
No revisions yet.