[TUHS] Systematic approach to command-line interfaces [ meta issues ]

Warner Losh imp at bsdimp.com
Sun Aug 1 08:10:04 AEST 2021

On Sat, Jul 31, 2021 at 3:33 PM Jon Steinhart <jon at fourwinds.com> wrote:

> Richard Salz writes:
> > On Sat, Jul 31, 2021 at 3:21 PM Jon Steinhart <jon at fourwinds.com> wrote:
> >
> > > opinion, it doesn't add value to do something that's already been done
> > > but differently; it detracts from value because now there's yet another
> > > competing way to do something.
> > >
> >
> > You mean like not using getopt and rolling your own?  Shrug.
> >
> > while ((i = getopt(argc, argv, "xxxxx:xxxx")) != -1)
> >    switch (i) {
> >    case ....
> >   }
> > argc -= optind;
> > argv += optind;
> >
> > So I never got getopt().  One of my rules is that I don't use a library
> > > in cases where the number of lines of gunk that that it takes to use a
> > > library function is >= the number of lines to just write it myself.
> >
> >
> > I don't know, what lines in the above are extra beyond what you write?
> The
> > last two if being generous I suppose.
> Well, in my opinion that's not really an accurate representation of using
> getopt.
> I would of course write the #include line, and the table of options, which
> would
> end up being >= the number of lines that it takes me to do this...
>         while (--argc > 0) {
>                 if (*(++argv)[0] == '-') {
>                         for (p = *argv + 1; *p != '\0'; p++) {
>                                 switch (*p) {

Except for all the things this gets wrong, it's ok. The problem with
inlining getopt
is that you wind up with cases like -f foo'' on the command line being
treated differently
than '-ffoo'. Inlined code like this can be quite frustrating for the user
to use. Your
locality of reference is cut and paste bugs that getopt eliminates because
it handles
all the special cases in a uniform way.

> Even if it took a few more lines to do it my way, I'm a believer that good
> coding
> style keeps "meatspace locality of reference" in mind.  As programmers, we
> put in
> a lot of effort to ensure locality of reference for computers, but then
> completely
> toss it for people who aren't as good as it.  So given a choice of a few
> lines of
> code versus having to look something up somewhere else, I choose the few
> lines of
> code.

And a few more bugs...

Being a geezer, I have lots of code lying around from which I can extract
> working
> fragments such as the one above.  Writing those few lines of code provides
> insulation
> from supply-side attack vectors bugs in libraries, versioning issues,
> having to load
> debug libraries, and so on.

getopt has been standardized since the 80s and has had universal adoption
the 90s. Hardly a version chasing issue since it's in everybody's libc.

> I realize that this isn't a huge deal by itself; it's a philosophical
> point.  When
> I strace any random program that I didn't write I'm astonished by the
> amount of
> library loading that takes place.  So any issues are multiplied by n.

The flip side to this is that libraries can be debugged once, while inline
like the above needs to be deugged over and over....

> Don't get me wrong; I use plenty of libraries.  But I tend to use those
> for stuff
> that is so common that there is a benefit from shared libraries (or at
> least there
> was before everything got containerized) and for libraries that do actual
> hard stuff.
> But I don't use libraries for small snippets of code that I could easily
> write
> myself yielding better code clarity for others reading my code.

Given the number of times I've been burned by trying to roll my own getopt,
I stopped trying years ago. It's harder than it looks.


> Jon
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://minnie.tuhs.org/pipermail/tuhs/attachments/20210731/6b16b219/attachment.htm>

More information about the TUHS mailing list