Our friend C01t is riding the elevator to the 15th floor for a meeting with Naomi, one of the system admins in charge of Guava Orchard’s IT infrastructure. After settling in as a member of project Feijoa, C01t has been tasked with building a command line app. Admins will use the tool to configure, maintain and troubleshoot the Feijoa service. He has never built a CLI before. Furthermore, no one on the team has a clear idea of what the requirements for the tool are. Therefore, Kaya suggested he meet with Naomi to get her input on the requirements.
“Why don’t I show you the Tamarillo
command line app”, Naomi proposes once they are settled in the conference room. “Sam and I think its easily one of the best CLIs we use”, she continues nodding at the system admin sitting across from her. “I run Linux. Sam runs windows. Yet both of us can use the Tamarillo
CLI from our desktops.” Then Naomi demos the intuitive command structure and contextual help feature of the app.
Next Sam opens one of the bash scripts they wrote to provision new users. To his surprise, C01t notices that the script invokes the same app that Naomi just demoed. “Scripting this tool was easy and straight forward. That capability alone simplifies our jobs a ton”, explains Sam.
“How long have you been using this app?”, asks C01t. “When did we deploy Tamarillo
? Maybe 15 months ago”, replies Naomi. “That sounds about right”, confirms Sam. “And you know what has been truly amazing? In these 15 months they have released 22 updates to the command line app. That’s roughly a new version every 3 weeks. And not once did they break or regress existing functionality”, Naomi explains. “That is amazing”, agrees C01t. “They must have a huge army of testers.” Naomi gives him a knowing smile. “As a matter of fact 2 developers spend 20% of their time developing the app. That’s it. There is not army of testers. Automated tests validate all functionality”, she explains still smiling.
The anatomy of a CLI
Naomi and Sam introduced C10t to a well written CLI. The features they highlighted provide an excellent road-map for teasing out the characteristics of a good command line app.
Deliver portability
Our primary goal when developing a CLI is to make it available on all platforms that our customers use. Furthermore, we aim to make installation of the CLI as simple as possible. Therefore, go
is our preferred language for the task.
With go
you can write the code once and run it everywhere. Additionally, all go
programs compile into binary executables. Since version 1.5 go
has built-in support for cross-compiling. Check out The Go Cookbook for instructions on how to cross compile your code. In addition, you can find the list of supported compile targets in the official docs.
spf13/cobra and urfave/cli are 2 widely used libraries for building command line apps in the vein of the git
command. Both provide a declarative way to define the command and sub-commands. Furthermore, both will handle the parsing and extraction of flags and command arguments. And both implement a contextual help system that enable you to build self documenting apps. Overall the libs are very similar. So you can confidently choose either one.
Design for usability
We aim to make the command line app easy to use. Therefore, we need to be mindful of how commands are organized and how complex the user input is.
Command structure
At the core of every CLI app there are 2 concepts: actions and entities those actions apply to. By organizing our command structure around these 2 concepts, we can build an intuitive self documenting application.
Consequently we can chose from 2 different approaches. The first approach is to build an action centric command structure. In this model the primary commands represent actions and the secondary commands are the entities. To illustrate this approach consider what command to start a service for the Tamarillo
app would look like:
> tamarillo start service [args ...]
Another option is to build an entity centric command structure. In this case the primary commands all represent entities and the secondary commands are the actions. Now the same command to start a service would look like:
> tamarillo service start [args ...]
So how do we decide which structure to apply? First we consider the symmetry of the actions. Do all or a plurality of the actions apply to a plurality of the entities? Next we consider the cardinality of the 2 concepts. Does our domain have a large number of actions but only a handful of entities? Or vice versa? If the actions are symmetric we make the primary command the actions regardless of cardinality. Otherwise we use the concept with the lower cardinality as the primary command.
The key is consistency. A consistent structure makes it easier for a new customer to explore the commands. Therefore, we must apply the structure we choose consistently to all commands.
Input
To improve ease of use we avoid requiring the user to provide UUIDs as parameters to commands. Because UUIDs are the preferred entity identifiers in most distributed systems, satisfying this principle is more complicated than it seems.
We recommend using config files to load and save the UUID(s) of the “active” entity(s). If the app is similar to git
, where commands are executed in the context of a working folder, then we use a config file per working folder. However, if the commands don’t have a folder execution context we can store any config files in the user’s home folder. To save the UUIDs we can implement explicit app commands for setting the active entity.
> tamarillo service set -id a0744c52-36fe-11e8-b467-0ed5f89f718b
However, our preferred way is to implicitly set the “active” entity to the last entity that was explicitly specified. Then all subsequent commands can omit specifying the UUID explicitly.
# Start the service
> tamarillo service start -id a0744c52-36fe-11e8-b467-0ed5f89f718b
# Query for the status of the serice
> tamarillo service status
# Restart the service
> tamarillo service restart
Another option is to accept entity names instead of unique identifiers. However, for this to work the service has to support entity names.
Output
There is no output harder to read than rows of data where the columns are misaligned. So we align tabular output produced by the app. We use the tablewriter library to format tabular output.
Another priciple is to make information stand out by leveraging colorful text. However, we must be judicious with the use of color. Too much color can actually impair the readability of your output. In a number of our applications we have used the color library to generate colorized output.
Build for versatility
Probably the most consequential omission during the initial design of a CLI is scriptability. Following a few simple patterns we can implement a command line app that is capable of producing JSON output in addition to the human readable one. And as a result one can now easily parse the output using jq in any shell script.
Here are some simple rules of thumb to follow:
- Output a single JSON object. Even displaying multiple JSON objects with clear delimiters, e.g. “\n”, makes the output considerably harder to parse.
- Suppress all other output. If we do not any additional output will interfere with parsing of the JSON output.
- Display errors as valid JSON objects when the command fails.
Structure for testability
Finally, you want to write suite of automated tests to guard against regressions. To accomplish this goal we write both integration tests and unit tests.
We write the integration tests to exercise the app against real services/environments. Here we leverage all the work we did to make the CLI scriptable. Because we can emit JSON output from all commands, we can build robust test cases that validate app behavior. Furthermore, we are able to reliably implement complex test scenarios that requires us to pass parameters between commands.
On the other hand, we use unit-tests to ensure all execution paths are covered, especially failure paths. However, to write unit tests we have to carefully structure the app. First of all, we use client abstractions to interact with external services. During unit-test execution we replace the clients with mocks. Then we make the command action function easy to unit-test by following some simple rules such as: do not access global variables; return detailed results that can be asserted on; propagate errors through return values – never use os.Exit
or panic
; and pass in an io.Writer to receive all output.
I oversee a vape store directory site and we have had a listing from a vape store in the USA that likewise offers CBD items. A Calendar month later on, PayPal has contacted use to claim that our account has been limited and have asked us to get rid of PayPal as a payment method from our vape store website directory. We do not offer CBD products such as CBD oil. We merely offer marketing professional services to CBD firms. I have taken a look at Holland & Barrett– the UK’s Top Health Store and if you take a close look, you will witness that they promote a comparatively comprehensive series of CBD products, particularly CBD oil and they also happen to take PayPal as a settlement method. It appears that PayPal is administering double standards to different firms. As a result of this constraint, I can no longer accept PayPal on my CBD-related internet site. This has limited my payment choices and right now, I am intensely contingent on Cryptocurrency payments and straightforward bank transfers. I have checked with a solicitor from a Magic Circle law practice in The city of london and they explained that what PayPal is undertaking is entirely against the law and discriminatory as it ought to be applying a consistent criterion to all companies. I am yet to get in touch with one more legal representative from a US law firm in The city of london to see what PayPal’s legal position is in the United States. Meanwhile, I would be very appreciative if anyone here at targetdomain could provide me with different payment processors/merchants that deal with CBD companies.
With havin so much content and articles do you ever run into any problems of plagorism or
copyright infringement? My site has a lot of completely unique content I’ve either created myself or outsourced but it appears
a lot of it is popping it up all over the web without my permission. Do you
know any techniques to help protect against content from
being stolen? I’d truly appreciate it.
❤️ Alice sent you a HOT video! Click Here: http://bit.do/fSHAz ❤️
Access to the 1xbet UA from anywhere where there is Wi-Fi or mobile Internet. At the changeless duration, applications do not establish up much space in the thingamajig’s memory.
Hello everybody ! can anyone suggest where I can buy CBD Pet Tincture 500mg By Natural Leaf CBD?
I went over this web site and I conceive you
have a lot of excellent info, saved to my bookmarks (:.
Here is my web blog – good skin care
I know this if off topic but I’m looking into starting my own weblog and was curious what all is required to get setup?
I’m assuming having a blog like yours would cost a pretty penny?
I’m not very internet savvy so I’m not 100% sure. Any suggestions or
advice would be greatly appreciated. Cheers
my homepage … drug crime
I am not sure the place you are getting your information, however good topic.
I needs to spend a while finding out more or figuring out more.
Thanks for excellent info I used to be on the lookout for this info
for my mission.
Feel free to surf to my web page :: http://forum.vkmoravia.cz
Hi there! This post couldn’t be written any better!
Reading this post reminds me of my old room mate!
He always kept talking about this. I will forward
this article to him. Pretty sure he will have a good read.
Thanks for sharing!
Feel free to surf to my webpage low carb diet
I was just looking for this information for a while. After 6 hours of continuous Googleing, at last I got it
in your web site. I wonder what’s the lack of Google strategy that do not rank this kind of
informative websites in top of the list. Normally
the top sites are full of garbage.
My web page; forum.vkmoravia.cz
Hello terrific blog! Does running a blog such
as this require a large amount of work? I’ve virtually no expertise in computer programming however I had been hoping to start my own blog soon. Anyways,
if you have any suggestions or techniques tips for weight loss new blog owners please
share. I understand this is off subject but
I just wanted to ask. Cheers!
Hello, you used to write wonderful, but the last several posts have been kinda boring…
I miss your super writings. Past few posts are just a little out of track!
come on!
My site foods rich in omega 3 fatty acids
I could not refrain from commenting. Perfectly written!
Also visit my page eradicates eczema
This paragraph is genuinely a fastidious one it helps
new web people, who are wishing in favor of blogging.
my webpage – smooth skin
Genuinely when someone doesn’t be aware of then its up to other users that they will assist, so here it occurs.
My blog post … low carbohydrate
You are my breathing in, I possess few blogs and very sporadically run out from post :).
Here is my website :: impact carbs
It’s an remarkable piece of writing in support of
all the internet people; they will obtain benefit
from it I am sure.
Here is my homepage :: healthy eating
Good Morning everyone , can anyone advise where I can buy Being Hemp?