Should This Be a Feature?

Posted on May 22, 2021

One thing I’m very proud of is me releasing cras 2.0.0 earlier this week! A very… unique release indeed! Very few new features… less features than the 1.x series! (Have I become a GNOME developer?? /jk)

Which features have been removed, you ask? Those which I feel are easily reproduced by means of using shell commands. Let me show you a very practical example from cras itself.

$ cras example
#01 [TODO] First task
#02 [DONE] Second task
#03 [DONE] Oh no, what a busy day!
#04 [TODO] Take a nap

So, earlier versions of cras printed a counter of how many tasks are completed against how many are pending and they also provided a couple of CLI options which allowed the user to filter out parts of the output (e.g. the list of tasks, the counter itself, etc.). These features are all gone… because… well…

You wanna know which tasks are still pending?

$ cras example | grep 'TODO'
#01 [TODO] First task
#04 [TODO] Take a nap

What about how many are pending, how many are completed, and print out a counter… let’s say in a script that feeds into a WM status bar?

$ echo "pend: $(cras example | grep -c 'TODO') / todo: $(cras example | grep -c 'DONE')"
pend: 2 / todo: 2

The flexibility is… absolute! Why limit users by providing a limited subset of possible filters when you’ve got our beloved friend grep to deal with whatever filtering you need to apply to cras’s output? Or if you prefer using awk… you just can!

This has allowed me getting rid of lots of “hardcoded” things that well, yes, were configurable in config.h, but in the end not even myself used… I ended up implementing “short” modes that essentially did what I could easily write as a shell script.

Now I’m way happier with the state of cras, honestly.

In general, I see this as a very hard to answer design question. How much do you want to implement into your own program and how much do you want the user be reliant on the standard POSIX toolchain? Lately I tend to favor the latter, but it comes with a cost: your interface becomes more abstract and your user needs to know how to deal with scripts… Yes, it’s super powerful… but only useful for those “in the know.”

Long time ago, I always wrote my programs following the Emacs-esque kitchen sink approach. cras is one example of that (just check out cras 0.x or 1.x), but I think even minitimer has suffered from this at some point. The usual thought when doing so was “I wanna be in control of the user experience.” And it’s true: if your program incorporates lots of use-cases, you’re rewarding your user with consistency and a feeling of support: “This program totally supports this, this, and that you’re trying to do with it… because we provide a native way to do it!” Less inter-op, but depending on who your users are maybe it is the smartest move.

Sometimes I feel it’s up to the task. To be honest, I can’t see how MySQL/MariaDB, for example, would benefit from becoming a suite of shell scripting-aware tools… On the other hand, their single point of entry is perfect for their use case. Or take GNOME Shell: It’s catered to users who just want to tweak their desktop or workstation experience the least as possible and want it to be super consistent. Is it less UNIX-y than my WM-based setup? You bet it is! But am I the user GNOME designed their desktop for? Nope.1

Let’s be honest, you know? I can write my programs in this quite minimalist fashion because these are hobbyist projects. I can essentially do with them whatever I please. I’ve grown to love fiddling with pipelines, writing scripts, and making my system be a beautifully organic network of little tools that (usually) cooperate among each other in (occasional) harmony. But hey, that’s me on my personal laptop and the couple of servers I’m the sysadmin of… If I were dealing with a commercial project I’d probably have my potential users surveyed and do whatever they seem to think is best in their own experience. In a commercial setting I’m pretty sure the result would look way more like Git (which is why it’s been so succesful, BTW): an all-in-one solution that might be implemented in lots of small modules (opening the doors to inter-op), but provides a single entry point to use all of its features.

It’s a fun topic. I think I’ve spent quite some time on all of my projects thinking “Should I implement this or should this just be left to scripting?” I guess my answers have varied wildly from time to time, from project to project. Who knows… maybe I end up one day implementing a whole CalDAV client into cras one day so you sync your task lists with a server? Just kidding… I guess?

Stay safe! Love y’all!

  1. Not anymore, actually. I was a very loyal GNOME Shell user for a long time… but my interests and tastes changed in time. Nothing bad about that… I still think it’s an amazing DE. ↩︎