In 2019, after several years as a cellist and orchestra manager, I started learning to code. While I didn’t have a technical background, I found I had developed a number of coding-adjacent skills through studying music. One practice I’ve adopted from music learning has helped me deliver code with fewer mistakes, better choices, and more efficiency: a thoughtful process.
If you’re not familiar with the process of learning classical music, you might be surprised by how many intricate problems we encounter, many of which we examine before even touching the instrument. I’ve found a similar approach is valuable when working in an enterprise code base full of interdependent systems. With this in mind, I’ve broken down the parallel music learning and software development processes into several stages.
Setting up your space
It’s a common joke among musicians that we can’t practice if our room isn’t clean. We take our space seriously, knowing how much it can distract or unsettle us. In music there’s a “flow” state very similar to that of coding. But that doesn’t just happen by itself. Reaching a focused mindset can take a really special set of circumstances, which are unique to you as a person, and sometimes fluctuate day-to-day. As a first step in the process, it’s helpful to take a moment and assess what environment will help us do our best work.
At music school, I often needed the accountability factor and lack of distractions of the school practice room. Most music schools have a block of tiny rooms, empty except for a chair and a music stand (if you’re lucky), and their only purpose was individual practice. That whole section of the school was full of practicing students. These days, the equivalent is taking my laptop to a cafe, where my mind is far away from the dirty dishes in my kitchen and anything else that could distract me. Or, I might just need to do those dishes, clean my desk, make some coffee, turn on a lofi playlist and the noise-canceling headphones, and enable do-not-disturb mode. Either way, this first step of the process can impact how effective the rest of the process will be.
Understanding the context
A lot of classical music was written under interesting political, romantic, or social circumstances. For example, Shostakovich’s 7th Symphony was written in the Soviet Union as World War II broke out and became a symbol of resistance to “enemies of humanity.” This knowledge impacts how we perform the pieces – in the Shostakovich example, we would bring in intensity and sometimes sarcasm. When learning a piece, we would also consider the composer’s typical style, and the nuances in the instruments of the period, which would limit or inform our technical choices. Some musicians refer to learning a piece of music as “studying” it, which is an apt description due to the research involved in the process.
Programming requires a similar exploration of context, ideally early in the process. You might carefully consider the requirements or expectations of a ticket and ask clarifying questions. You want to understand how your work fits into the bigger picture of feature delivery, and why it is important. In both music and programming, we are asking the same questions: What are the intentions behind the technical direction? What is the big picture? What exactly are we trying to accomplish?
Consulting the experts (and the docs)
Are there existing solutions to this problem? Don’t reinvent the wheel. If there’s already a tool or design pattern or interface for this, we should use it. That might take some discovery.
When I was learning a new piece of music, I would get on YouTube and check out performances by a variety of other cellists. Everyone has their own style and approach, so it was a good way to open my mind to all the possibilities of how to play the piece.
This step of the software development process might include:
- Looking at existing solutions to similar problems in your code
- Searching previous PRs and company documentation for the topic
- Talking to other engineers on your team about how this has been done in the past, and why
- Googling, Tweeting, etc.
Getting in there
In music, this is probably the most fun step in the process, and the least fun for someone else to hear. I would sit down with the cello and the sheet music, and start playing through it (badly). I would stay open-minded, not committing to any musical choices. The goal would be to discover the biggest challenges, and how the piece physically feels on the instrument in a general sense. I might mark some ideas in the music in pencil.
If I were programming, I would be going through existing code, assessing all the possible dependencies and the biggest challenges. I might write some high-level pseudocode or notes. I could check out existing test data for a similar method or feature and see how it maps to the code. If possible, I would walk through the user flow that is impacted by this code, and step through the code with the debugger. Again, no commitments yet, just open-minded exploration.
Making a plan
OK, now that we have a lot of information to work with, we’re ready to come up with an approach. Musically, this means we decide where the most important moments are, and what we want to “say” as an artist with the piece, what we want the audience to feel or think when they hear it. More practically, how much time do we have to learn this? We might want to time-box certain parts and move on to make sure we can cover everything, or plan which days we work on which parts of the structure. We have already assessed what we think the biggest challenges will be, so we could plan to focus most of our energy there.
In this stage of the programming process, we would come up with some testing ideas and consider edge cases. We could look at our deadlines and determine what our MVP should be, or map out some milestones. We would decide what to tackle first – start with the easy wins, or the biggest challenges. This might be a place where we break the work into tickets, or mentally divide the ticket into sections that can be tested independently. And now that we know our dependencies, we can decide whether to write new code or extend existing code, and plan the structure.
At this point in the process, we have a high-level plan and an end goal. Now how do we get from Point A to Point B? Here are a few of the strategies I use, in both music and coding:
- Break it down into tiny pieces. In music, this means working on a few measures at a time. When you have part one down, work on part two, then put one and two together. When that’s working, figure out part three, and put parts two and three together, then parts one to three (and so on). I often do the exact same thing when I code!
- Brainstorm a few ways you could solve the problem, then choose a good option and give it a try. For example, if it’s a big “shift” (a lot of physical distance on the instrument to cover), you could use any combination of fingers as a starting point and ending point. Each option would have unique pros and cons impacting sound, accuracy, and speed. If one way isn’t working well, you have several more options to choose from. Same with coding – there are many ways to solve even simple problems, so it can be helpful to start with several ideas and assess pros and cons.
- Try working backwards instead of forwards for a different perspective. Sometimes in coding and in music we know where we want to end up, but not where to start – so why not start with what we know?
- Ask for help or ideas from a mentor or friend. This might be built into the environment, like music lessons or coding mentorship, or you might have to reach out to a colleague.
- Limit the time you spend on one problem so you don’t have time to get too frustrated or lost in the details. Try setting a timer for 20 minutes. Take a break and practice diffuse thinking. When all else fails, call it a day and come back tomorrow with a rested mind.
Bringing it all together
The problems are solved! Now we can put it back together and start refactoring. On the cello, this is where I would play larger sections through, make sure I am amplifying those important moments that I planned, and strengthen the “character” (AKA vibes) of the piece. In my code, I would be stepping through the flow that I wrote, checking against my company style guide, unit test suite, and static analysis tools, maybe improving variable or function names, and DRY-ing it all out.
This is arguably one of the most important parts of the development AND music learning processes. In music we have several avenues to challenge our assumptions and learn how we can improve. Weekly private lessons are essential to a college performance degree; lessons are essentially an intense session of 1:1 feedback with a professor, often with the expectation that you will immediately adapt to their suggestions and build on previous feedback to refine your performance. Closely related are master classes, feedback sessions in front of an audience; and chamber music coachings, similar but with a small group such as a string quartet.
For the development process we have code review and pair programming (in addition to tests and static analysis, which can also give great feedback). Just like in music lessons, the key is adapting to the feedback, both from this project and previous projects, into our work, to refine our code and build on our knowledge. Receiving feedback can be difficult – no one likes to be wrong, and we tend to get attached to our choices – but I try to treat it just like I would on cello: a critical part of the path to a better outcome.
Performing / Deploying
I don’t know about you, but I never feel like my code or my music is ever truly “done.” I’ll probably look back at my finished product in a year and notice improvements I could make (which is a milestone of growth in both careers). But we have to balance our desire for “perfect” with deadlines and deliverables. We have to decide what is “good enough” – what we can stand behind and feel confident about, knowing that it’s short of “perfection.” I often remind myself that 100% all the time is unrealistic. So, let’s call this the final step in the process, knowing that we will continue to grow after this project is finished.
Of course, we can’t talk about deploying, or performing, without talking about failure. All the processes in the world can’t prevent human mistakes; they happen to all of us. But if there’s anything I’ve learned in music, it’s that The Show Must Go On!
The process I’ve described is pretty granular, and some development work isn’t so complex that it needs to be broken down this far. But when I’m facing a big project, not sure where to start, or feeling overwhelmed, it’s a great reference for me. I hope it is for you too.
Happy holidays! If you need a soundtrack to get you in the spirit, I have a recommendation 😉