Book Image

Building Modern CLI Applications in Go

By : Marian Montagnino
Book Image

Building Modern CLI Applications in Go

By: Marian Montagnino

Overview of this book

Although graphical user interfaces (GUIs) are intuitive and user-friendly, nothing beats a command-line interface (CLI) when it comes to productivity. Many organizations settle for a GUI without searching for alternatives that offer better accessibility and functionality. If this describes your organization, then pick up this book and get them to rethink that decision. Building Modern CLI Applications in Go will help you achieve an interface that rivals a GUI in elegance yet surpasses it in high-performance execution. Through its practical, step-by-step approach, you’ll learn everything you need to harness the power and simplicity of the Go language to build CLI applications that revolutionize the way you work. After a primer on CLI standards and Go, you’ll be launched into tool design and proper framework use for true development proficiency. The book then moves on to all things CLI, helping you master everything from arguments and flags to errors and API calls. Later, you’ll dive into the nuances of empathic development so that you can ensure the best UX possible, before you finish up with build tags, cross-compilation, and container-based distribution. By the end of this UX book, you’ll be fully equipped to take the performance and flexibility of your organization’s applications to the next level.
Table of Contents (21 chapters)
1
Part 1: Getting Started with a Solid Foundation
6
Part 2: The Ins and Outs of a CLI
10
Part 3: Interactivity and Empathic Driven Design
14
Part 4: Building and Distributing for Different Platforms

The philosophy of CLI development

Philosophy plays a major role in the development of computer science. Throughout history, there have been many great contributions to computer science through philosophy, partially because many computer scientists were and are also philosophers. It is no surprise that each OS has its own distinct philosophy.

Windows, for example, hardcodes most of its intelligence within the program or OS, assuming users’ ignorance and limiting their flexibility. Although the barrier to understanding is lower, users interact with the program without understanding how it works.

The developers of UNIX had an opposing philosophy: provide the user with almost limitless possibilities to empower them. Although the learning curve is steep, much more can be developed within an environment that doesn’t shield its users from the complexity of freedom.

There have been many books written about UNIX’s philosophy and implementing it in real life is an art form. I am sure, therefore, many people view coding as a craft. Although there are many other philosophies to review, the focus in this section will be on UNIX’s philosophy.

The legendary designers of the Go programming language, Ken Thompson, Robert Griesemer, and Rob Pike, share a long history with UNIX, and it feels fitting to discuss the philosophy within the context of its creators since Go was built around it.

UNIX’s philosophy advocates for simple and modular designs that are both extensible and composable. The basis is that the relationships between numerous small programs are more powerful than the programs themselves. For example, many UNIX programs handle simple tasks in isolation, but when combined, these simple tools can be orchestrated in a very powerful way.

Checklist for a successful CLI

The following are some principles inspired by this UNIX philosophy that when followed will help create a successful CLI:

  • Building a modular program

Design your CLI with standardization in mind to ensure it can be easily composed with other applications. Specifically utilizing standard in and out, standardized errors, signals, and exit codes helps to build a program that is both modular and easily composable. Composability can be handled simply with pipes and shell scripts, but there are also programming languages that can help piece programs together. Continuous Integration/Continuous Delivery (CI/CD), orchestration, and configuration management tools are often built on top of command-line execution and scripts to automate code integration or deployment or to configure machines. Consider the data output from your program and how easily composable it is. The best options are plain text or JSON when structure is needed.

  • Building for humans first

The first CLI commands were written with the assumption that they’d only be used by other programs. This is no longer the case, and so programs should be built with humans first in mind.

Conversation will be the main method of human-computer interaction. Imagine the natural flow of human conversation and how that concept can be applied to help a user who has misunderstood the program design. In natural language, your program can suggest possible corrections, the current state in a multi-step process, and request confirmation before continuing to do something risky. In the best-case scenario, your user has had a pleasant experience with your CLI, feeling empowered to discover operations and receiving assistance when needed. In the worst-case scenario, your user feels ignored and frustrated with no help in sight. Don’t be that CLI!

Finally, write readable code so other developers can easily maintain your program in the future.

  • Separating interfaces from engines and policies from mechanisms

Decoupling these allows different applications to use the same engine through interfaces or use the same mechanism with different policies.

  • Keeping it simple

Only add complexity when it’s necessary. When complexity does occur, fold it into the data instead of the logic. Where usability is not compromised, use existing patterns.

  • Staying small

Don’t write a big program unless there’s no other way.

  • Being transparent

Be as transparent as possible so users can understand how to use the program and what’s going on. Transparent programs have comprehensive help texts and provide lots of examples allowing users to easily discover the parameters and options they need and have the confidence to execute them. The GUI certainly has a leg up in terms of transparency and visibility; however, we can learn from it and see what can be incorporated to make the CLI easier to learn and use. Users resorting to Google or Stack Overflow is an anti-pattern here.

  • Being robust

Robustness is the result of the former principle: transparency and simplicity. The program should work in a way that the user expects, and when errors occur, explain what is happening clearly with suggestions for resolution. Immediately printing stack traces or not informing the user with a clear and immediate response leaves the user feeling like they are on shaky ground.

  • No surprises

Keep your program intuitive by building on top of a user’s existing knowledge. For example, a logical operator such as + should always mean addition and - should always mean subtraction. Make your program intuitive by staying consistent with pre-existing knowledge and patterns of behavior.

  • Being succinct

Don’t print output unnecessarily and don’t be completely silent, leaving the user to wonder what’s going on. There’s a balance in communication required to say exactly what needs to be said; no more, no less. Too much is a large block of verbose text that forces the user to parse through it to find useful information. Too little is when the command prompt hangs in silence leaving the user to assume a state about the program.

  • Failing noisily

Repair what can be repaired, and when the program fails, fail noisily and as soon as possible. This will prevent incorrect output from corrupting other programs depending on it.

  • Saving your time

Build code to save developers’ time as opposed to the machine’s time, which is relatively cheap these days. Also, write programs that generate programs. It’s much faster and less error-prone for computers to generate code over hand-hacking.

  • Building a prototype first, then optimizing

Sometimes, programmers spend too much time optimizing early on for marginal gains. First, get it working, and then polish it.

  • Building flexible programs

Programs may be used in ways the developers did not intend. Therefore, making the design flexible and open will allow the program to be used in ways unintended.

  • Designing for extensibility

Extend the lifespan of your program by allowing protocols to be extensible.

  • Being a good CLI citizen

Bring empathy into the design and peacefully coexist with the rest of the CLI ecosystem.

The philosophy directly influences the guidelines for creating a CLI. In the next section, you will clearly see the link to satisfy the philosophy tenets discussed, and if anything, following the guidelines will increase the odds of creating a successful CLI.