Installation • Usage • Notes • License
Simply download a release from the releases page and run! You may wish to put it on your PATH for it to be easily executable (e.g. in /usr/local/bin
).
Run:
go install github.com/liampulles/ranking-cli/cmd/sportrank@latest
To get the latest version on master, otherwise change latest
to a specific version.
To install from source (requires make
) clone the repo and in the root folder run
make install
This will build the app and place it in your configured GOBIN directory.
Given a file input.txt
with contents:
Lions 3, Snakes 3
Tarantulas 1, FC Awesome 0
Lions 1, FC Awesome 1
Tarantulas 3, Snakes 1
Lions 4, Grouches 0
Running the following:
sportrank -i input.txt
Will produce output:
1. Tarantulas, 6 pts
2. Lions, 5 pts
3. FC Awesome, 1 pt
3. Snakes, 1 pt
5. Grouches, 0 pts
You can also choose to take input from STDIN and/or output to a file, e.g.:
cat example.txt | sportrank -o output.txt
The architecture of the system follows Robert Martin's clean architecture (https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html). This means the usecase layer has no sight of the adapter layer, and the adapter layer has no sight of the driver layer. The architecture differs slightly though in that I've added an outer wire
layer for dependency injection, and that I've put the domain logic in pkg/league
, since it may be useful as a library for other apps.
Using this architecture, one could trivially extend the app (or create a new app) to invoke the ranking code from an HTTP endpoint, or RPC method, etc. without modifying the business logic itself (in pkg/league
).
I wrote a little piece a while back around using the Clean architecture in Go on my site: https://liampulles.com/2020/09/29/notes-on-applying-the-clean-architecture-in-go.html
As mentioned, the wire package deals with dependency injection. One could use the Google wire tool to do this, but for a simple app like this I think its simple enough to wire it oneself.
There are a handful of "services" in the system, for example cli.Engine
. These services consist of an interface and an implementation and may depend on other service interfaces, which are injected by the wire package.
This pattern is very useful for unit testing, since dependent services can be mocked (in this repo, the mocks are generated with mockery) to ensure that the service being tested is the only thing being tested.
Note lines like this:
var _ RowIOGateway = &RowIOGatewayImpl{}
This line will fail if *RowIOGatewayImpl does not implement RowIOGateway - this line thus acts as a kind of guard (which is why I use it).
I'm familiar with other sort of local repository management tools (e.g. Gradle), but I like make
for my personal projects because it is simple to use, powerful, and widely available on Linux-like systems.
Some things you might like to try:
make view-cover
: Generate and view test coveragemake pre-commit
: Update dependencies, run tests, generate code, lint, etc. - I run this before I submit code generally.make install-tools
: Install any tools needed to work on the project. This should get invoked automatically if you run a make command and a needed tool is not available (I hope).
For personal projects, I use Travis for CI, and goreleaser for CD (in this context, meaning creating a Github release with binaries).
See LICENSE