What Makes "Good Software?"

In the nearly five years since I changed careers to become a full-time firefighter I have kept my distance from developing software of any consequence. To be honest, I had lost my desire to sit at a keyboard and relished the chance to spend my time in other ways. Sure, I've made the switch from Linux to FreeBSD, written a few scripts here and there, created a wiki for firefighters and even dabbled in automated stock market analysis for my own interest but I have otherwise turned down for-profit programming gigs in favour of freedom to spend my time elsewhere.

Although my day job as a firefighter has little to do with software development my prior experience building software has come in handy from time to time. In late 2015 I began working on a couple of small programs to replace a shared spreadsheet used by firefighters to record productivity metrics. Using the old system, only one person could enter data at any given time and it was too easy to accidentally wipe-out changes made by others. To solve this problem, I created two small programs using VBScript and HTML Applications as the foundation. Both of these scripts present simple, domain-specific interfaces that make sense to the users and hide the relative complexity of Excel by recording data in spreadsheet files in the background. One script allows users to record productivity information and the other generates a report from this information for use by management-level personnel. The program went live after about 80 or 90 hours of design, development, end-user documentation and testing. It solves all of the problems of the previous system, is simple to maintain and runs with minimal dependencies. It was distributed by placing a link on our intranet that opens a folder where the relevant scripts can be double-clicked and launched. Since it launched I have received a great deal of feedback that indicated that users were happy with the new system and that it ultimately made their job easier.

Recently I began to develop another piece of software. This time we're dealing with the management of annual hose testing information. The problem is significantly more complicated than the previous project which merely dealt with the recording and reporting of numbers for different categories but I'm hopeful that goals of this project will have similar positive results for the fire department.

As I found myself back at the keyboard for the second time I have begun to think about the considerations that will ensure that the current project is as much of a success as the last one. Here are my thoughts, in no particular order, about what makes "good software."

Good software offers excellent user experiences.

It's been said again and again but I cannot stress this enough. Nothing matters unless the folks on the floor find that their jobs have been improved in some tangible way. People's experiences with your software matter. They're not simply automated cogs in a big machine; they have emotions, goals, demands placed upon them by external forces and expectations. No matter how "slick" your software might be, or how well written it is, if it requires users to jump through hurdles it isn't going to gain traction.

Good software "solves the problem."

These aren't the problems you imagine. They're the ones voiced by real people on the floor. Listen to them because they will tell you nearly everything you need to know and give you the background to derive key take-aways. Also, the problem must be solved in as simple a manner as is possible. Complicated approaches, both technically and from a user-design standpoint only serve to make things harder for everyone.

Good software is simple to build and deploy.

So often we, as programmers, over-complicate the development and delivery of our software. We get too concerned with frameworks, philosophies like TDD (hey, TDD is great - stay with me here) and making things "perfect" from our perspective. I have been as guilty as anyone during my time when I punched a keyboard for a living and I understand the desire to refine our work. That said, some really good software has been written in ancient and unpopular languages. We get excited about trendy things like Rust, incorporating git into every possible nook and cranny of our workflow and turn our nose up at legacy programs written in BASIC and COBOL, never mind that those pieces of software may have solved the problem with accolades and ran for decades while we became infatuated with web-only delivery and app integration.

None of this is meant to say that "modern" software isn't moving in a good direction. Only the people who replace us will be in a position to judge as such. Let's remember to take a step back from time to time and reflect on what we're really doing (solving problems and making jobs easier) and stop ourselves from getting caught up in the latest fad just for the sake of it.

Good software fits into "the bigger picture."

This is the tricky piece of the puzzle. Software so often satisfies the other important areas but fails to fit into the bigger picture. We need to develop our programs with a holistic approach that recognizes the part that our programs will play and respects the reality that our software is not the be-all, end-all. The programs we build must fit within the human-driven process in place and play nicely with the other kids in the sandbox (these are "other" software programs -- the ones we did not write). The user experience might be great, and it might solve the problem but if it's a square peg you're trying to shove into a round hole you've missed the boat entirely.

I will readily admit that I don't have all the answers and sometimes I don't even know what the questions are but this is how I see "good software" in a few simple points. What do you think makes good software?

Falling Into You

I have this song labeled as recorded sometime in 2003 however I don't have any recollection of the exact situation so it's possible that it was a year or two earlier. Like Spanish Orgasm, it was probably composed using a simple WAV editor with tracks layered over one another.

Shockingly racist? An open response to Queen's University and Celeste Yim

The CBC recently posted an article titled Queen's University investigates 'shockingly racist' student costume party wherein the university's Alma Mater Society described party-goers costumes as "inappropriate" and were decried by Toronto comedian Celeste Yim as "shockingly racist." This article brings to mind another decade-old costume related news bite prompted by Prince Harry's choice to wear a swastika armband to a friend's fancy dress party. It's generally accepted that the prince's costume was actually offensive and inappropriate but are the costumes worn, presumably by Queen's students, truly "shockingly racist?"

According to the CBC, the university has stated that it will take otherwise unspecified "appropriate action" if it is determined that the event was sponsored or sanctioned by the university. It can be safely assumed however, that there will be no punitive measures taken should the event be found to be independent of the university.

According to Yim, the costumes "are indisputably and unequivocally offensive, tasteless, and should not be tolerated. Context and intentions have no bearing." Tasteless is perhaps an applicable label however I must take issue with Yim's other statements. Since she has neglected to state why she believes the costumes to be offensive, we can only surmise it is because they represent stereotypes or that the wearer is from a different culture or race.

Declaring an idea or concept "off limits" is a hallmark of those who are not interested in discourse or wish to dissuade others from debating the merits of the issue at hand. Beginning a statement by labeling an issue as "indisputably and unequivocally offensive" is akin to playing white-noise to prevent conversation. Canada is a free society but it is only free because people have the ability to freely exchange ideas and opinions - even if one person disagrees with something they must be permitted the opportunity for discourse or at the very least, the option to weight-in as they like. Since Yim cannot be speaking for everyone it is likely that others do not share her views. One would expect that Yim, as a comic, can appreciate the importance of free speech and even perhaps the role that stereotypes play in our world. Certainly the latter is common cannon-fodder for comedians everywhere.

Stereotypes aside, it is not inaccurate to portray a Mexican at a party by wearing a sombrero. This is apparel that is easily identified with Mexican culture but it does not have any more negative connotations than dressing as a plaid-wearing, axe-toting Canadian lumberjack would. Clearly these should offend no-one and as tasteless as some of the costumes worn by the Queen's students might be they are not indisputably offensive. A costume influenced by a race or culture is not automatically racist: someone might dress as a geisha but this is a representation of an actual role in Japanese culture and not a racist remark.

Yim also implies that "context and intentions have no bearing." This is a false proclamation: context and intention are paramount in nearly every situation from social interaction to legal proceedings. Most adults will agree that there is a great difference between being insulted by someone accidentally or on purpose. Similarly, outcome in a court of law can differ greatly depending on intent as is often the case between findings of manslaughter or murder.

Finally, with respect to statements by Carolyn Thompson, the vice-president of the university's Alma Mater Society, that events such as these "undermine Queen's ability to provide a welcoming and respectful campus environment," one must ask whether any truly challenging or divisive topics are actually debated at Queen's University or if they have banned discourse in a vain attempt to avoid offending anyone at any time.

The Night Pat Murphy Died by Great Big Sea

This was recorded sometime after December 2015 using nothing more than my cell phone and a less crappy audio recording app that isn't as prone to cutting out. I have many fond memories of listening to this song being played while having one too many beers in the Irish pubs found in Kingston, Ontario.

With apologies to Great Big Sea.

Yellow by Coldplay

This was recorded in the fall of 2015 using nothing more than my phone and some crappy audio app that came with it. For whatever reason the mic was over-driven and caused some bits to be dropped. This led a friend to remark that the recording had a slightly Nirvana-like sound. If memory serves I should have been outside cutting the lawn but the recording seemed like a better idea at the time.

Firing Line

Watching Occupy Wall Street unfold in 2011 and before that, Arab Spring I began empathize with movements that involved active protest and the risks that participants take both in regards to physical harm or in other less tangible costs. "Firing Line" was somehow the result of my ruminations.

The rudimentary recording apparatus I was using left me sounding a little stuffy (I did not have a cold) but I kept it due to the fact that it is one of my few complete songs.

Spanish Orgasm

This is one of the first songs that I recorded that I felt comfortable with sharing. It was recorded sometime in 2001 or 2002 in my off-time at the offices of Scouts Canada where I was working. I used a very simple WAV editor that came with the computers we had in the office and may have included 3 or 4 tracks with each one layered on top of the previous recording. One of my friends says it reminds him of Danger Bay but I couldn't begin to tell you where the inspiration came from.

It is admittedly a little "busy" in places but for some reason it still appeals to me.

gvfs-trash and NFS

My wife and I use a couple of desktops at home for most of our computing needs. Most of our user files (e.g., /usr/home) are stored on a separate server, shared over NFS and amounted via autofs. Said server also provides an NFS export that we use for our shared documents - stuff that we both need read-write access to. For the sake of simplicity I take advantage of the -mapall parameter in the exports file on the server. This nifty little option ensures that whomever has access to mount the NFS export read-write will read, write and delete files as a single user on the server. This effectively solves the problem of setting up more complicated permissions for file sharing between a small group of people. The /etc/exports file looks like this:

/usr/home       -alldirs                client1 client2
/srv/fileshare  -mapall=fileshare       client1 client2

The problem with this setup rears its ugly head when you're interacting with the NFS mounts on the client through Thunar, the default file manager for XFCE (I've come to appreciate a lot of what XFCE brings to the table over the past 6 or 7 years since we escaped the insanity that is Gnome3). Thunar uses some glib magic for interacting with the file system, and when a user hits the "Delete" key or picks to "Move to Trash" from the context menu, a poorly-documented gvfs binary named gvfs-trash is invoked and in both cases it is supposed to move the offending file to the user's waste bin. On the NFS mount this function failed with the following unhelpful message:

Error trashing file: Unable to find or create trash directory.

After digging around with truss to figure out what the heck gvfs-trash was actually doing and scouring the FreeDesktop.org Trash specification, I discovered that gvfs-trash is supposed to look for a directory named .Trash in the root of the NFS mount and that this directory must have the sticky bit set.

Okay. Makes sense. I guess.

# mkdir /srv/fileshare/.Trash
# chmod 1777 /srv/fileshare/.Trash

At first glance this seems to work fine. Running gvfs-trash FILE-TO-TRASH now executes without error and gvfs (and in turn glib) goes ahead and creates /srv/fileshare/.Trash/1001, puts a couple of sub-directories under the one named after my effective UID, moves the offending file and Bob's your uncle. Because we're using the -mapall option, everything is created using the user we specified on the server in the exports file (in this case the user name is fileshare).

Unfortunately the problem also occurs the second time gvfs-trash is run to trash a file. It fails again with the same damned error message. Okay, thanks gvfs.

It turns out that not only must .Trash exist with the sticky bit, but the UID directory immediately below must be owned by the user who is trashing the file, never mind that this didn't matter when we were trashing the first file. To "fix" this problem I ran the following commands:

# chown matt:matt /srv/fileshare/.Trash/1001
# chmod 1777 /srv/fileshare/.Trash/1001

Since I have a limited number of user accounts this ungainly fix appears to work, at least for the short-term.

I think the moral of the story here is that when you are implementing anything that tries to be halfway "smart" about what it is doing (in this case, gvfs-trash and the ungodly mess of glib below it), you need to be VERY careful that your process a) provides a more helpful error message when it fails, and b) doesn't work in weird and unexpected ways (in this case, working the first time but failing the second time). Generally speaking, your users shouldn't have to run system-level debugging tools and refer to the spec when easily returned and friendly error messages would otherwise save them a lot of time.