Software Elegance
Jakob Jenkov |
Software Elegance is my term for the functional elegance of software. In 2008 I was studying software usability extensively, and I came up with a short set of guidelines for achieving functionally elegant software. In fact, I formalized these guidelines in a small project about Software Elegance which was my last project during my Masters in IT from ITU in the autumn semester of 2007.
In the years since I formalized the guidelines they have been very helpful for me when designing software, both GUI, services and APIs. Plus, these guidelines have been really helpful in evaluating third party software. The guidelines immediately give me some dimensions along which to evaluate the software. Having benefitted from these software elegance guidelines for a long time they have proven themselves useful, so I decided to share them with you.
Elegance Defined
Before I list the software elegance guidelines I want to more clearly define what I mean by elegance. By elegance I mean:
Making something hard seem easy, almost effortless.
This is what a ballet dancer does when standing in a very difficult and physically demanding position, as if it was the most natural, effortless position to stand in.
This is what a free climber does when climbing up a vertical cliff as it if was a regular latter.
Functional, not Aesthetic Elegance
It is important to underline that I am talking about functional elegance and not aesthetic elegance, when I am talking about software elegance. First of all, software aesthetics have a tendency to change over time, like the clothing fashion industry. Today flat icons are cool, tomorrow 3D icons are cooler etc. Software aesthetics also seem to be more subjective. This tendency to change and to be more subjective makes it hard to say anything objectively true about aesthetic software elegance.
Second, I am not educated in graphical design so I am not really that well equipped to pass judgment on aesthetic elegance as it is.
Of course, you cannot completely seperate function and aesthetics. A visually clear and appealing user interface will naturally feel more functionally elegant too. However, my focus is still on functional elegance.
Software Elegance Guidelines
The software elegance guidelines can be summed up in a single sentence:
Solve my problem, with minimal effort from me, and don't get in my way.
As you can see, this sentence defines elegance as how the user feels when interacting with the software. It is a subjective experience, but with somewhat objective measures.
The simple sentence above contains three rules:
- Solve my problem
- With minimal effort from me
- Don't get in my way
I will explain what these three rules mean in more detail in the following sections.
Solve My Problem
The rule solve my problem means that the software must solve the user's problem. When a user has a problem and evaluates a piece of software as a potential solution to that problem, the software will either solve the whole problem, solve part of the problem, or nothing at all.
Often, the problem is not really a single, concrete problem, but rather a problem space. For instance, reading data from, and writing data to a database. Or keeping track of a project. Or optimizing investments for bank clients. Or enabling users to connect and communicate.
Inside a problem space there are typically many smaller concrete problems to solve. The more problems of the total problem space a given piece of software solves, the better. The more it will feel like the software "solves the user's problem".
With Minimal Effort From Me
The rule with minimal effort from me means that the problems the software solves should be solved with as little effort required from the user as possible. As little looking and reading, as little moving of the mouse, as few clicks and as little keyboard typing as possible. In other words, as little mental and physical effort as possible.
Requiring minimal effort from the user is when software goes from feeling like a "tool that gets the job done" to feeling elegant. The easier it is to get the work done with a given tool, the more elegant the tool will feel.
Don't Get in My Way
The rule don't get in my way means that the software should not make it impossible or disproportionately harder to solve some of the problems in the problem space. You may think this rule is obvious, but I have often seen software (both APIs and GUI apps) that were so focused on solving only one part of the problems in the problem domain, that other problems were completely unaddressed.
As example, imagine a JSON parser which can only parse JSON into Java objects, but in your case you do not really know what the JSON looks like ahead of time, so you cannot really create a Java class to represent the JSON. Such a JSON parser would solve the problem of parsing JSON into Java objects, but prevent you from parsing JSON into a more dynamic structure - which is what you need in this case. Such a JSON parser would "get in your way". It only solves part of the problems in the problem space, and it prevents you from solving other problems in the problem space (unless you supplement it with yet another JSON parser).
Software Elegance Example
To illustrate how the three rules can be applied during development, I will take you through a very simple example. Imagine you are developing a method that needs to calculate the sum of all byte values in an array. The first version of this method (in Java) might look like this:
public int sum(byte[] bytes) { int sum = 0; for(int i=0; i<bytes.length; i++) { int val = bytes[i]; sum += val; } return sum; }
This version solves the summing problem for anyone who has an array of bytes to be summed. But, how about
users that need to sum only part of an array? That is not possible with the above method. Thus, the above
method is not really living up to rule no 1 and rule arguably rule no 3. In order to sum part of an array,
I would have to copy that part to another array, and pass that as parameter to the above sum()
method. You could argue that is "getting in my way", and thus a violation of rule no. 3.
Here is a different version of the previous sum()
method that enables the user to sum a part
of a byte array:
public int sum(byte[] bytes, int offset, int length) { int sum = 0; for(int i=offset, n=offset + length; i<n; i++) { int val = bytes[i]; sum += val; } return sum; }
With this version a user can sum either part of all of an array, like this:
byte[] byteArray = ... // get byte array from somewhere int sumAll = sum(byteArray, 0, byteArray.length); int sumPart = sum(byteArray, 10, 20);
This version of the sum()
method no longer limits the user from summing either part or all of
a byte array. But, if you have to sum all of the byte array, the code is a bit more verbose than what it
could be, because you still have to pass the offset and length (no of bytes to sum) as parameters. This is
still a slight violation of rule no. 2, "with minimal effort from me". Let's overload the sum()
method with one more version, to make it easier to use when you want to sum all bytes in a byte array.
public int sum(byte[] bytes){ return sum(bytes, 0, bytes.length); } public int sum(byte[] bytes, int offset, int length) { int sum = 0; for(int i=offset, n=offset + length; i<n; i++) { int val = bytes[i]; sum += val; } }
Using the sum()
method now looks like this:
byte[] byteArray = ... // get byte array from somewhere int sumAll = sum(byteArray); int sumPart = sum(byteArray, 10, 20);
That's a bit less effort than before.
As you can see, using the 3 rules of software elegance to guide your design can help you make the software easier to use.
Software Elegance is an Iterative Process
Achieving elegance in your software should be an iterative process. Do not try to make your software 100% elegant from the beginning. Doing so would result in delayed releases. Instead it is often better to improve the functional elegance aspect from release to release, just like you would with any other part of the software.
Additionally, getting feedback from users is also necessary. Users will tell you what they think could be made easier, or what problems your software is causing, or is not solving etc. To take this feedback into consideration you need an iterative approach to implementing functional software elegance.
Don't Make Me Think
Steve Krug's book about web usability titled "Don't Make Me Think" is one of the more popular books on web usability. The title is supposed to sum up his usability philosophy in a single sentence. Don't make me think. Don't make the user think. Make the software intuitive.
While I agree with that statement, I think it is too narrow. You also do not want to make the user "work". And you don't want to solve one problem only to create another. That is my sentence contains three broader rules, and not just one.
To be fair to Steve Krug's book, it does cover a lot of useful tips. If anything, perhaps a broader title would be more fair to its content - but a longer title would perhaps be too long for a book cover.
Tweet | |
Jakob Jenkov |