The emerging field of software studies (and micro-annexes like “code studies”) shows a remarkable interest in code obfuscation (e.g. here, here, and here), a fun practice for creative programmers that plays on the fact that source code is text and can therefore be endlessly transformed (there are also more serious uses for obfuscation, generally in situations where source code is visible by design, e.g. JavaScript on the Web). While the practice of making a program’s source code unreadable without breaking functionality is indeed a way of approaching software from a potentially revelatory angle, I am somewhat astounded by how much attention humanities scholars pay to an exercise that is diametrically opposed to what 99% of all programmers spend considerable blood, sweat, and tears on every day, namely to make their code readable.

Code obfuscation as creative and playful practice for expert programmers speaks to the humanities’ interest in the original, the artistic, the deviant, and the critical but there is a real danger of losing connection with the mundane practice of writing software, where considerable energy is spent on writing code in a way that other people can easily understand it and, perhaps even more importantly, that a programmer can understand it quickly herself when coming back to a script or module weeks or months after it was written.

As most programmers will attest, the considerable difficulty of programming lies not so much in the “programming” part but in the managing of large amounts of stuff: complex architectures that span over many modules, huge APIs and libraries that provide highly specialized functionality, programming languages with always growing numbers of comfort functions (just look at how many array functions there are now in PHP), pages and pages of (sometimes badly written) documentation, different versions of basically everything, and – of course – the large amounts of code we ourselves and the people we work with have written, not so rarely under considerable time constraints, which leads of course to less than stellar code. The logistical dimension of programming is considerable.

SVN systems, powerful IDE’s (for somebody like me who only programs a couple of hours per week, autocomplete and integrated documentation are simply a godsend), and better development methodology obviously make the task of negotiating this massive environment a lot more bearable, but these tools are not eliminating the need to read code all the time to understand what’s going on. That’s why we try to make it readable as we write it and good refactoring (going over one’s code after the functionality is implemented) treats readability as a priority. But still, every programmer I know has, at one point in time, decided to write a library or a program herself simply because she didn’t want to experience the excruciating pain of reading somebody else’s poorly written code. This is how bad things can get.

Computer Science literature (like Steve McConnell’s classic Code Complete) and the Web are full of guidelines on how to write readable code and recommendations are intensely discussed and can be extremely detailed. I would like to argue here that one can learn as much – or more – about software by looking at strategies for readability than by looking at obfuscation. Some things are rather obvious, like choosing good names for modules, classes, functions, and variables; or like code indentation, which some programming languages have even made a requirement. Good commenting seems to be rather evident as well but there are many different schools of thought on that and automated comment generation in certain programming editors has not lead to real standardization. In general, while there is certainly wide agreement on the need for readability, the persistence of differences in style makes it clear that this is largely a question of convention and therefore depends on normative agreement rather than on simply finding the “best” technique.

But what I find most interesting about the question of readability is that beyond the cited elements lurk even more difficult questions that concern the borders between readability and architecture and between readability and complexity. Ed Lippert for example writes: “Don’t write ‘clever’ code; the maintenance programmers don’t have time to figure out your cleverness when it turns out to be broken.” This points to some of the basic tensions in modern software design and engineering: while programmers learn to value elegance, efficiency, and compact code, the requirements of large teams with a high degree of division of labor and the general speed-up of hardware can make readability a higher priority than execution speed or compactness. This can also mean to not use certain obscure functions or syntactical conventions. Consider these two examples in JavaScript:

variable1 = (variable2 == 10) ? 20 : false;

and

if(variable2 == 10) {
  variable1 = 20;
} else {
  variable1 = false;
}

These two elements are functionally equivalent; the first one however is much shorter and, especially for less experienced programmers, more difficult to read and understand.

Another question concerns when and how to divide code into functions, objects, modules, etc. Dustin Boswell and and Trevor Foucher’s Art of Readable Code for example recommends to “extract unrelated subproblems” by moving the code into a subroutine. While this may be straightforward in many cases, what the “reader” needs to know to understand the code can vary a lot from one case to another. Creating subroutines can certainly help with readability (and make code more easily reusable), but it a) means that the reader has to track down the subroutines and b) may make the code more complex simply because the subroutine may take into account different use cases that have to be distinguished. While redundancy is often considered a crime, it can have benefits when it comes to readability.

The subject of readability can be (and is) discussed infinitely but what is significant from a software studies’ perspective is that the problem points to the incursion of a social and economic context into the practice of programming. Not only do we ask “what is my code supposed to do?”, but also “who is going to read my code?”, “will other people work with my code?”, “is this something I will reuse?”, “how important is execution speed?”, and so on. While studying obfuscation points to the duality of computer code as text and machine, the readability question reveals it as caught up in various contexts that have to be negotiated in the practice of programming itself. That code is executable is the technical condition for software. That code is readable is not a requirement on the same level; but it has become a major aspect to a program’s capacity to become part of an increasingly structured professional practice.

Post filed under algorithms, computing, software studies.

5 Comments

  1. At the Software Fun (Funware) symposium Michael Murtaugh presented his paper on the principle of Do (Not) Repeat Yourself related to the idea of good versus bad programming. Clear versus obfuscated? In relation Wendy Chun and Andrew Lison talked about the ‘fun’ of obfuscation.

    http://www.annehelmond.nl/2010/12/01/funware-michael-murtaugh-do-not-repeat-yourself/
    http://www.annehelmond.nl/2010/12/02/funware-wendy-chun-and-andrew-lison-so-fun-its-not/

  2. In my book, The Philosophy of Software, I use obfuscated code not as a case of unreadable reading, or even for the spectacular, rather I use it as a stepping off point to talk about the materiality of code through the notion of software *testing*. Testing is a hugely important part of the software lifecycle and links the textual source code to the mechanic software and creates the feedback cycle between the two.

    This I then link to Callon and Latour (via Boltanski and Thevenot) to the notion of ‘tests’ – implying that it is crucially the running of these obfuscated code programs that shows that they *are* code at all (legitimate tests), rather than gibberish. The fact that they are unreadable by humans and yet testable is very interesting, more so as they become aesthetic objects in themselves as the programmers start to create ASCII art both as a way of making the code (unreadable), now readable as an image, but also adding another semiotic layer to the meaning of the code’s function. Equally I discuss the nature of scoping that these tests imply (tests of strength) and the fact that the mutability of code is constrained through limits placed in terms of the testing and structure of the competition, but also how these restrictions which serve as what Boltanski and Thevenot would call ‘tests of strength’, which themselves are reflexively played with in terms of clever programming that works at the borderline of acceptability for programming practices.

    • Bernhard says:

      Hi David,

      Yes, I think obfuscated code is really quite revealing when it comes to understanding what programming languages are and how they function in terms of logic, but my point is that as practitioners, we are constantly struggling against the “creeping obfuscation” that is the result of time constraints, differences in style between programmers, bad habits, sheer complexity, forgetting, and so on. Trying to make our code readable is so much part of what we try to do every day when writing software that I think that it merits some attention as well. The playful aspects of programming should not make us forget that most programming work is real drudgery – shifting data from A to B, designing interface states (the most horribly dull work in my view), etc. – that is embedded in commercial pressures and cost constraints. Writing readable code is part of the logic of control and efficiency (building things that work) that computation is largely embedded in – including open source for that matter… Unit tests and similar techniques can indeed be approached from the logic of computation and the theory of software design, but there is also the fact that, in practice, they are used to discipline bad programmers into writing working code. A management technique for getting at least some productivity out of the 50+% of CS students that get a degree without actually being able to design a non-trivial piece of software. Looking at this “in practice” – which is really not very glorious – is what I’m suggesting. I guess that I’m just a bit cynical after years of writing code for food and teaching programming…

      cheers!
      B.

  3. I completely agree. I don’t think obfuscated code would be a good way in for teaching so we completely agree there 🙂 However for humanistic readings I think tests are a nice abstraction as an alternative (or in addition to) the close reading of source code.

    I talk about some of the kinds of things I think would be useful in a humanities perspective for teaching some notions of ‘code’ through the idea of ‘iteracy’. This might not be useful for CS students, of course, who require a much firmer grasp of computational principles, but this you might find interesting:

    http://stunlaw.blogspot.com/2011/09/iteracy-reading-writing-and-running.html

    and an attempt to implement the ideas in Zajal code:

    http://stunlaw.blogspot.com/2012/02/iteracy-attempt-to-read-write-and-build.html

    I wonder if Livecoding might be a nice way into teaching programming though… 🙂

  4. We might also note that the drudgery of programming is constantly being abstracted away through clever layers, such as Ruby, but also through the use of IDEs and other visual programming techniques. Do I think that the drudgery of programming is equivalent to the drudgery of working in a factory, not at all, and machine assisted programming allows the creativity of the individual in even the most ‘boring’ jobs. In fact often ‘boring’ programming jobs are extremely well-paid due to the difficulties of retaining staff (and options are often made to connect it to more exciting programming practices). So there is definitely some interesting work to be done in mapping the way in which creativity, programming language, abstraction layer, and so forth plays out in people’s everyday experience of programming practice.

    Regarding management techniques, I think you are right that Taylorist approaches are used in the software industry, however one only needs to look over the literature to see the lack of success in this area. Software engineering is still a relatively recent discipline and there is still, today, a reliance on the super-human efforts of a small cadre of programmers within a project a la Ullman’s The Bug. The lack of a silver bullet in software programming still eludes the managers, who are therefore reliant on programmers who know far more about the system they are working on than any level of management. Whilst not wanting to be too optimistic or celebratory about this, after all programmers can, and often are, very mercenary in these situations, nonetheless, this is an interesting moment for those interesting in studying software, and of course, the potential for radical politics also remains radically open.

Leave a Reply

Your email address will not be published. Required fields are marked *


Tech support questions will not be answered. Please refer to the FAQ of the tool.