carnet

Thesis defense

This is an edit of the presentation I gave at my PhD defense on 20.12.2023, at Paris-3 Sorbonne Nouvelle1. The lead-up to it was a lot more stressful than the actual defense, and I think the most important aspect of it all was rehearsing reading the text out loud, and speaking it slowly. The enactment of confidence often brings confidence.

Introduction

Good morning everyone,

First of all, I would like to thank the members of the jury for being present here and providing the opportunity to discuss this work; I would also like to thank Alexandre and Nick for their assistance and guidance over these past four years, and finally I would like to thank the audience in the room, for being here.

I will now present the results of this thesis project, focusing on the role of aesthetics in understanding source code, highlighting my thought process in developing research questions and methods, and will then focus on the findings, before concluding on some further research directions.

This all started with a weekly assignment in graduate school. The prompt was “write a video game in 250 lines of code”, and the first thought that crossed my mind was: what does it matter that we write a certain amount of lines of code, if they are to be turned into a dynamic system anyways?

In the end, I handed in a short story, a somewhat naïve version of boy-meets-girl, in a bit more than three hundred lines of JavaScript. As there was no user-visible output, the only way to appreciate the work was to read its source code.

var Sun = function(){
 this.pos = 0;
 pos++;
};

var Phone = function(a, b, c){
 this.number = parseFloat(a+''+b+''+c);
};

var Fate = function(o){
 this.obstacles = o;
 this.distance = 2+Math.random()*10;
 this.inAction = function(){
  hope++;
 };
};

function wait(){
 var r = Math.random();
 var thought = memories[parseInt(r*memories.length)];

  var past;
  var present;
  past = present;
}

So this got me thinking about the kind of creativity that one can have with machine texts, and I first thought that this kind of pleasant code only happened within an artistic context, such as an art school. But, as I started to program professionally, I encountered software that would uglify, or beautify source code.

import { ref, onMounted, reactive } from 'vue';

const msg = ref("")
const HOST = import.meta.env.DEV ? "http://localhost:3046" : ""
const syllabi = new Array<SyllabusType>()

let start = () => {
    window.location.href = '/cartridge.html'
}

onMounted(() => {
    fetch(`${HOST}/syllabi/`,
        {
            method: 'GET'
        })
        .then(res => {
            return res.json()
        })
        .then(data => {
            Object.assign(syllabi, JSON.parse(data))
            console.log(syllabi);
            if (syllabi.length == 0)
                msg.value = "No syllabi :("
            else
                msg.value = `There are ${syllabi.length} syllabi.`

        })
        .catch(err => {
            console.error(err)
            msg.value = "Network error :|"
        })
})
import{_ as p,g as f,o as l,c as n,a as c,h as e,t as r,b as u,i as b,u as _,F as y,H as g,e as w}from"./Header.js";const H={class:"container p-3"},N=e("h1",null,"Home",-1),k={class:"syllabi"},x=["href"],B={class:"cta"},F=m({setup(S){const s=v(""),d="http://localhost:3046",o=new Array;let h=()=>{window.location.href="/cartridge.html"};return f(()=>{fetch(`${d}/syllabi/`,{method:"GET"}).then(t=>t.json()).then(t=>{Object.assign(o,JSON.parse(t)),console.log(o),o.length==0?s.value="No syllabi :(":s.value=`There are ${o.length} syllabi.`}).catch(t=>{console.error(t),s.value="Network error :|"})}),(t,i)=>(l(),n(u,null,[c(g),e("main",H,[N,e("div",k,[e("div",null,r(s.value),1),e("ul",null,[(l(!0),n(u,null,b(_(o),a=>(l(),n("li",null,[e("div",null,[e("a",{href:"/syllabi/"+a.ID},r(a.title),9,x)]),e("div",null,r(a.description),1)]))),256))])]),e("div",B,[e("button",{id:"cta-upload",class:"btn btn-primary mb-4 cc-btn",onClick:i[0]||(i[0]=a=>_(h)())},"Upload yours!")])]),c(y)],64))}});var O=p(F,[["__file","/home/pierre/code/commonsyllabi/viewer/www/src/Home.vue"]]);w(O).mount("#app");

From a formal perspective, the difference is quite obvious to us. The first example shows white space, full words and overall structure. The second one is a compact sequence of characters that it’s hard to make sense of. And yet, functionally, those two extracts do the exact same thing. So, again, why does it matter if it’s beautiful, as long as it works?

And, since the concept of code being beautiful and ugly seemed to be a thing amongst programmers, I started to wonder about the conditions of the aesthetic appreciation of source code?

State of the art

As I started investigating this question, a few things stood out

First, while there are several publications from the field of humanities and social sciences on code and software, these were often lacking any actual presentation of source code itself, focusing rather on an abstract conception of code, besides works within the field of software and platform studies, which I am indebted to (Montfort et. al., 2014; Cox and McLean, 2013; Marino, 2020; Paloque-Bergès, 2009).

Second, in the computer science literature, one can find multiple mentions of aesthetics and source code, taking for granted the need for such aesthetics in code, and providing only short, pragmatic justifications (Knuth, 1997; Oram and Wilson, 2007; Kernighan and Plauger, 1978).

Furthermore, the code they are referring to is quite different from the one mentioned in the humanities literature. The former tends to focus on creative uses of source code, while the latter on more productive use cases.

So what I wanted to propose in this work is a discussion of the aesthetics of source code at the theoretical level, but nonetheless based on empirical observations from a broad range of source code excerpts, in order to better understand how aesthetics operate across various, specific contexts.

In other words, can we bridge the gap between humanities, computer science and trade literature? And to start this investigation, I first needed to clarify what it is that I would be talking about.

The definition of source code was somewhat straightforward. I decided to focus on its textual component and its origin as a human creation, and which is meaningful both to a human and to a machine, since this is one of the specificities of programming languages (harman, 2010; Stallman, 2002).

It does not include machine-generated code, from compiler to LLM, in part because the original focus on writing source code as a creative act.

As for aesthetics, I focused on an approach faithful to the sensual component of the concept: one should be able to describe clearly an aesthetic property, insofar as it is something that can be immediately perceived (Rancière, 2013; Genette, 1993).

Within aesthetics, we can also disentangle experiences and judgments. First, the encounter of a particular configuration of sensual properties can elicit a response in the person who encounters it (the aesthetic experience), whom in turn decides whether such a stimulus is positively or negatively valued (the aesthetic judgment), which implies a particular standard (Carroll, 2002; Dewey, 1980).

Second, I intended as much as possible to separate the term beauty from the term aesthetic. This allows the scope of program texts to go beyond those that are considered beautiful (implying a sense of excellence), and include weaker value judgments, such as “nice”, “pleasant”, or “pretty”.

Lexical uses and semantic references

Since my intent was to reconcile theory with concrete instantiations, the primary sources of this thesis were made up of both program texts and commentaries on such texts, called meta texts.

For the program texts themselves, were subject to a close reading, a somewhat traditional approach in literature, but very rarely applied to source code (Richards, 1930).

Additionally, looking at the meta-texts, helped me recontextualize them. These meta texts are analyzed through the framework of pragmatic discourse analysis (Schiffrin, 1994). The insight here is that, even though programmers might all use different arguments and different lexical registers, and semantic references, they are still (pragmatically) talking about the same thing: writing nice, good code.

In order to distinguish them from secondary source and bibliographical references, they were selected on the basis of their object (it should be source code specifically, rather than computing in general), of their style (commentary or opinion, rather than scientific inquiry.), and of their medium (that is, not limited to traditional publishing circles, thus including blog posts, forum threads and trade conference talks).

The results from gathering and analysing this corpus was finding both diversity and unity.

At the lexical level, we can notice that there specific words and phrases used by programmers to describe what they consider to be aesthetically pleasing code, noting how it related to the program texts that they offered as an illustration of their point.

From this analysis emerged a specific group of positive qualifiers, which tended to revolve around the terms simple, elegant, clean, robust. The negative qualifiers tend to focus on messiness and materiality as factors in an aesthetic experience (note that there no mention of adjectives such as “rhythmic, touching, dreamy, or dramatic”).

At the semantic level, we see the different fields summoned by programmers in order to clarify what they mean by beautiful code, as they refer to code as…, as well as different practices.

Software engineers tend to value code that is robust, clear and unsurprising. Deeply embedded in industrial and commercial production, they are influenced by large organizational structures (whether corporate or open-source), and the need to write sustainable software.

/**
  * Enables distinct select clauses.
  *
  * @param bool $distinct
  * @return \Kirby\Database\Query
  */
 public function distinct(bool $distinct = true)
 {
     $this->distinct = $distinct;
     return $this;
 }

In comparison, hackers tend to hold values such as fitness, cleverness, and technical knowledge, focusing on their relationship to machine function, and not to other code writer, or code readers.

This example here is incredibly hard to understand, but it is a very fast way to calculate the inverse square root of a number.

float Q_rsqrt(float number)
{
    long i;
    float x2, y;
    const float threehalfs = 1.5F;

    x2 = number * 0.5F;
    y = number;
    i = *(long *)&y;           // evil floating point bit level hacking
    i = 0x5f3759df - (i >> 1); // what the fuck?
    y = *(float *)&i;
    y = y * (threehalfs - (x2 * y * y)); // 1st iteration
                                         //  y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration,
                                         // this can be removed

    return y;
}

Poets tend to value playful use of language, double-entendres and weaving in concepts outside of the computational into the computational. The code written is rarely presented to be modified, but rather exclusively read, and still today gets printed and sold on physical medium.

The code poem we see here is titled black_perl.pl, and is an example of the productions of the community of writers of the language Perl. We can note here the use of reserved Perl keywords, re-arranged in a way that suggests another meaning to a human reader, while being valid for the machine interpreter.

    #!/usr/bin perl
    no warnings;
    
    BEFOREHAND: close door, each window & exit; wait until time.
      open spellbook, study, read (scan, $elect, tell us);
    write it, print the hex while each watches,
      reverse its, length, write, again;
    kill spiders, pop them, chop, split, kill them.
      unlink arms, shift, wait & listen (listening, wait),
      sort the flock (then, warn "the goats" & kill "the sheep");
    kill them, dump qualms, shift moralities,
      values aside, each one;
    die sheep? die to : reverse { the => system
      ( you accept (reject, respect) ) };
    next step,
      kill `the next sacrifice`, each sacrifice,
      wait, redo ritual until "all the spirits are pleased";
    do { it => "as they say" }.
      do { it => (*everyone***must***participate***in***forbidden**s*e*x*)
    + }.
      return last victim; package body;
    exit crypt (time, times & "half a time") & close it,
      select (quickly) & warn your (next victim);
    AFTERWARDS: tell nobody.
      wait, wait until time;
    wait until next year, next decade;
    sleep, sleep, die yourself,
      die @last 

Scientists, especially computer scientists, tend to value insightful, theoretical code, which is rarely production ready, or interact in meaningful physical ways with the world.

This example here is a Scheme interpreter written in Scheme, and has been compared to “Maxwell’s equations of code”, meaning that there are simple, and fundamental symbolic expressions revealing deep insight about what they describe.

  (define (eval-expr env)
  (lambda (expr env)
    pmatch expr
      [,x (guard (symbol? x))
        (env x)]
      [(lambda (,x) ,body)
        (lambda (arg)
          (eval-expr body (lambda (y)
            (if (eq? x y)
                arg
                (env y)))))]
        [(,rator ,rand)
          ((eval-expr rator env)
            (eval-expr rand env))]))

So even though we have identified multiple practices and aesthetic ideals, they also often overlap, hackers might see themselves as poets, engineers might write a function in a scientific style, etc.

Ultimately, all of these practices work with the same medium, so there might be a commonality.

It turned out that the main purpose of writing aesthetically-pleasing code is to alleviate the cognitive burden of understanding exactly what the code does, what it should be doing, and how it is doing it.

It’s not so much only about creative expression as it is also about functional communication. And so if it is about understanding, then I had to understand what software really is.

Aesthetics and understanding

First of all, it helps to consider software as an abstract artifact, a notion developped by Irmak, and similar to Turner’s discussion on computational artifacts (Irmak, 2012; Turner, 2018). By existing between the realm of abstract ideas and concrete execution, we see a fundamental tension which constantly needs to be resolved.

As an artefact, it also needs to refer to the intention of the creator, and the purpose of the creation, two things which ought to be grasp in reading its source code.

Since the purpose of an artifact is how it exists in the world, what is software in relation with?

For Simondon, it can be found in the associated milieu, in the elements that it mutually interacts with. This means that understanding software does not only imply understanding intent, hardware, and everything in between, but also its representation of the world and the agency of the humans who engage with it at the source code level (Simondon, 1953).

At this point, I saw what there is to understand in software, and I then turned to how aesthetics facilitate this understanding.

The approach I chose to figure out how the aesthetics can help in understanding source code was to see how the adjacent aesthetic fields deal with cognitive engagement.

The idea was that taking a comparative approach to the different fields that code is recurringly being associated with via metaphorical devices could help me determine the aesthetic specifities of source code.

Based on the work of Lakoff and Johnson, as well as Ricoeur, considers metaphors as way to both reveal and hide features of target domains via their comparison with a source domain, as they extend beyond single words, and into whole texts (Johnson and Lakoff, 1980; Ricoeur, 2003).

Code as literature tends to focus on the textual aspect, the phenomenological fact that we read code above anything else. The first parallel made is with poetry, and the ability of poetry to bring the unthinkable into the realm of the thinkable operates a form of compression, packing the most meaning into the least amount of lexical tokens (Mateas and Montfort, 2005; Heiss and Gabriel, 2020; Turner, 2006).

Additionally, we can point to the spatial implications of literature, in particular through Marie-Laure Ryan’s work, and the ability of written prose to suggest mental spaces, to enable perceptual modeling, to support worldbuilding or explore stories, as in interactive fiction (Ryan, 2021).

class love{};

void main(){
    throw love();
}

And yet, research in cognitive neuroscience has shown that the neural mechanisms at play when one reads source code are not exactly mapped to the the neural mechanisms activating when reading prose. So indeed, code is kind of like text, but not exactly text.

Code as architecture suggests that it is no longer about writing code, but about building code.

First, function is an essential component when judging the quality of a building. While there are some categories of buildings that have no function beyond their appearance (pavillions and follies), a building’s function, while hard to pinpoint exactly, remains central in judging a building’s quality.

A building’s function also depends on how humans use it, how they inhabit it. Here, architecture does not consider a construction not as an abstract plan to be realized, but as a structure to be built up in pieces (or patterns, in the software engineering linguo), then modified through use. The habitability of a structure thus becomes important (Gabriel, 1998; Schummer, 2009).

#define	PMC_VERSION_MAJOR	0x03
#define	PMC_VERSION_MINOR	0x00
#define	PMC_VERSION_PATCH	0x0000

/* * Kinds of CPUs known */

#define __PMC_CPUS() \ __PMC_CPU(AMD_K7, "AMD K7") \ __PMC_CPU(AMD_K8, "AMD K8") \ __PMC_CPU(INTEL_P5, "Intel Pentium")	\ __PMC_CPU(INTEL_P6, "Intel Pentium Pro") \ __PMC_CPU(INTEL_CL, "Intel Celeron") \ __PMC_CPU(INTEL_PII, "Intel Pentium II") \ __PMC_CPU(INTEL_PIII, "Intel Pentium III") \ __PMC_CPU(INTEL_PM, "Intel Pentium M") \ __PMC_CPU(INTEL_PIV, "Intel Pentium IV")

// ...

/*
 * struct pmc_mdep
 *
 * Machine dependent bits needed per CPU type.
 */

struct pmc_mdep
{
    uint32_t pmd_cputtype; /* from enum pmc_cputype */
    uint32_t pmd_npmc;     /* max PMXs per CPU */
    uint32_t pmd_npmc;     /* PMC classes supported */
    struct pmc_classinfo pmd_classes[PMC_CLASS_MAX];
    int pmd_nclasspmcs[PMC_CLASS_MAX];

    /*
     * Methods
     */

    int (*pmd_init)(int _cpu);   /* machine dependent initalization*/
    int (*pmd_cleanup)(int _cpu) /* machine dependent cleanup */
}

Finally, the role of craft is a crucial reference in how programmers refer to what they do, and how to do it well: it is about being true to the material that you are working with, about putting in the forefront the unspoken/tacit knowledge component that is considered essential to doing something well. It implies direct, skillful and bodily engagement (Martin, 2008).

Finally, code as mathematics propose three different kinds of aesthetic experiences.

For the first two, beauty in mathematics is split between either an appreciation of beauty of the concepts themselves, or an appreciation of how to demonstrate (or proof) such a concept. Aesthetic pleasure can be found either in the theorems, or in the proofs (Rota, 1997; Hardy, 2012).

The third approach is when we consider, with Natalie Sinclair, aesthetics as a heuristic. Indeed, the way things look seems to indicate that one is on the correct, or right path towards achieving one’s intended goal, and thus serve as a guide for mathematicians to organize their thoughts. In a sense, the better it looks, the truer it is (Sinclair, 2004).

(* OK *)
let get_hp m =
    match m with
    | {name=n; hp=h; ptype=t} -> h

(* better *)
let get_hp m =
    match m with
    | {name=_; hp=h; ptype=_} -> h

(* better *)
let get_hp m =
    match m with
    | {name; hp; ptype} -> hp

(* better *)
let get_hp m =
    match m with
    | {hp=h} -> hp

(* best *)
let get_hp m =
    m.hp

Findings

So, taking all of these different metaphorical mappings, this allowed me to highlight some of the ways in which aesthetics and cognition are related in the field of programming, and how function is involved.

First, source code needs to represent multiple entities alternatively, or simultaneously, nonetheless within the same formal artefact (i.e. the source code file(s)).

Source code aesthetics offer a resolution to this issue of context-switching, by allowing the compression of meaning from different levels of abstractions, and different domains of reference, either conflating them or clearly delimitating them.

This process of compression relates to expressivity in poetry, enlightenment in mathematics, and the recurring aesthetic ideal of writing “elegant code” in programming, all different ways of saying “doing the most with the least”. Whether in code poetry, software engineering, computer science or hardware hacking, it is about the choice of syntax which can, through a process of layered meanings, evoke multiple things at the same time, from the computer type of a variable, to the real world entity the variable refers to, or the programmer’s knowledge of the language.

package main

import (
	"fmt"
	"math/rand"
	"time"
)

func recall(date int) {
	random_delay := (rand.Int() % 5) + 1
	time.Sleep(time.Second * time.Duration(random_delay))
	fmt.Println(date)
}

func main() {
	go recall(2045)
	go recall(2046)

	fmt.Println("We're done!")
}

/*
-- possible output #1:
2045
2046
We're done!

-- possible output #2:
2046
2045
We're done!
*/

As a means of translating intent between world, machine and human, source code aesthetics address the requirement of meaning mulitple things, while attempting to focus the reader’s attention as little as possible as on itself.

Another aspect relates to the structure of the code. As programmers peruse the program text non-linearly, they need to switch between levels of abstractions, not just in the same statement or token, as we have just seen, but across statements in the program text as well.

What this means is that the formal presentation of program texts enable a situational awareness This organization of the levels of abstraction, mainly seen at the statement- and block-level facilitates conceptual symmetry: that which does the same thing should look the same.

def _load_player(self):
    """Load the configured video player and return an instance of it."""
    module = self._config.get('video_looper', 'video_player')
    return importlib.import_module('.' + module, 'Adafruit_Video_Looper').create_player(self._config, screen=self._screen, bgimage=self._bgimage)

def _load_file_reader(self):
    """Load the configured file reader and return an instance of it."""
    module = self._config.get('video_looper', 'file_reader')
    return importlib.import_module('.' + module, 'Adafruit_Video_Looper').create_file_reader(self._config, self._screen)

This situational awareness, or the proper structuring of code to facilitate the location of one’s current position in the overall mental model of the software, also implies navigational awareness. Since those texts are more often dwelled into rather than linearly read, meaning that the possbility for the evolution of reader attention is multidirectional, the semantic nature of the syntax, statement and blocks should be flexible enough to be able to make sense from multiple perspectives, all the while being consistent enough to make sense on its own right, which I call conceptual integrity.

At the very start of this project, I assumed that beautiful code was disinterested, non-productive code. Then I thought that beautiful code was only functional code. In the end, the notion of function turns out to be more complex.

I ended up qualifying the relationship between aesthetics and functionality, it can be as a mutual reinforcement. That is, in the context of source code, the aesthetics of an artefact are improved by its functioning, all the while the artefact’s function is highlighted by its aesthetic features.

There is also not a single function, as source code can have different purposes or intents. A source code’s function can be to describe correct software, but also to decribe some concepts, whether computational or poetic, or even to hide its actual machine function, depending on the context in which it is written and read.

This taking into account the context of reading, especially in the aesthetics of engineering, also allows us to reconnect aesthetics to ethics: by taking into account the background, expectations and needs of the reader, one enters into an altruistic relationship of easing a cognitive burden for the next person who needs to engage with the work. If you see nice code, it probably means that someone cared.

Implications

A first implication concerns source code as the infrastructure for our contemporary knowledge ecosystem.

More and more media, from text to sound and video, is now accessed via software.

As such, digitally-encoded texts, such as academic publications, technical documentation, collaborative wikis, news investigations, or electronic literature, can also be subject to some of the aesthetics of source code, transposing concepts of levels of abstraction, conceptual symmetries, conceptual integrities and habitability in user-facing experiences.

As we consider that digital texts might not be read, in the usual sense of the term, but rather multidimensional structures travelled through, explored and inhabited, this opens further possibilities to think about the presentation and modification of digitally-encoded meaning as they contribute to creating mental models in their audience’s minds.

Finally, I have tried to sketch out an outline as to how one might go about studying diverse excerpts of source code, focusing on similarities as much as on differences. By developing further methodological and analytical tools, this suggests an other field of research: rather than looking at computer through the prism of human comprehension, we could look at humans through the prism of computers.

What is the worldview of a compiler? What do programming languages have to say about our conceptions of the local and the global? What do we learn about us when we study the source code of an operating system?

These are all research directions that I intend to investigate further, but for now I thank you for your attention, and am looking forward to our discussion.


  1. There’s a similar endeavour by Margot Mellet defending her thesis on the physicality of writing at blank.blue↩︎