Music and Design Patterns
Posted on March 24, 2008
Filed Under Computer Science |
Or, an interesting but lengthy analogy. To skip straight to my point, click here.
Debating Design Patterns
Design patterns are a problem. Well, not exactly. Design patterns are extremely useful, as they are just common solutions to common problems. That sounds reasonable to me. So, what’s the issue?
For one, their misuse is expensive. Jeff Atwood, for one, argues that they introduce unnecessary complexity into code, and that there are frequently other alternatives that can be considered without cracking open the G.O.F. book.
On a similar note, M.J. Dominus has a presentation on overcopying/underthinking design patterns. He argues that the accepted use of design patterns has turned programmers into macro-using robots. He concedes that design patterns are very useful, and that the people who have written extensively about them are either very smart or have great foresight. Implementations should be suited to the problem at hand, not copied and pasted from a book.
Another deeper view of the issue is that design patterns should be invisible to language. Peter Norvig wrote a very good presentation describing design pattern implementation levels:
Level of Implementation of a Pattern
- Invisible: So much a part of language that you don’t notice. (e.g. when class replaced all uses of struct in C++, no more “Encapsulated Class” pattern.)
- Informal: Referred to by name, but must be implemented from scratch for each use.
- Formal: Implement pattern itself within the language; Instantiate/call it for each use; Usually implemented with macros.
Lisp, he claims, is so malleable that the language itself either automatically supports design patterns of other languages (such as the Abstract Factory pattern,) and that the macro system is so powerful that the language can change to support new design patterns.
Unfortunately for modern computer science, not everyone is using a Lisp-like language. In fact, the opposite is true. We have plenty of incomplete languages, and millions of coders using them. So, how do we react as a field? Two (not necessarily mutually exclusive) options are as follows:
- We can be happy that our language solved all problems except adoption 87 years ago.
- We can try to help out the average programmer make the software we use every day better.
At the end of the day, we need to try to accomplish #2 one way or another, whether it’s by getting everyone to program in Lisp or not. Education is one of the most practical ways to help make saner uses of design patterns. We need to find and praise elegant implementations of common design patterns. Why do I think this? Because of my experience with guitar.
Music
Throughout high school, I took guitar lessons with Steve Johnson (he’ll appreciate the publicity,) a musical jack-of-all-trades. I started lessons as a bumbling, tone deaf idiot, and he transformed me into a competent, semi-tone deaf idiot in four years. Because of his teaching focus, I learned that the parallels between math, programming, and music are endless. In this particular instance, I want to examine the focus of my guitar lessons.
In the beginning, I was promised that the first few months would be hard, and he was right. The name of the game was rote memorization. All of the scales. All of the modes of the scales. All of the chords that the scales imply. All of the tricky practice exercises. It was never overbearing, but I hadn’t played an instrument since the fourth grade, so I needed to catch up on the basics. This, however, was familiar to me. Learning to program is little more than running scales on a new instrument. If you’ve never done it before, you need to put extra work into it.
Once I could talk the language of the musician, the lessons changed drastically. The lesson that we always came back to was chord progressions (or changes.) First, I learned the standard 12-bar blues. Then I learned about standard variations on the 12-Bar riff. Then I learned about tons of chord substitutions and how it changed the mood of the 12-bar. Then I learned about the “modern” way to play a 12-bar blues. That, combined with a good amount of theory, allowed me to catch up on 90 years of blues music in a matter of months. I was never great, but I sure understood the hell out of it, and I practiced enough that I could fake it.
Why were 12-bar blues changes the focus of my early lessons? If I had the fortitude, I could walk into a blues club and jam with people that I had never met. Someone could call out “12 in Bb with 2-5-1 turnaround” and we would all automatically be on the same page. The beauty is that none of us would play it the same way; some guitarists are reserved, and other guitarists need to be unplugged in order to be quiet.
Any newbie who learns the 12-bar blues has reached a basic competence in blues: they can recognize when other guitarists do it, they can recognize variations on it, and they can make their own. Because it is such a simple and popular structure, they will wow their non-artistic friends with little effort, because they are using the 12-bar pattern. Not only that, but musicians develop their own ideas on how to approach the 12-bar. Everyone recognizes it, and everyone can borrow from the toolkits of others.
My lessons didn’t stop with blues, though. We went over punk riffs, and where they reappear in rock. In Jazz, I memorized “Rhythm Changes” and “Giant Steps”-style changes. I learned the chords of “Pachelbel’s Canon in D”, as they appear in almost every song. I learned a lot of modern approaches that have long since been replaced in my brain by episodes of Arrested Development.
I don’t want to put words in his mouth, but it seemed to me that one of Steve’s core beliefs was that competent musicians know chord changes so well that the changes wrap around their soul. Guitarists are much better off when they can feel where the song was going to go next, even if you haven’t read it on the sheet music yet. It comes out in your playing, and you have better conversations with the other musicians. Each has their own personalized implementation for the same idea.
What Could This Possibly Have to Do With Programming?
Chord progressions are design patterns. They give a common framework musicians can use to communicate. However, the implementation is left to the musician. You can play classically or bluesy. You can shred the progression. You can take the most “outside” ideas of modern atonal theory and apply them to the song. There are elegant implementations, there are common implementations, there are “outside” implementations, and there are bad implementations.
Chord changes aren’t represented in the core notation/language of the music, but you can use musical notation to spell out changes. You can also use shorthand languages to design the music. The sentence “12-bar in Bb, 2-5-1 turnaround, on my lead” gives away none of the implementation details (voicings/melodies, etc.,) yet the song is written in a breath.
Design patterns act the exact same way for programmers. They are, at heart, a common framework by which programmers can discuss a design. They can spend less time focusing on minutiae and more time discussing design and code.
Even if you are using Python or Perl and you don’t have to explicitly define an Iterator to loop through arbitrary collections, you could easily point to a “for x in y” statement and say “iterate through y” to describe part of an algorithm. You will be correct, and a coder from any paradigm won’t have to give it two thoughts.
Design patterns always exist, but are sometimes invisible.
Here’s Where I Drive Home The Point
Programming and music are both very personal arts. People from both professions use limited languages to describe any thinkable idea, and one “task” can be done any number of ways. Combine this with the imperfection of humans and it’s clear that we have trouble on our hands.
There are infinite ways of making mistakes, and the ingenuity and productivity of humans ensures that we’ll always be increasing our error count.
If you haven’t been to a high school battle of the bands, I recommend you go to one. It’s bad. There are good acts, but they are drastically outnumbered by walls of awful. Some of the awful acts are completely unbearable. They solo out of tune. They play out of time. Worst of all, they’re guaranteed to play for 30 minutes. It’s pain.
However, every once in a while, something magical happens. You find an awful band that somehow still sounds good. The guitarist is still transitioning rough, the drummer still isn’t keeping everything together, but if another band was playing their music, you’d like it. That’s because one of their members is a “songwriter” (stole chords from Nirvana, moved them to another key, and put a different melody over it.) They took a good chord progression and put a good riff on it. You’ll see this most often in punk-rock or pop-punk bands. You hate the band, but you can’t help but admit they came across a catchy riff.
The band sounds good because they are using a design pattern, something that is already correct. Not only do these frequency combinations sound good to the human ear, but we’ve been listening to them for years. They are a “correct solution” to the song problem. They have different implementations.
There are also anti-patterns: common elements of songs that don’t sound good. For example, the big rock ending sounds stupid when it doesn’t begin or end the set. That doesn’t stop bands from doing them. It’s easy to see why, though: when you’re actually writing a song, it’s tempting. You’ve already come up with a neat counterpoint intro, a verse, a chorus, a bridge, beat your singer until he came up with lyrics, harmonized, and now you have to end the song, too???
The big rock ending is easy, and it’s a well-known solution, but you’re better off taking a pizza break and coming up with a snappy ending. You can always turn a snappy ending into a big rock ending, but you can’t do the reverse. That’s just what happens with some anti-patterns: it’s a solution that’s easy, practical, and wrong.
Another anti-pattern is the overuse of common design patterns. For example, the song “Blue Eyes” by The Cary Brothers uses the same 3 damn chords for the entire song. The entire song. I just can’t listen to it. Not only that, but there are other bands that base their entire careers on the “3-chord wonder” (G, C, D or I, IV, V.) This is abusive, but they can get away with it because they are technically proficient in other areas. This doesn’t mean that that particular chord pattern is bad, it just means that it is abused.
Musical education plays a huge part of this. It’s no mistake that talented bands that focus on chord progressions tend to do extremely well for years. There’s nothing special about Green Day, but they use musical design patterns cleanly, and they continue to receive critical acclaim album after album. Their education has helped them reach success. Most bands that don’t get it never reach that stage, and those that do frequently find themselves with only one success.
That’s where the education on design patterns comes into play. Design patterns are correct solutions to problems. This can never be said enough. If people didn’t have the knowledge of design abstractions, they would create their own, or fly blind. They would also defend their design decisions to the death, as they’re never wrong, naturally. The only possible outcome of this is the end of all that we know and love.
We need to find good implementations of design patterns, and we need to popularize them to the point where newbies look to use them. In the future, when they are designing the next silver bullet programming language, they will know where to pull their awesome solutions from. For example, the following in Python:
for i in some_list: # do_something
This is a beautiful implementation of the iterator pattern. It’s very clean and elegant, and saying it aloud sounds like a mathematical formulation (something to which I am partial.) This is not the only elegant implementation: functional languages also have some good implementations. For example, folds.
You can consider this another game of Perl golf, but with a better outcome: we can design better languages, and in the meantime, people write better code. As a bonus to Lisp users, people may be convinced to switch to languages that do their most common design patterns better.
It is clear to me that we need to teach the newbies to write better songs, and the best way to do this is to make a big deal about the best implementations. It seems like every single programmer in the world is learning about design patterns through one way or another. We need to get them to see different ways of doing the implementations: formally, informally, and invisibly. Peter Norvig started in the right direction by providing Lisp’s transparencies to some common design patterns. However, he didn’t finish the task. He didn’t get all of the patterns, and there is more than one way to skin a cat.
Popularity: 47% [?]
Comments
2 Responses to “Music and Design Patterns”
Leave a Reply

With regard to newbies:
The problem with “inferior” languages and design patterns is that they are being thought as The One True Way in [university] courses. Such as the singleton pattern. Use that, and never ever use a global variable, becuase those are evil. (Paraphrasing the GO/TAGBODY, err- GOTO)
Rather, I’d like to see the *reasons* for making certain choices properly explained, such that students understand when a global variable can be used, and when it cannot. You might need a bit of theory, but as a programmer, that shouldn’t be a problem. Sure, much of your average programmer’s consists of gluing libraries together, but hey, if they were better written, she wouldn’t have to do so much work!
As someone who’s been a musician longer than he’s been programming, this actually helps me understand the purpose of design patterns better - thanks!