In a recent blog post, I started thinking about software as performance art, linking it back to my life as a violinist. I realised that, although I felt very definitely that software and violin are both performance arts, I couldn’t really define performance, art, or performance art. So I’m going to start by thinking about what art is. (Note that this is a deliberately self-reflective post: it’s what art is to me, not what others have thought and written about it.)

I find it’s easier to think in concrete examples rather than abstractions – so when I think of art, the first words that come to mind are sculpture, music, drawing, light. These words have an inherent sensuality: when I think of sculpture, I imagine a marble statue, but mainly by touching it and feeling the cool, smooth, slightly textured surface. When I think of music, I think of my violin: dark honey-coloured wood with mesmerising patterns that I could stare at for hours, and the scent of a luthier’s workshop. Drawing: I think of the feel of a pencil on rough paper, creating a slight ridge in the paper and the vibrations transmitting up my arm. Light: the shaft of light through a window hitting the marble sculpture, or even more heavenly, the filtering of sunlight through green leaves. There is nothing more blissful than this.

So art is physicality, sensuality – a way of experiencing the world that is deeply linked to the physicality of my body.

I haven’t said much of smell and taste, which to me are the most intimate and evocative of senses. Maybe another time – my experience of smell and taste are too personal for me to share.

How does art come to be? Is it deliberately created? By humans? Is a field of bluebells art, or is it nature? I would have said art is created by humans, but then the sunlight filtering through the green leaves…is that nature or art? Does it matter?

I think I will be broad and say that the sunlight in the green leaves is art.

And maybe this a characteristic of art: it expands and deepens our experience.

I leave you with this suggestion: find something you have never smelled and inhale its scent deeply.

Today in BRYTER’s Q4 2020 Inspiration Day, I ran a session entitled “Software as Performance Art”. It was my first tentative toward steps toward finding underlying harmony between my performances as a violinist and my career as a software developer.

I know performance is an essential part of my identity and the way I create community for myself. But I’m not sure I can even define performance – I am only confident stating its specific characteristics in the particular area of Western classical music: I walk on stage, sometimes alone but usually with friends, play music, receive applause, leave.

I think I know what art is – but again, I’m only confident in listing specific incarnations (music, sculpture etc).

I’m really not too sure what performance art even is! But did that stop me from asking if software can be performance art? Not at all, luckily.

Of course, what is software? And do I care about software or code? Does code exist only as a mental abstraction when the server is not currently running? Does it have physicality? How can you perceive it with your senses? Does it have emotion?

I think I am tentatively working toward an understanding of the code itself (including tests!), unrelated to a UI, as a form of performance art. Art, because it is creative and expressive (whether it should be beautiful is another question!). Performance, because it is not written to be languished in a museum but rather worked on, improved, enhanced.

We’ll see where I go with this!

In my spare time, I help classically-trained musicians like me transition to software developers. One of them recently asked me, “I don’t have £8k to spend on a bootcamp. Can I just teach myself to code?” Here’s my answer (disclaimer – I’m a bootcamp grad so this is not first-hand experience).

Yes, you can learn to be a developer without going to a bootcamp (or getting a CS degree). I know this, because people have done it. So let’s discuss what a bootcamp does, and how you can replicate that yourself.

A good bootcamp should give you two things:
1. A structured learning environment
2. A foot in the door at job interviews

Let’s talk about the structured learning environment. Writing software professionally generally involves working as part of a team. This almost always means using git, creating pull requests, reviewing code, writing documentation, and can also mean working in a sprint schedule, daily standups, and pair programming.

Because you do a bootcamp with other people, you have a built-in team. Different bootcamps do this in different ways – at Makers we paired daily and then had group projects in later weeks. This meant that we learned to use these critical software skills like git and were comfortable especially with pull requests and reviews.

The structured part is more obvious – you pay money to someone to create structure for you. Can you create the structure on your own? That depends on your own motivation and discipline.

I’m considering the course content as part of the “structured learning environment” and I won’t delve deeply into it here. But figuring out what to learn (as opposed to how and where) is its own challenge!

So let’s talk about job interviews. Bootcamps usually have relationships with companies and can get you past initial screening. This (in my opinion) is one of the most important things about a bootcamp – what sort of job can they land you afterward?

The good news is that you can network on your own as a developer by attending meetups, communities such as CodeBar, joining Slack groups devoted to topics you’re interested in and getting active on Twitter. (And in fact if you’re attending a bootcamp, you should do this anyway.)

And once you’ve learned a bit of code, probably the best way to build your portfolio, experience, and network all at once, is to contribute to open source projects. Find a project you’re passionate about, check that they have a good code of conduct, and dive in!

Good luck with your code journey 🙂

We have a multi-project build with the following structure:
– mainProject/heldenleben/src/
– mainProject/eulenspiegel/src/

The files in mainProject/eulenspiegel/src/main are built with a standard Gradle task and consumed in mainProject/heldenleben/src/main.

However, let’s say we needed to take the file mainProject/eulenspiegel/src/test/testHelper.kt and make it available for use in mainProject/eulgenspiegel/test/violinTest.kt.

There are 3 elements that need to happen:
1. mainProject/eulenspiegel/src/test/testHelper.kt needs to be compiled to Java bytecode
2. mainProject/eulenspiegel/src/test/testHelper.kt needs to be packaged into a jar file
3. mainProject/heldenleben/src/test needs to find and use the file created in step 2

Let’s look at each step.

1. Compile to Java bytecode
Before files are packaged into jars, they first need to be compiled to bytecode. In our case, we want to compile mainProject/eulenspiegel/src/test/testHelper.kt. Compilation should produce the corresponding classfile at mainProject/eulenspiegel/build/classes/kotlin/test/testHelper.class.

One way to do this is manually, by running the pre-defined testClasses task. However, we can combine it with step 2!

2. Package into jar file
The following code sample written in Kotlin DSL and found in mainProject/eulenspiegel/build.gradle.kts, will compile our source code and package it into a jar file. Let’s step through it.

1 tasks.getByName("assemble").dependsOn("testJar")
2 
3 tasks.register<Jar>("testJar") {
4     archiveFileName.set("eulenspiegel-testHelpers-$version.jar")
5     include("com/eulenspiegel/helpers/*") 
6     from(project.the<SourceSetContainer>()["test"].output)
7 }

Line 1 tells Gradle’s default assemble task to wait for this testJar task that we are defining on line 3. Without line 1, assemble will not fail but it will not produce the testJar output. (You can run the testJar task manually – find it under other/testJar – but then you’d have to add it everywhere assemble is used so much better to just make assemble depend on the testJar.)

Line 3 registers a task of type <Jar> with the name “testJar” – the name is a string and can be whatever you like.

Line 4 sets the name of the archive (jar) file that we are going to produce. $version is a variable created elsewhere in the build.gradle.kts.

Line 5 is optional – in this case, we only want to include a single file. Leave blank to include everything in mainProject/eulenspiegel/src/test.

Line 6 tells us to use the standard source set located at mainProject/eulenspiegel/src/test.

3. Tell mainProject/heldenleben to use our jar file
The relevant sections of mainProject/heldenleben/build.gradle.kts are below. Let’s step through them.

1 tasks.getByName("compileTestKotlin").dependsOn(":eulenspiegel:testJar")
2
3 repositories {
4     flatDir {
5         dirs("${buildDir.absolutePath.replace("heldenleben", "eulenspiegel")}/libs")
6     }
7 }
8 dependencies {
9     testImplementation("com.mainProject:eulenspiegel-testHelpers:$version")
10 }

Line 1: the standard compileTestKotlin task needs to wait for our testJar task to finish, or it will fail. (And beware – this is likely something that will be caught on CI because you’ll have a local file hanging around in mainProject/eulenspiegel/build/libs that mainProject/heldenleben can find.)

Line 3: by default, Gradle will look remotely for your dependencies. These lines tell it to look for local files.

Line 5: By default, Gradle will look in mainProject/heldenleben/build/libs for the jar file. We need to tell it to look in mainProject/eulenspiegel/build/libs instead.

Line 9: this is the line that actually creates the dependency!

Good luck with your Gradle builds and comment with your thoughts 🙂

Yesterday I had the sheepish* experience of spending a couple hours trying to work out why the code I had committed in a working state suddenly stopped working. So I thought I’d write a blog post about how to debug this mysterious situation! While some of these scenarios are less likely to happen in local development, they can definitely happen in production, so if, like me, you believe in “You build it, you run it”, this can help debugging the live site as well!

What happened to me?
I was writing code to manipulate MS Word documents. I had automated tests that checked the XML of the MS Word, but for sanity, I had a local output for the file so I could open it and visually check it. I committed my changes in a working state, went to lunch, and came back and…the tests were all green but the output file was missing the changes. I tried a bunch of things that had previously caused weirdness with MS Word (hint: MS Word is really tricky to work with), ranging from invalidating my IDE’s cache, killing all the gradle processes, wiping the output folder, and a lot of swearing. I eventually realised the problem was that I was using parameterised tests, but not parameterising the NAME of the file I was outputting…so it was overwritten with each test run, and the last run had an empty input which (correctly) resulted in no change to the MS Word document. Cue more swearing.

So let’s talk about times when things mysteriously don’t work, and what some of the causes can be.

Cause 1 – external files
If you are working with input or output files, here are some questions you can ask:
– If reading from an input file, has the file been saved before being read?
– How is the output file being named?
– Is the output file path exactly what I am expecting it to be?
– Can the data in this output file be modified by another process (check out concurrency control)?

Cause 2 – software versions
I once worked in a company with a couple different codebases, each one of which used a different Node version. If you forgot to switch the Node version, you’d get weird errors (hint: there is a way to automatically switch versions on *nix – check out .nvmrc). Some questions you can ask:
– Could switching directories cause my current software version to be incorrect?
– Does this code depend on an external dependency which may have changed its version?

Cause 3 – build issues
Your code probably relies on some built dependencies. Some questions you can ask:
– Are all the dependencies built and where I expect them to be?
– Can I verify that each step of the build process is working as expected (implicit: do I know each step of the build process)?
– Is something interfering with my build process?

Cause 4 – asynchronous issues
I recently wrote a test that reliably failed every other time it was run. The problem? Part of the test relied on an unzipping process that was a bit slower – so by the time the assertions were run, the unzipping hadn’t been finished yet and the input files weren’t present. I ran a cleanup process to delete the files, but the files weren’t present by the time that was run either – so they hung around for the next test run. Some questions you can ask yourself:
– Is there any part of this process that will take longer than other parts?
– Could the capability of my operating system / hardware be slowed by some other process?
– If my tests rely on an external connection, is the network down?
– Is a remote server down?

And when none of these questions leads you anywhere, I have also found copious amounts of swearing usually do the trick…as long as I leave it for a few hours and come back to it.

*Extending the definition of sheepish to mean “something which cases me to feel sheepish” as “sheepifying” just feels so wrong.