2013-11-16
Unix getopt versus Google's getopt variant and why Unix getopt wins
The longer title of this entry is 'why Google's version of getopt is right for Google but wrong for (almost) everyone else'.
One reaction to my rant about Go's getopt problem is to ask what the big problem is.
Looked at in the right light, the rules implemented by Go's flag
package (which are apparently the Google
more or less standard for parsing flags) actually have a certain amount
to recommend them because they're less ambiguous, more consistent, and
less likely to surprise you.
For example, consider this classic error: start with a command that
takes a -t
flag switch and a -f
flag with an argument. One day
someone in a hurry accidently writes this as 'cmd -ft fred bob
'
(instead of '-tf
'). If you're lucky this will fail immediately with
an error; if you're unlucky this quietly succeeds but does something
quite different than what you expected. Google flag parsing reduces the
chances of this by forcing you to always separate flags (so you can't do
this just by transposing two characters).
In an environment where you are mostly or entirely using commands that
parse flags this way, you get a number of benefits like this. I assume
that this describes Google, which I suspect is heavily into internal
tooling. But most environments are not like this at all; instead,
commands using Go's flag package (or equivalents) are going to be the
minority and the vast majority of commands you use will instead be
either standard Unix commands or programs that use the same general
argument parsing (partly because it's the default in almost everyone's
standard library). In such environments the benefits that might come
from Google flag parsing are dwarfed by the fact that it is just plain
different from almost everything else you use. You will spend more time
cursing because 'cmd -tf fred bob
' gives you 'no such flag -tf' errors
than you will ever likely save in the one (theoretical) time you type
'cmd -ft fred bob
'.
(In theory you could also sort of solve the problem by always separating flag arguments even for programs that don't need this. But this is unlikely in practice since such programs are probably the majority of what you run and anyways, other bits of Go flag handling aren't at all compatible with standard Unix practice.)
In other words: inside Google, the de facto standard is whatever Google's tools do because you're probably mostly using them. Outside Google, the de facto standard is what the majority of programs do and that is standard Unix getopt (and extended GNU getopt). Deviations from de facto Unix getopt behavior cause the same problems that deviations from other de facto standards cause.
Now I'll admit that this is stating the case a bit too strongly. There are plenty of Unix programs that already deviate to a greater or lesser degree from standard Unix getopt. As with all interface standards a large part of what matters is how often people are going to use the deviant commands; the more frequently, the more you can get away with odd command behavior.
(You can also get away with more odd behavior if it's basically impossible to use your program casually. If an occasional user is going to have to re-read your documentation every time, well, you can (re)explain your odd command line behavior there.)