UP | HOME

Command-line program interface

When writing a system consisting of multiple software components, it's too easy to get stuck with a particular technology: a language, if it's monolithic or heavily relies on a language-specific library; a message bus/queue if the architecture is service-oriented; a DB engine and structure if it's just a bunch of programs using DB directly; and weird non-standard conventions for things like logging and configurations tend to arise, leading to the big ball of mud.

In dealing with that, KISS and Unix philosophy seem to be rather helpful, along with the aim to keep the components as independent and unattached to each other as possible. Basically, writing them with minimal assumptions about the system they'll be used in, sticking to standards whenever they are defined, etc.

Yet it gets rather tricky when it comes to interaction between components: when integrating a program into a system, it should exchange data with others somehow. I've used serialization (mostly JSON, primarily because it's common nowadays) + stdin/stdout for that (well, also environment variables where that made sense), what works mostly fine, but JSON on input is not that handy for scripting, cron jobs, manual invocation, and not the most common way to tell a program what to do: for that, there are command-line arguments, which solve the other listed issues as well.

Well, mostly: for large inputs or streams of data, something like JSON would still be more suitable, and most of the time JSON parsers and printers can be derived directly from types (e.g., with Aeson in Haskell), while for command-line arguments there usually are just parsing libraries. In an attempt to fix the latter, I've started writing the coalpit library, which derives command-line option parsers along with printers.