

versions
was officially announced to the world last month, and since then I’ve been working on adding features I think will make this tool more useful.
Today I’m introducing a new minor version: v0.1.0
, but before that…
Architecturally versions
is pretty straightforward, it consists in the following:
go.mod
files, which represent “projects” or “repositories”,go.mod
files with the goal of generating a matrix of packages,go.mod
file,v0.0.1
was built with those steps in mind. The initial goal was to quickly implement a proof of concept, an actionable prototype that worked with one objective: to render flavored markdown. This objective was accomplished.
However, this code was not in a shape to be easily extented, sure it did the job, but it required more thought if the plan was to move forward and continue with the development. With that in mind my next goals before making a new release were two:
It was clear that separating the actual parsing from the rendering (and its concrete rules) was needed. The first version assumed flavored markdown was the only rendering output supported, it included concrete rendering rules applicable to this type and it was intertwined with other non-rendering logic. This change was required for allowing adding more ouputs in the near future, like JSON.
In v0.0.1
really everything was implemented in two functions:
versions.NewGoMods
for doing something with the parsed go.mod
values, andversions.PrintMarkdown
for printing out the actual markdown code.So, how we go from that really concrete implementation to something more abstract?
The way I thought about it in v0.1.0
was to define the final results in a new Versions
type:
// Versions contains the parsed go.mod files.
Versions struct {
Modules map[ModuleName]Module
GoVersions GoVersions
Packages Packages
}
The fields in this type contain the parsed values organized in threee different ways:
go.mod
file contains, Modules
field, this includes the Module
s:ModuleGoVersion
s, and itsPackage
s.Packages
field, organized internally by ModuleName
,GoVersions
field.Having those three fields available are the basic layer required for allowing different renderers to generate what is needed. markdown
is the concrete example so far, this package only renders the results, it still supports the options that were available before but now they don’t affect the parsing process.
After cleaning up the code and refactoring it, the second goal was to add a new feature. I thought that adding LICENSE
support would be a good excercise, because:
Package
, because licenses are per package and could change depending on the concrete version used,Therefore adding a feature like this will allow me, the user of the versions
package, to determine how good or bad the user experience was (from the development perspective that is), to corroborate whether the final refactored code is better or not.
In the end this was an interesting excercise that proved that the code was easier to work with and also led to another nice change, the introduction of olekukonko/tablewriter
for rendering markdown code in a more user-readable way.
This time I wanted to diverge a tiny bit from the usual announcement-like post and instead walk you through my thought process and how the code evolved. For sure versions
is still in its infancy but I think it makes sense to describe the behind-the-scenes from time to time.
To install the current version you can run:
GO111MODULE=on go get github.com/MarioCarrion/versions/cmd/versions@v0.1.0
Using it is the same as before:
versions <full path to 1 go.mod> <full path to 2 go.mod> <full path to N go.mod>
Have fun!