Search This Blog

Showing posts with label Analogies. Show all posts
Showing posts with label Analogies. Show all posts

How to Determine if Something is Good

I recently came across an old article entitled How Art Can Be Good by Paul Graham that I had tagged as something of interest, and I decided to read through it again. In it he argues that art can be good in an objective sense, and that good art is not simply a matter of good taste. I found this article fascinating because while I agreed with his premise that art can be objectively judged, I disagreed with most of Graham's arguments. With most of his articles, he exhibits clear, sound reasoning, and I learn a great deal from his writing. This article is peculiar in that the reasoning seemed much weaker and more vague, but it still made me think deeply about what makes a thing good so I want to explore that idea more carefully.

Keep in mind that Graham's article was written in December of 2006. He may no longer hold the same beliefs that he did when he wrote this article, and I'm not trying to tear down his ideas about good art or attack him in any way. I respect him both as a writer and as a thought leader in the tech startup community. I'm merely attempting to analyze the reasoning in the article and describe my own thoughts on the subject.

Being able to determine if something is good has much practical value, especially if you're the one creating the thing that you hope is good. When creating a work of art, or any other product for that matter, you want to have a keen sense of what makes it good because the better a product is, the more value it will have for more people. I'm going to widen the net well beyond art at this point because the qualities that make art good can apply to almost anything, so we'll be comparing art to music, movies, video games, literature, food, consumer products, Mathematics, and, of course, software.

You Keep Using That Word…


Right from the outset, Graham entangles the idea of good art with good taste in order to disprove that they are equivalent:
One problem with saying there's no such thing as good taste is that it also means there's no such thing as good art. If there were good art, then people who liked it would have better taste than people who didn't. So if you discard taste, you also have to discard the idea of art being good, and artists being good at making it.
He later concludes this argument by saying that if there is no way to make art better, then the Sistine Chapel is as good as a blank canvas, and since that's absurd, we have a contradiction. Therefore good art exists. I agree with the conclusion, but the argument is either circular, a straw man, or a slippery slope. I can't decide which one it is.

First, taste is a characteristic of the person who is judging the art, not a characteristic of the art itself, so they are already two different things. It's easy to think of something that I consider to be good, but I personally don't like it. Take music for example. There is plenty of music, whole genres in fact, that I don't like to listen to, but I can still appreciate that songs from those genres take great skill to perform and that plenty of other people like those songs. I also have guilty pleasures that I know aren't that good in a musicality sense, but I enjoy them all the same. Does that mean I have good taste for some music but not other music? No, it means I have varied tastes in music, and my tastes are different than other people's.

Second, good and better are also different things, yet he uses them as if the person with better taste automatically determines what is good taste. The world is not so narrow and simple. Faulkner and Hemingway are both considered good writers (an understatement, I know), but if one person liked both of their works and another person only liked Faulkner, would the person who liked them both have better taste? There are literary experts that like Faulkner's stream of consciousness style and hate Hemingway's terse, matter-of-fact style and plenty of other experts that love Hemingway's writing and hate Faulkner's. They can still agree that both are great authors and are important to read. Neither literary expert is better than the other because of which author they prefer, and the authors are difficult to rank because they are so different from each other.

Finally, each step of this argument doesn't immediately follow the previous step, and I think it is because the definition of good is vague and indeterminable. In the context of art, the word good can have at least two distinct meanings that I've only alluded to so far. Art can be good in the sense that it takes great skill to create, and it can be good in the sense that it evokes strong emotions in the viewers. Art created with great skill can include new techniques that have never been used before. There are numerous examples of famous paintings that were some of the first to use perspective effectively. At the time the technique was discovered, perspective was a difficult skill to master, and the paintings that showed good use of perspective were ground-breaking. Today a painting can't be considered good purely on its use of perspective.

We can see the distinction between these two concepts of good in different kinds of movies. Certain movies break ground with special effects. The Matrix is a great movie partly because so many incredible special effects were invented for it, and they were put to good use telling the story of the movie. On the other hand, I think Mr. Magorium's Wonder Emporium is a great movie partly because of the strong reactions of joy and sadness I get while watching it. I can jump into that movie at any time during the last third of it, and I'll be choked up within minutes.

Good has multiple distinct meanings, and throughout Graham's article the word seems to shift between these two meanings of requiring great skill and evoking strong emotions. It is generally easier to objectively analyze whether or not something requires great skill than it is to analyze that it evokes strong emotions, but they both play a part in making something good. Good can have other meanings as well, in the sense of morality for example, but Graham didn't get into those and I won't, either.


Know Your Audience


After the introduction, Graham goes on an extended discussion of what type of audience we're talking about when someone says that a piece of art is good. Who is the art good for? Who would appreciate the work of art? After touching on a number of characteristics that would appeal to people generally, noting that art can appeal to different groups of people in different ways, and even bringing aliens into the discussion, he settles on all human beings as the intended audience when art is described as good.

I generally agree with his reasoning here, although it is a bit drawn out and the bit about aliens seemed unnecessary. He did overlook an important group of people, though—experts in the field. He was arguably talking about how to judge whether a work of art is good for a general audience, but expert opinion is still important because experts in a field will have a much different perspective on something in their field than the general populace would. Once you have a certain level of knowledge about a given subject, your ideas about what is important, what is difficult, and what is elegant will change dramatically.

In mathematics, proofs that are particularly elegant can be considered beautiful. This is something that the average person will likely not appreciate, but an expert mathematician will see beauty where anyone else would see incomprehensible jargon. Sometimes the beauty comes from structuring a proof in a way that neatly solves the theorem in a more concise way than was thought possible. Other times the beauty comes from building up intricate mathematical machinery, and just when you think things are going to get even more complex, everything falls into place and the solution practically drops out of the proof's structure quite unexpectedly. These are forms of beauty that take intense study and specific knowledge to appreciate.

Experts will also see depth in something that the average person will fail to notice. A good example of this phenomenon happens in video games. Some games have layers of depth in game play that is not at all obvious on a single play-through. Devil May Cry is an old action game from 2001 where you are a half-demon named Dante who fights demons with a sword and guns. At first glance it's a run-of-the-mill action game, but if you spend enough time with it, you'll discover all kinds of expert-level secrets in the game. The enemies and levels are designed so that it's possible to complete every level without ever taking a hit, and the game keeps track of that, giving you bonuses and special rankings for good performance. The holy grail is a perfect SS game where you never take a hit for the entire game and complete each level within its time limit. To achieve this feat, you need to learn special tricks for using your weapons and defeating enemies. The game has a ton of depth that only experts will see and appreciate. Most of the games that are considered the best by expert gamers are like this, and the opinions of the expert audience are important when determining whether a game is good or not.

Comparing Apples and Oranges


Graham moves on to a discussion of how the general public leans in its preferences for art, and how those preferences stem from errors of personal bias and artist's tricks. He claims that good art can't be determined by a vote the way a good apple or a good beach could because the public is easily swayed by branding and advertising. I disagree both with the claim that voting is ineffective in determining if something is good and that apples and beaches are all that different than art.

Regarding voting, it's true that you may not think something is good while the majority of people think it is good, but it's likely that the set of things that come to the top in a vote includes some pretty good stuff. (Let's ignore politicians here because no one's going to agree that that statement holds for them.) Take smart phones as an easy example. People vote for smart phones with their wallet, and the top 10 list of best selling smart phones is dominated by Apple, Samsung and Xiaomi. You may not like iPhones. You may not like Galaxy phones. But it's pretty likely that you'll find a good phone on that list. They all have good performance, good build quality, and good design.

I find voting to be a pretty good guide for finding all kinds of good stuff. It's how I choose books to read on Amazon. I will nearly always pass on a book that gets less than a four-star rating because in my experience, they've been almost universally bad. I have a much better chance getting a good book with a four- or five-star rating, even though the occasional stinker still makes it through. It takes a strong recommendation from someone I trust to convince me to read a three-star rated book, and a rating less than that is out of the question. Life's too short, ya know?

Regarding apples, it seems entirely possible that I would not like an apple that the majority of people vote as being exceptionally good. What if I like sour apples and most people like sweet apples? What if I like my apples tart, covered in cinnamon, and baked in a pie? What if I hate apples? The point is that there are enough kinds of apples in the world that deciding which ones are good isn't all that different than deciding which works of art are good. Reasonable people are going to disagree on what is good art and what is a good apple. It kind of comes down to what tastes good to you, and now we've come full circle.

I Said I'd Talk About Software


All of these ideas about what makes good art or movies or smart phones also applies to software. The definition of good changes slightly because the user of a piece of software likely doesn't care if it took a lot of skill to make nor will it evoke strong emotions of joy or sadness. Maybe it will cause intense frustration, but that shouldn't be a goal. What good software does do is make the user feel highly skilled. It gives the user a great sense of accomplishment because she can do things easily that were difficult or impossible before. It should also be enjoyable to use and help the user feel productive. These things will make the user happy.

Expert users will find elegance and depth in good software. I am continually impressed by the cleanness of features in Firefox and the limitless capabilities of Vim, although I wouldn't say I'm an expert in either, yet. The point is that good software has layers of depth that keep enticing advanced users to explore further and discover new powers to make themselves more awesome. In the end good software, like good art, is still a matter of taste. Some people will like Chrome instead of Firefox. Some people will like Emacs or Sublime instead of Vim. For something to be good, it has to meet the requirements of being high quality and being appealing to an audience, and beyond that people's preferences are going to come down to taste.

So coming back to Graham's article, I think there are ways to determine objectively if art is good, but once those objective criteria are met, we are still left with a wide variety of art. Then it comes down to personal preferences, and different people are going to like different things. Ideally, good art is determined by both objective criteria and taste, and on that we seem to agree.

Momentum

"An object at rest tends to stay at rest, and an object in motion tends to stay in motion." Isaac Newton's First Law of Motion seems to apply as well to projects as it does to physical objects. In my experience it is much easier to continue working on a project and keep it moving if it already has decent momentum. It is much harder to make any progress on a project that is languishing from lack of attention, or has hit a barrier that has stopped it completely. To keep a project that you care about moving, you need to at least maintain momentum, and preferably build it up.

In classical mechanics, the measurement of momentum of an object is a simple calculation consisting of the mass of said object multiplied by its velocity:

p=mv

The equation couldn't be simpler, but it has powerful implications in physics. Those implications can also apply to projects.

Specifically, a project has properties that could be considered its mass and velocity. The mass of a software project could be the amount of code, design assets, and documentation that have been created for it. If the project has been released and is out in front of real users, the mass could also be the number of people using it. If the users are actually customers paying for the software, the mass could be the amount of revenue the software is bringing in. In any case, the mass of a project is most likely growing over time. Since the mass is increasing, according to the equation, momentum should also be increasing, but there is that other term to consider.

The velocity term is a vector that has a direction and a magnitude. The magnitude of the velocity (a.k.a. the speed) of a project is simply how fast it is moving over time. How quickly are features being added, bugs getting fixed, or interfaces getting polished? How fast are infrastructure and various support mechanisms being added to the project so that it can survive in the wild? Those are some of the things that determine the speed of a project.

As for the direction, that is determined by how the project is progressing towards the goals set out for it. Two things need to be considered here. The project could either be headed in the direction of the project goals or not, and the project goals could either be in the right place or not. Ideally we want the project goals to be in the right place and the project heading towards them, but that's not always reality.

We've now come to the first insight we can gain from this mental model. (It's obvious, but that's the way insights are sometimes.) If you realize a project is heading in the wrong direction or the goals are way off-base, then how easily the project can be course-corrected will depend on its mass and its velocity. The larger a project is or the faster it's moving, the more energy it will take to change its course because it has more momentum. Likewise, the larger the course correction needs to be, the more energy it will take to get it back on track. Small adjustments can be made even to large or fast-moving projects relatively easily, but if you have to turn a large project completely around, it is going to take a lot of effort.

Something else that happens to projects over time, other than needing course corrections, is that they grow. Much of the energy that a team puts into a project gets converted to mass in the form of the aforementioned materials, customers, and revenue. All of this accumulated mass makes projects more sluggish as they grow. It takes more and more energy to keep a growing project moving fast, which is why it seems physically impossible to make progress on huge, crusty projects with any kind of speed. In contrast, a greenfield project has almost zero mass, so it feels like making lightning fast progress takes no effort at all.

Those greenfield projects don't stay small for long, though. A new project that's making good progress will quickly increase in mass. As it grows, another force will come into play that is alluded to in Newton's First Law of Motion—friction. Since a project is never built in a vacuum, it will have to overcome all kinds of friction to stay in motion. As a project grows, its surface area will also grow, increasing the frictional forces on it.

Even projects that you wouldn't think would encounter more friction as they grow will, in fact, do so. For example, this blog seems to be adding friction as I write more and more posts. I didn't anticipate that. As I've learned things about writing and added new features to my later posts, I am acutely aware of the benefits of revisiting some of my older posts and updating them. I should also refresh my memory of things that I've already written. Both of these frictions continue to grow as I write more, and I'm sure other frictions will arise as I keep going. I also continue to deal with the multitude of distractions from everyday life that are pulling me in directions other than writing.

One way that I've found to keep the momentum up with writing—something I committed to from the start—is to write every single week, no excuses. I normally do even better than that by doing something blog related every single day. It's not always writing; I do that two to four nights a week. The rest of the days I'll make notes in Trello when an idea strikes me or I'm reading something and come across a good example for a future post. I also take time to think about my writing. It may not all seem like momentum, but it all adds up to a blog that keeps moving. It has worked pretty well for me.

I've found that that mentality works well for any kind of project, personal or work-related. Personal projects have all kinds of frictions, not the least of which is probably work and the energy drain that comes with it. It's so much easier to come home and veg out in front of the TV or drift on the internet than sit down and work on a project, but none of that will keep the momentum going, even if you care deeply about the project. The same is true for work projects. Frictions abound with meetings, email, and other (sometimes necessary) distractions.

The best way to overcome these frictions, whether for work or personal projects, is to do something for the project every day. It doesn't have to be a big thing every day. Some days are so packed with meetings or you're so exhausted when you get home that the best you can do is fix one simple little bug or think about the next feature for ten minutes, fifteen minutes tops. Do that. Even a small bit of progress will keep the momentum up on a project so that it's still moving when you have the time and energy to do something big for it.

The last thing you want is for the project to stop completely. Then you have to overcome the most devastating of all forces—static friction. Keeping momentum going is so much easier than starting up a project from a dead stop, especially as the project gets bigger (remember the project's mass). If you want a project to keep going, do at least one thing for it every day because the momentum will help carry your project along. Momentum is a powerful thing.

Skiing Can Teach Us A Few Things About Programming

Alpine skier

A couple weeks ago, I described a skiing exercise as an example of how, in many sports, practice is intentionally made harder to make playing the real sport easier, and that the same principle can be applied when practicing programming. It turns out there are a few more things programmers can learn from the thrilling sport of alpine skiing.

Plan, Then Execute


When you're out skiing, there's a lot of planning that happens before and during each run. It all starts with deciding how you'll get up the mountain when you're down at the bottom, snapping into your bindings. Whether you're with a group or on your own, you'll need to decide which run you want to try out, and which lift will get you to the desired run with the least amount of skating across flat open snow. Depending on how far away it is, the best way may actually involve going down one or more different runs to get to the one you really want to do. And if you are with a group, you'll have to take everyone's wishes and abilities into consideration and make compromises as well.

Once you're on the lift, you may pull out the resort map again and try to figure out how you want to attack the run, or if you've been down it a few times already, you may be thinking about how you want to do things differently this time. The same run can feel entirely different each time you go down, depending on the path you take.

When you arrive at the top, narrowly avoid those people that congregate near the lift exit, and take a moment's pause on the crest of the run, you'll want to take a survey of the slope below. You'll be deciding on your initial path, looking for obstacles you want to avoid (or pursue if you want to challenge yourself), and waiting for any other skiers to go far enough down the run so that no one gets clobbered.

Once everything's clear, you can push off and carve your way down the mountain. However, the planning doesn't stop here. You need to be constantly looking out for new obstacles and making minor course corrections all the way down the run. You may stop and reassess your path at times if there's a blind spot created by a large ridge or if something entirely unexpected happens, like someone being loaded on a stretcher by the ski patrol up ahead.

Your path down a ski run is the combination of a general plan of attack and a series of dynamic decisions that take the current conditions into account. You may reach your destination by an indirect route, but being flexible is crucial to having a safe and enjoyable trip. This method of planning and execution applies equally well to programming, both at the project level where it should sound quite similar to agile methodologies, and at the coding level where you have to understand the code you're changing and adapt to new information as you're making changes.

Pick The Right Skis


There are all kinds of different skis out there, and they all have different strengths and weaknesses. Powder skis are much wider than other skis so that they will float on top of deep, fluffy snow instead of diving into it and burying you. Trick skis are much shorter and may have tips that curve up on both ends so you can go backwards as easily as forwards. As the name implies, these skis are built for playing in half pipes and terrain parks, and it's much easier to pull of flips, spins, and grinds with them.

Hyperbolic skis are made to carve turns easily in a wide range of conditions and are highly recommended for beginners for their easy learning curve, yet they're still fun for advanced skiers. The classic all-mountain ski is still the best choice for moguls because they are narrower than hyperbolics, making it easier to switch edges quickly and make incredibly fast turns, a requirement for attacking the bumps. Finally, super side-cut skis are a hybrid between hyperbolics and all-mountain skis. They make some compromises in either direction so they tend to be good in more situations, but not the best in any one situation.

Given that there are so many types of skis, you will want to pick the best one for the type of skiing you want to do. For example, if you want to try out the bumps and all you have is a pair of powder skis, you're not going to have a good time of it. Of course, these types of decisions come up in programming all the time, and the most obvious analogue for skis would be programing languages. If you pick the right language for the job and you know how to use it well, you're going to have a much easier time than if you only know one language and try to use it for everything. Being well-versed in multiple languages makes you a much more versatile programmer.

Be Aware Of Conditions


When you're out on the mountain cutting up the runs, the last thing you want is to be caught by surprise by unexpected conditions. At best, they could make your day rather uncomfortable. If you're more unlucky, poorly handled surprises could land you in the hospital, or worse. Conditions include the weather expected for the day, the type of snow on the slopes, and the actual obstacles and people around you while you're going down a run.

You should be aware of all of these conditions because they're important for your safety and comfort. Skiing in sunshine is much different than skiing in a (light) snowstorm, and skiing in a blizzard is ill-advised. Temperatures and wind speed will drastically change what you'll want to wear, and dressing in layers is always recommended because you'll be warmer or colder at various points of the day, depending on the immediate weather and your activity level. If you're wearing lots of layers, you can adjust so that you're not sweating or freezing.

The properties of the snow can vary tremendously as well. Fresh powder is great, but if it's deep enough, you'll need those powder skis to enjoy it at all. Wisconsin hard-pack is a combination of man-made snow and excessive grooming, and hyperbolic skis tend to work well in it. You should take extra care when skiing in soft, wet snow because you can hit patches of slush that will grab your skis and send you tumbling down the run. And then there's ice. Make sure your edges are sharp, and good luck!

Most of the time skiing is really not as hazardous as I'm making it out to be here, but it's still important to stay aware of what's happening because accidents happen when you least expect it. The same holds true in programming, with the conditions being anything from the OS environment to the current program state, and accidents taking the form of bugs. The more aware you are of all of the conditions in play for the code changes you're making, the more likely you'll be able to recognize, avoid, and fix bugs in your code. Over time, experience will teach you what conditions matter in any given situation, and you'll be better able to handle all of those nasty coding surprises.

Find The Zone


After all of the planning and adjusting for conditions becomes second nature and you really get comfortable with your skis, you'll find that your enjoyment of the sport reaches to new heights. Your skis become an extension of yourself, and you can anticipate your next turns with complete fluidity and purpose. Being in the zone can be both a serene and thrilling experience. The feeling that comes from conquering the mountain with grace and control is exhilarating. To me, that is what skiing, and programming, is all about - mastering the tools and yourself to surpass your limits and accomplish feats you never thought possible.

What Can Chess Teach Us About Programming?

Chess board


Similar to how it seems that many programmers play a musical instrument, particularly the guitar, it seems that many programmers love to play chess. Now that may be the case only because people in general like to play the guitar and play chess. But I think programmers especially like playing the guitar because it allows them to express their creativity, and they like playing chess because of their proclivity toward analytical problem solving.

There aren't many problems out there that are more complex and difficult than a game of chess (with Go possibly being one of them). Yet, programming is full of mind-bending problems that we have to overcome everyday, and so there are many parallels between chess and programming. We could certainly learn some things about programming from the strategies involved in playing and getting better at chess.

Phases


For starters, chess has three phases of the game: the opening, the middle game, and the ending. In the opening, both players follow a series of moves that have been played time and time again in thousands of previous games throughout history. Most of the advantages or disadvantages of each move have been studied extensively, and there are accepted lines of play for each side that will lead to slight advantages to one player or the other. If the players have studied openings extensively, the opening may last for twenty moves or more. Similarly in programming, when you start a new project, you will go through a known set of steps to setup the environment and lay the foundation for the rest of the project. Much of the initial setup will build a skeleton for the rest of the code to hang from. It gives the project structure, much like the opening moves in chess will build up a pawn structure to use as the pieces are developed and put into motion.

At some point one of the players will introduce a novelty - a move that takes the game out of established opening play - so that the players now have to rely on their own chess playing skills. This phase is the middle game, where strategy and tactics take over as each player grapples for advantages and attempts to maintain them through the rest of the game for a win. The middle game can be fraught with uncertainty, with countless options available on each move and few certain paths to victory. Tactical strikes can change the balance of the game quickly. The advantage can quickly change hands as attacks succeed or fail and pieces are exchanged.

The long middle game of a software project can have its fair share of uncertainty as well. Every design decision entails tradeoffs and compromises, and the final success of the project is largely unknown, much less what it will actually look like once all is said and done. There will be days where everything seems to be going great, other days where nothing seems to work at all, and that momentum can change in an instant. This is the time to celebrate small victories, attempt to keep morale up, and strive to maintain momentum and positive progress.

Back in the chess game: at some point enough pieces will have been removed from the board, and the position becomes more clear. The transition from the middle game to the ending is not as well defined as from the opening to the middle game, but at some point it becomes obvious that the end of the game is imminent. In this phase every move becomes critical, and the game can be won or lost because of a single pawn move at the wrong time or the precise path that the king takes across the board. Precision of execution is paramount. The same goes for software projects. At some point most of the planned features will have been added, and the bugs are getting progressively cleaned out of the system. It becomes clear that this software will actually ship, but the execution from here on out is critical. Everything has to line up precisely for the best possible outcome on release day, and the slightest mistake could make a huge difference in the success of the product.

Pattern Matching


Okay, the phases of the game showed some similarities to software projects in broad strokes, but there are a number of other more specific things that we can learn from the game of chess. At its heart, chess is a game of pattern matching, and that is how the masters are so good at playing. When they look at a chess board, they don't see two sets of sixteen separate pieces on individual black and white squares. They see combinations of interacting pieces controlling space on the board. They see a pawn structure that defines the game and shows which strategies will be appropriate to pursue. They can instantly memorize any given position and assess the strengths and weaknesses by recognizing common configurations of pieces so that they can spend their mental energy analyzing the best course of action.

If you've ever watched an expert programmer at work, you may be amazed at how quickly he (or she) can determine how a piece of code works and make necessary changes. This ability comes from the same pattern matching skills as the chess master, but the patterns are in the code. I'm not talking only about design patterns here. An expert programmer stops seeing individual keywords, variables, and operators, and instead he sees the structure of the code itself. He can recognize similar blocks of code that he's seen in the past and work with it at a higher level than just reading and manipulating individual symbols.

For the chess master, this pattern matching ability is useful beyond merely assessing a position. Being able to recognize more chess patterns will give you a better ability to calculate the best lines of play, and it will improve your horizon - how many moves ahead you can see. Strengthening this ability to concentrate on the position and calculate deeply in spite of what pressures the player is under is known in chess as developing mental toughness. That concept is perfectly appropriate to programming. As you gain more experience and expand your ability to see software patterns, you will be able to see larger and more complex transformations of code with less mental effort. You will be able to anticipate more potential problems and envision more promising solutions when writing code, all by improving your mental toughness.

To develop this skill in chess, you should do lots and lots of practice drills. There are entire books filled with positions where one player has an immediate tactical advantage over the other, and you are supposed to see the correct lines of play that capitalize on that advantage. You can also do all kinds of different drills with a few pieces to practice essential tactics like pinning, forking, skewering, and discovered attacks. Seeing these tactics will become more automatic as your pattern matching skills improve. There are also all kinds of ways to improve your pattern matching skills in programming. In particular, studying algorithms and data structures, and practicing on programming puzzle websites like Project Euler or Programming Praxis will greatly improve these skills.

Strategy And Tactics


Much of master level chess revolves around the tension between strategy and tactics. Strategy involves the long term advantage you can leverage from things like the pawn structure and the control of space and critical squares on the board. Tactics instead consist of the short term execution of maneuvers that result in a decisive material advantage. Skewering your opponent's king to trade a rook for a queen or forking the king and bishop with your knight could lead to an overwhelming advantage of force, if you can hold on to it.

The opening is where strategies are first put into place, and most of the opening theory is based on gaining a strategic advantage, assuming the opening lines are played correctly by both players. The middle game is the land of tactics, and this is partly why the balance of the game can change so quickly during this phase. Most novice players make the mistake of focusing too heavily on memorizing different openings, when they should really be studying tactics. Even though strategy depends on deep chess knowledge, most games at the amateur and even the master level are primarily determined by tactics.

When amateurs look at grandmaster games, they will read an awful lot of discussion about subtle positional advantages and strategic play. What amateurs seem to forget is that to reach that level of play, grandmasters had to be absolutely excellent at tactics. They have gotten so good at tactics that for the most part, they have taken tactics out of the game. At least, that's what it looks like on the surface. If you look at the alternate lines of play in a grandmaster game, they are littered with devastating tactics narrowly avoided on both sides. The point is that grandmasters are exceptionally skilled in both strategy and tactics, no matter whether they are described as positional players or tacticians.

In programming creating new code can be thought of as strategic play and working with legacy code can be equated with tactical play. When writing new code, you must think longer term about all of the implications of the design you implement. How you structure the code could have an impact on the project for years down the road because it establishes a way of doing something that can become hard to change as more code is added to the original architecture. On the other hand, working with legacy code entails making surgical changes to existing code, and small changes can be decisive in fixing broken code or adding new features. Refactoring in particular can be thought of as a known set of tactics that can improve legacy code with small, well-defined code changes.

As with strategic or tactical grandmasters, expert programmers may have a preference of creating new code or working with legacy code, but they are excellent at both tasks. The defining characteristic of experts is not whether they are better at building something new or fixing something old, but that they have exceedingly good judgement about programming in general. Just as a grandmaster will have a better idea of when to develop her position and when to go on the attack, an expert programmer will know when it is better to write their own code or use a library and what the best way to debug a particular piece of code would be. Experts have a general sense of good judgement that comes from years of practice, experience, and hard work developing all of their skills. Their preferences for one particular way of doing things tend to show only when the trade-offs of choosing one way or the other are insignificant.

Beauty


It only takes a short time learning chess before you begin to realize that the game is filled with beauty. You can hardly find any book on chess that doesn't mention it in one way or another, and commentary on famous chess games is filled with acknowledgements of beautiful positions or exchanges or checkmates. The more you learn about the game, the more you can appreciate the beauty that unfolds from the interaction of the pieces and how they can work together when the game is played well. One of my favorite types of checkmates is the pure mate, where every square around the mated king is either attacked or occupied only once. Being able to achieve something so perfect in the course of a game with nearly endless possibilities certainly elevates the game to a work of art in the hands of the masters.

The best programmers strive for beauty in code as well. For them it is not enough to merely create functional, productive software. They strive to transcend normal, everyday code to create masterpieces that solve complex problems in clear and elegant ways. For them programming is not a job or a hobby, but a labor of love that they pursue with a deep passion. Of all the things chess can teach us about programming, this one becomes the most obvious with time. Bringing order to complexity is a thing of beauty that is deeply satisfying to achieve.

What Can Golf Teach Us About Programming?

Golf ball teed up with driver

Golf is a game of accuracy and patience. You start with a little ball slightly bigger than one and a half inches in diameter, and you have to sink that ball into a hole barely more than two and a half times its size that lies hundreds of yards away using only a set of clubs. The less strokes you can do it in, the better, and once you've done it, you get to do it all over again on the next hole. That sounds like an apt metaphor for software projects if there ever was one.

On a software project, you start out far from your goal, the finished product. You may not be able to see the goal when you start, but there are markers and flags along the way leading you in the right direction. Mistakes can send you off in the rough (or worse), and it takes extra time to get back on the right path. There are also plenty of obstacles, traps, and hazards to deal with. In golf, when you get into trouble, the best thing you can do is get back to the fairway. Taking risky shots from bad positions can make a bad situation much worse, and you may never recover, so get to safety first instead of trying to be a hero.

Another place to keep it calm and not try to be a hero is on the tee. We all love grabbing our big driver and taking a monster swing to crush that ball into oblivion, but we're more likely to put the ball much closer to the hole and on the fairway if we take a nice, smooth, easy swing. Have you ever noticed how professional golfer's swings look so effortless, yet they can hit the ball a country mile while maintaining accuracy? That ability comes from great technique and control, not from brute strength. When you try to kill the ball, you're only succeeding in killing your swing with a loss of control. The ball may very well go far ... into the woods. Save the monster swing for the driving range where you have the ability to experiment and hopefully gain some control over it with practice.

The same can be said for software projects. If you try to hammer out hundreds of lines of code in one shot, you may feel like you're making great progress, but you could end up far off course and no closer to your goal. Take it easy. Code a little, test a little. Talk to your customers frequently. Get some feedback so that you know when you're veering off into the trees and can make corrections early.

While you're making those corrections, you can think about your approach. In golf you start out with long shots that cover plenty of distance to the hole, but as you get closer, you use shorter clubs and the shots get shorter and more accurate. More than half of your shots in a game of golf will be taken on and around the green. That means that 90% of the distance to the hole is covered by half of your strokes, and the last 10% of the distance takes the other half. That characteristic should sound very familiar to software engineers, where projects are estimated to be 90% done when you're only halfway through the schedule. Amazingly, that last 10% takes the other half of the time.

Because of this 90/10 property, you can improve your golf game more dramatically by shaving strokes off of your chipping and putting game than you can by adding 50 yards to your drive. Being 100 yards from the green isn't that much better than being 150 yards from the green, but if you can easily sink 10-foot puts, you're going to have lots more opportunities for a lower score. Could the same be true in software projects? If you improve the testing, bug fixing, and tweaking that goes on before releasing a product, that could have as much if not more of an impact on schedule than improving on the initial prototyping and coding at the beginning of the project. Of course, like teeing off, initial prototyping is the fun part. Who wants to spend all of their time practicing putting, am I right? Well, the golfer that nails more puts generally wins more games.

Another aspect of golf is the wide variety of clubs at your disposal. Every club has a job that it performs best, and sometimes the choice of club can make or break a shot. The driver is made specifically for hitting long shots off of a tee. The woods are good for long shots off of the fairway, but don't work well in the rough. The irons can get the ball up and out of the rough better, but can't hit the ball as far as the woods. Hybrids attempt to combine the best parts of the woods and irons, but they have their own compromises. The wedges work well when you get closer to the green, and they can help get you out of bunkers and tight spots. The putter, of course, is the club of choice on the green.

To master the game, you have to become proficient in all of these clubs and know when to use each one. Likewise in software engineering, you will become a much more productive programmer if you learn more tools and learn them well. Every programming language, library, API, or utility is another club in your bag. Take the time to learn their strengths and weaknesses and in which situations to use them to the best advantage. No tool is perfect for every situation, and using them in the right context will make you much more effective as a programmer.

As you're trying to improve as a programmer, you can keep a golfing practice tip in mind. Consider how much there is to think about when trying to improve your golf swing. There's your posture, your grip, your stance, and your line-up to the target for starters. Then during the swing there's the backswing, the downswing, ball contact, and follow-through. The whole swing involves timing, tempo, and rhythm. And for heaven's sake, make sure you keep your head down and your eye on the ball while you make contact with the club face. There is no way that you can be thinking about all of those things during the two seconds that it takes to swing the club.

So don't. Focus on one thing at a time. During your swing, you should be thinking about only one aspect of your swing. If you try to practice even two things at once, you're going to do both of them badly, and you won't get anything out of your practice. If you stay focused and improve on one thing until it becomes second nature, then you won't have to think about it anymore, and you can move on to something else. The same strategy works well in software engineering. Pick one thing to learn and then learn it. Don't split your time and attention over too many things or you won't make progress on any of them. If you concentrate on one thing at a time, you'll learn it faster and actually make use of it more often because you'll know it better.

Here's one last thing that becomes painfully obvious in golf. No matter how good you are, there will be things about almost every shot that you wish you could have done better. Sure, there will be the occasional shot that feels and looks awesome, but it's those great shots that make you believe that you can do better on all of the others. You are not alone. I've read about professional golfers - golfers that have won Master's Tournaments - that say they think 80% of their shots are crap. They thought they could do better than they did on that many of their shots, and they are the best golfers in the world. I'm sure they practice every day to improve on those shots where they felt they came up short. Remember that - there's always room for improvement.

What Can Artists Teach Us About Programming?

Today I witnessed a remarkable feat. We had a guest speaker by the name of Ben Glenn at my daughter's Sunday School class. He gave an amusingly comedic and somewhat inspirational talk about appreciating and developing your gifts, but that's not what I want to talk about. I want to talk about what he did next. He turned on some music, put on a surgical mask, and began drawing with chalk on a large black sheet clamped to a standing wooden frame. He said the sheet was a plain old bed sheet from Wal-Mart, and it looked like it would fit a queen-sized bed.

As he jumped back and forth, spreading colored chalk over that bed sheet and sending clouds of dust into the air, I was mesmerized. Slowly at first, and then progressively faster, a scene appeared before us of a sunset on a shoreline with an island of mountains off in the distance and a lighthouse and palm trees framing the image in the foreground. Within about 20 minutes he had created a beautiful work of art, and we all got to see it come to life.

I hadn't brought a camera, so I can't show exactly what he drew for us, but it looked something like this print from his web store:

Ben Glenn print Castaway

I think the fact that he can create these images so quickly and in front of a live audience is incredible. I know it's not a unique talent, but it sure does take a major amount of dedication, focus, and practice. I appreciate that. And it was awesome to watch. If you ever have the opportunity to watch a great artist at work, take the time to really see what it takes to create a thing of beauty in real time. As I was watching the scene unfold, I couldn't help but think about how what he was doing with chalk and a canvas mirrors what programmers do with a programming language and a computer. Even though his is a physical medium and ours is a virtual one, how we create our masterpieces has many similarities, and we can learn a lot from watching a great artist in the act of creating.

Let's start at the beginning, with an artist's worst enemy: a blank canvas. Now Ben obviously had a pretty good idea of what he was going to draw. He's done this hundreds of times before, and he's probably not going to draw something completely new for the first time on stage in front of an audience. He has a design of a scene in mind and he knows what he wants the scene to communicate with the audience. Let's assume he's taken care of all of those preconditions of design and requirements and we're looking solely at execution.

That blank canvas can be pretty scary. I know I've faced it plenty of times in the form of a blank file and an insistently blinking cursor. How to begin? Ben didn't hesitate. He grabbed a big stick of yellow chalk and immediately began throwing color up on that canvas in great strokes and swirls. Then he dropped the yellow and picked up some orange and did the same thing. Then he used some blue and some purple and some green, building a foundation for the scene he wanted to create. The blank canvas was the enemy, but he quickly beat it by putting up something real that he could work with and build on.

We can do the same in programming by writing something into that blank file as quickly as possible. Define a class and start filling it in. Don't try to think about every requirement and feature that class has to fulfill from the beginning. Trying to keep all of that in your head can paralyze you. Put up a skeleton first, something you can build on. Test Driven Development can help here because you can define the features and requirements as tests so you won't feel like you're forgetting any of them. The tests become part of the foundation of that class, and they give you something to write that should be easy to start with. Once you've filled in the class enough and all of your unit tests are passing, you know you're done.

Once the foundation was done, Ben started defining what would become the background with some additional detail. Here I started noticing that he used a wide variety of strokes. Some where finer and more precise to add definition to an element while others were coarse and strong to get a lot of chalk on the canvas quickly and rough out a new element. He knew intimately well when to use different techniques, and his movements were always definite and confident. That confidence came from practice, probably thousands of hours of practice. He knew exactly how each stroke would add to the visual appearance of the scene and he could produce each one without thinking because the motions were ingrained in his arms and hands from those hours of practice.

It was also obvious that he knew at a deep level how the different colors, strokes, and elements would interact on the canvas to produce a visually rich and stunning image. That knowledge likely came from intense study in addition to practice. We should strive for the same kind of understanding of our tools, languages, and frameworks, and experiment and practice with them until we can use them with the same elegance and ease.

As the scene developed, he would leave some elements unfinished, go to a different space to create another element, and then return to further define the earlier ones. He would move around the canvas, roughing in the sun, the planets, and the mountains at the same time so that he could use them as markers for each other and the other foreground elements yet to be created. They helped define the space and flow of the scene, but at first it was not clear what any of them were. He didn't need them to be completely refined and perfect right away; he only needed them to be there to add structure to the scene. Once everything was arranged and he went back and added detail, those nondescript elements quickly jumped to life.

The same type of process can be quite helpful in programming. First roughing in different classes and methods so that the whole program can hang together, before going back and filling in the details, is a great way to keep a project moving along without getting bogged down in the details too early.

Another effective technique that he used when adding new elements to the scene was throwing stuff away. He would develop an area of the scene and then later come back and draw something else right over the top of it. If you only look at the final picture, you may not even know that originally, the colors of the sunset covered the entire canvas. The mountains and the lighthouse weren't drawn on empty space; they replaced the sunset behind them. The same is true of the palm tree covering the mountains behind it. He wasn't concerned with preserving every ounce of work that was done on any particular element, even though time was limited. Some of that first chalk that was laid down is never seen in the final picture. It was put on the canvas only to be thrown away, but it still served a purpose. It helped define the background, and since it was drawn in first, it helped make the background that can be seen in the final image look continuous and flow behind the foreground elements.

What should we take away from that technique? For one, our code is not sacred and we shouldn't worry so much if some, or even a lot, has to be thrown out, redone, or replaced. Even if some particular code is pitched, it helped define the program at one point, and hopefully the good effects of that code will endure even after the code itself is removed. Inevitably, some of the original code will remain to the end, just as some of those original chalk strokes are still there in Ben's finished picture.

One last lesson we can take from watching an artist at work is how to stop. Ben knew he had our attention for a limited time, so when he had developed the scene enough and all of the elements looked recognizable and evoked the right mood, he set down his chalk and took his applause. He had created a beautiful, moving image in less time than it takes bake a pizza. I'm sure there are parts of it that he thought he could have done better, or things he wanted to change, but he also could have ruined it with endless tweaking while losing our engagement in the process. Instead, he shipped it to his customers, the audience. We could do worse than learning to do the same.

7 Ways That Programming is Like Weight Lifting


I like to find ways to connect the different things that I enjoy doing in life, even if at first they seem to have nothing to do with each other. Certain good practices can stand out more than others in any activity, and those practices can be applied more generally to other activities. Finding what works well in one activity can be used to achieve new levels of skill in other pursuits. Take some time to appreciate this, and you'll be surprised at how many connections you can make between seemingly independent things. What is really in common between different activities is you, the human being in the middle of it all.

The activity I'll explore today is weight lifting. I don't lift competitively, and my goal is to look fit and toned, not like the Incredible Hulk. I lift weights a couple times a week to stay strong and happy. Yes, happy. If I miss a workout I start to feel grouchy from the loss of physical activity. I sit at a computer all day and am otherwise relatively inactive, so my body and my mind need the physical exertion to keep from getting run down.

I have plenty of time to think during my workouts, and sometimes I ponder becoming a better programmer. As it turns out, a lot of the habits that help you progress in weight lifting can make you a better programmer, too. For instance:

Stick to a Schedule


You need a schedule. There is no getting around this fact in weight lifting. If you don't lift regularly, you're not going to get any stronger. Once you reach your desired level, you can maintain that level on two workouts a week, but until then, you need to be lifting three times per week, minimum. If you stick to  a schedule, you'll be able to make fairly steady progress, especially in the beginning before your muscles build up a tolerance for the workout.

If life interrupts or you succumb to laziness and miss a few workouts, all is not lost. It will take less time to get back to where you were than the time that you missed. As a rule of thumb, it will take one workout per week missed to recover your lost strength and start making progress again. But it's easy to keep skipping more workouts once you've missed a few so I wouldn't start down that road.

A continuous improvement schedule is a good habit to get into for programming as well. It may not be as essential as in weight lifting, but doing programming workouts a couple times a week to maintain your skills - or more often to improve your skills - is a great idea. Take some time to solve small algorithmic problems or write utility programs to keep your problem solving skills fresh and strong. Get a few books and explore whole new areas of programming to really make progress and learn new skills.

A Routine is Good, a Rut is Bad


If your workout routine is working for you and you enjoy it, then keep at it. If you're dreading the boredom of your workouts or feeling like you're stuck in a rut, then it's time to mix things up a bit. After doing the same routine for a couple months, your muscles will get used to it and stop responding to the stress you're putting on them. You need to change what you're doing to shock your muscles out of their comfort zone so they can keep growing. Do different exercises, use free weights instead of machines, do more repetitions with less weight, do less repetitions with more weight, or even change the order of the exercises to make your body work in a way that it's not used to.

Your mind works pretty much the same way. It adapts quickly to a particular task and gets bored easily. Find ways to challenge yourself to keep programming fresh and interesting. Explore new languages, libraries, and frameworks. Write algorithms in different languages and compare their performance and readability. Try writing code that is as understandable as possible without comments. There are all kinds of things you can do to mix it up and get out of a rut. The point is to do something different. You'll see things in a new way, and your programming skills will get stronger because of it.

No Pain, No Gain


There is no escaping it. Weight lifting is hard. When you're pushing yourself, every workout will get your blood pumping and your heart racing and leave you somewhere between tired and exhausted. You shouldn't push to the point of injury or extreme fatigue because then you're doing more harm than good, but a little exhaustion is a good thing. If you're feeling back to normal, or even energized, about an hour after the workout, that's right about where you want to be.

On a longer timescale, getting into shape will take years of work. It's not going to happen overnight, and you'll get as much out of it as the amount of work that you put into it. When you're first starting a workout routine, you're not going to be able to do much, and you're going to be sore for weeks until your muscles adjust. Once your muscles have learned to deal with the exertion, you'll have to keep pushing them to make progress. When you've reached a level of fitness that's satisfying, you'll still have to keep up the workouts to maintain the gains you've achieved.

You should expect no less of programming. It's also hard, it takes a great deal of time and effort to get better, and the amount of mental exertion you'll go through will be exhausting. Like weight lifting, you don't want to overdo it when programming. At some point you'll lose the ability to retain anything else without resting, and you'll make more mistakes than you fix so that you'll actually make negative progress. You need to push to make progress, but it needs to be sustainable. And like weight lifting, programming is going to take years to reach a decent proficiency, and decades of maintenance. If you want to stay at a certain level, you'll need to keep working at programming.

You Can do More With a Spotter


A workout partner is a wonderful thing to have. They are so much more than a pair of helping hands when you can't push out that final rep. A good workout partner will motivate you when you aren't feeling up to a challenging exercise. They will help keep you safe if you bite off more than you can chew. They offer constructive advice when you make mistakes or lose your form. They will keep you honest and hold you to your workout schedule when you want to take the day off. They will bring different ideas to the workouts, encourage you to try new things, and mix things up when they get boring. That pretty much sums up the advantages of pair programming and code reviews, too.

Don't Focus Only on Your Chest



If you only work your chest with bench presses, chest flies, and the like, you're going to plateau in a hurry. Having a strong back helps stabilize your torso so you can lift more weight safely. Strong arms, wrists, and hands do a lot during any upper body exercise, so they shouldn't be ignored, either. A strong core is even more important for stabilizing your body, providing power, and preventing back injury. And finally, don't forget about your legs. Chicken legs look ridiculous on anyone. Don't put a big barrel chest on those stilts. Build a nice strong foundation for your upper body.

The equivalent mistake in programming would be focusing on one specialized corner of the field. Don't do that. Branch out and develop your other programming muscles. If you're an embedded programmer, learn some web programming. If you write desktop applications, learn database design. Work on your core by learning some operating system design, compilers, microprocessor architecture, digital design, discrete math, or graph theory. Don't think of this as a definitive list, just some ideas that you can expand on. Find an area where you're weak and develop it. Learning new programming subjects will make you stronger in the areas you already know and bring you new ideas that were previously inaccessible or unknown.

Don't Forget the Little Muscles


Weight machines are very good at targeting specific muscle groups, but they take all of the variation out of the exercises. If you're not doing any free weight exercises and you don't do exercises that target smaller muscles like your rotator cuffs, wrists, ankles, and hip adductors, the neglect will likely lead to injury eventually. However, if you do develop these muscles, they will help stabilize your joints, making lifting easier and safer.

Most free weight exercises work a much wider range of muscles because your body has to work to control the weight, bringing these smaller muscle groups into play and strengthening them as well. The exercises become a positive feedback loop where the smaller muscles get stronger, which helps you lift more weight, which makes the bigger muscles stronger, which helps you lift more weight, which requires the smaller muscles to get stronger to control the heavier weight. Targeting the smaller muscles with special exercises can also help this process along.

In programming your small muscle groups are what support you in your day-to-day programming: language features, sorting and searching algorithms, string processing, regular expressions, network protocols, IDEs, typing, etc. Don't neglect these things because you think you already know them or it's a waste of time. The stronger you are at them and the more automatic they become, the less mental energy you'll waste on them and the more you'll have available for the really complex programming challenges.

You're Going to Have Good Days and Bad Days


Some days you won't feel like you can lift anything. You feel exhausted before you even begin, and it takes every ounce of will to get through the workout. This is normal. Keep in mind that tomorrow will be better, and do what you can. Other days you'll feel like Superman, and you can add extra weight and reps without breaking a sweat. Take full advantage of your temporary super powers.

Who knows why this happens. Maybe it's something you ate, or how you slept (or didn't), or the weather, or your biological cycle. Whatever it is, you're going to have good days and bad days, whether it's weight lifting or programming. Take the bad days in stride and don't get discouraged. Enjoy the good days when they happen, but don't let them go to your head. And the rest of the time, keep on keepin' on, and you'll keep getting stronger.

6 Ways that Programming is Like Juggling



In my continuing effort to draw connections between programming and every other activity in my life, I thought I would tackle the similarities I see between programming and juggling. I find that juggling is a pretty fun way to kill some time when I don't have the time to do anything more involved. It's relatively easy to find three or more relatively small round objects that I can try to keep in the air.

Since I have a couple of small children, I can generally look down at my feet and find a multitude of toss-able things readily available on my very own floor. Building blocks, plastic eggs, wooden fruit - it's all fair game, and entertaining for the kids as well. I once tried using a couple of medicine balls, but that didn't work out so well. Balls that heavy tend to screw up your tosses, and boy do your arms get tired fast. I suppose they would be good for training to juggle chainsaws, though.

Juggling has some nice advantages beyond wasting time. It improves your hand-eye coordination, reflexes, and spacial awareness. It's a neat party trick, for kids at least, and looks pretty impressive once you get a few tricks beyond the basic three-ball juggle under your belt. Okay, enough about the virtues of juggling. How does it relate at all to programming?

You have to keep multiple balls in the air. And when those balls are in the air, there is a lot going on. Your eyes are spotting which ball to catch next. Your hands are adjusting to where the balls are going to land. You're launching the ball you just caught so that hand is free for the next ball that's already on its way down. Each of your hands and your eyes are acting independently, but they are still connected through the paths of the balls and acting synchronously. At no point can you be aware of everything that's happening at once. Your hands have to know what to do and react without conscious thought.

With programming, you are juggling with your mind instead of your hands, and you have to keep numerous variables, functions, and processes in the air at the same time. The bigger the program, the more that's potentially going on at once. If you had to consciously think about everything, you would have a hard time making progress. You have to depend on your mental reflexes to retrieve the necessary information at the right time for the particular code you're writing. If you have to constantly jump around the code to remember which variables do what and where that other function is called and what were the side effects, you're dropping the balls instead of keeping them all in the air.

Consistency and accuracy are your two best friends. When learning to juggle, one of the first things you have to train yourself to do is throw the balls exactly the same height and distance every time. If you watch a good juggler, the balls or rings or clubs will all travel along exactly the same path as if they are wired together. When they deviate from that path, the juggler is either inserting a quick trick into the juggle, or he is transitioning into a different juggle that will become the new path.

A routine is made up of a series of transitions from one steady state to another with slight deviations thrown in to surprise the audience. The absolute consistency and accuracy of every single throw allows the juggler to think at a higher level about the next part of the act instead of how to throw and catch each ball as it's happening. That ability to step back from the basic mechanics and let the subconscious take over allows a smooth, dynamic performance to happen.

The same principles free a programmer to think at a higher level. If you consistently use the same design patterns and conventions when you're programming, you can do more forward thinking. You can get to this state of mind more easily by adopting standard naming conventions, method and class structures, and coding style. Once you are thinking less about what to name things, what you did name things, and how to structure code, you can relieve your mind to concentrate on achieving your goals. Increasing your accuracy frees up even more time that you were spending correcting compiler errors and simple coding bugs, leaving more time for higher level thinking and design.

Juggling requires efficiency of motion. It's quite tiring at first. It seems like you have to move your arms and hands in a dozen different directions, as if they need to be everywhere at once. After a few minutes all of your muscles get pretty worn out. As you get better, you figure out how to combine separate movements into more fluid motions that conserve energy and use the momentum of the balls to your advantage. As you move your hand to catch a falling ball, you let your wrist relax at just the right moment to load it like a spring and then bring your forearm in slightly and relaunch it to your other hand with a light flick of your wrist. You make less course corrections and all of your movements get smaller and more focused. Eventually you have all of the time in the world to catch the next ball, and you conserve your energy to keep juggling for much longer stretches of time.

In programming, efficiency of motion would apply directly to typing skills. That much is obvious, but let's cast our net a little wider. Efficiency of motion also applies to the entire programming environment. Take the time to learn the shortcuts of the operating system, IDE, and editor you're using. The more efficiently you can move around your programming environment, the faster you'll be able to program, and the more mental energy you'll have to put towards programming better. Whenever you find that you're making a course correction by interrupting your coding flow to accomplish some task, take a little extra time to see if there's another way to do it that will flow more smoothly. Eventually you'll be able to dance around your programming environment much more efficiently, spending less time wrestling with the environment and more time writing great software.

It is hard to learn new tricks. Once you have the basic three-ball juggle down, you'll want to expand your repertoire. Maybe you want to learn to juggle two balls in one hand or sneak a throw behind your back. You'll quickly find that every new trick is practically as hard to get right as the original three-ball juggle. Your hands have no idea what to do, and you have to force them to move where you want them to go because they will no longer do anything right on their own. Suddenly, juggling takes all of your mental focus again. More than in any other activity I can think of, in juggling it is difficult to learn new tricks.

Sticking with the same old tricks is boring, though, so there's quite a bit of motivation to challenge yourself and learn new ones. Learning new programming tricks can also be difficult, but also necessary. If you don't take the time to learn new languages and frameworks, your skills will stagnate and programming could become quite tedious. Overcoming the difficulty of expanding your bag of tricks is well worth it. Don't let the fear of temporary awkwardness stop you. You'll get past the initial pain of learning something new, and you'll be a stronger programmer when you're done.

Juggling has a natural progression. Start out passing one ball back and forth between your hands. Then add a second. Once you're comfortable with that, add the third. Then try juggling two balls in one hand, then two in the other hand, and then try two in each hand at the same time. Once you can juggle four at once, add a fifth. You can also branch out into bounce juggling or juggling clubs or passing with a partner. I'm drastically oversimplifying, of course, but the point is that there is a definite progression to getting better at juggling.

I don't believe that learning to program has a natural progression. For every programmer, there is likely a different path to getting where they are. But there are parts of programming that do have progressions. When you're trying to refactor a section of code, even if it is a great big tear-up and redesign, there is likely a natural progression that will get you from the current code to the desired code through a series of smaller, simpler steps that maintain working code. If you can find that progression, you can make your life much easier because you'll know everything is working at each step of the way instead of doing a major overhaul and finding that nothing works at the end. Take the time to find that natural progression.

Improvements come suddenly and without warning. When I was first learning to juggle three balls, I would keep a running count of how many throws I successfully caught. It was slow going at first, and I felt like I was stuck at six throws for a long time. Then all of a sudden I could do 15 throws, and I was stuck there for days of practicing. Then I jumped to 25 throws without consciously doing anything differently. Once I took the step beyond 25 throws, I could basically juggle three balls as long as I wanted, and I stopped counting and moved on to other tricks. None of these advances were gradual. It was as if the motions had suddenly sunk into my muscle memory, or some subtle change improved my efficiency of motion, and I took a big leap forward in skill.

I noted that when learning the guitar, techniques or pieces of music that were once difficult could become easier without noticing. Juggling isn't like that because the feedback is immediate and obvious. You have an absolute reference to always compare against: are you keeping everything in the air, or not? Programming can have absolute references like that, too. Can you suddenly write 100 lines of code without making any syntax errors? Or maybe you've done a large refactoring without introducing any new bugs. Or you've become so proficient with a new framework that you can keep coding without having to look things up in the documentation. These kinds of improvements will all be immediately noticeable.

Experiencing these leaps in programming skill is quite satisfying. Something clicks, and suddenly you can do things that you previously only admired in more experienced programmers. Keep practicing, work for those improvements, and your efforts will be rewarded.

10 Ways That Programming is Like Playing the Guitar


Connections between seemingly unrelated things make powerful learning devices. Those connections form links between things you are learning and things you already know, helping you to internalize new concepts. They also form stronger interconnections between different things already stored in your memory, and the cross pollination can give you a deeper understanding of both things. I'm always looking for ways to relate what I'm trying to master to what I already know, so when I began learning to play the guitar a couple years ago, I noticed a lot of similarities between it and programming. Here are ten ways that they are related.

You have to practice to get better.


Obviously. No one thinks you can learn the guitar by watching other people play or by listening to great guitar music on your iPod without actually picking up a guitar yourself and playing it. To get good, you have to practice a lot. Your fingers, hands, and arms have a lot to learn for even the simplest songs: fingering chords, picking strings, strumming, and learning basic form. Without practice, you could never learn or get better at playing the guitar.

The same is true of programming, yet most programmers don't practice. College coursework or what you do at your day job probably doesn't count in most cases. That's more equivalent to performing, not practicing. Practice involves dedicating time to learning new aspects of programming or working on those skills that are lagging. You can't do that while you're performing.

You get better faster if you practice consistently.


If you practice the guitar sporadically, only picking it up once a week or less, it is extremely difficult to get any better. You spend your whole practice trying to get back to where you were the last time you played, and you have no time to work on anything new. On the other hand, if you practice 5-7 days a week for an hour or two at a time, you're going to improve rapidly. If you do that practice session at the same time and in the same setting everyday, you'll do even better because your body and mind will trigger on the familiar environment and switch right into practice mode. You can whip through a quick warm-up and get into the meat of your practice without any effort. You know what to do and you don't waste any time getting it done.


You can get the same benefit from consistency with your programming practice. Do it in the same place with the same programming environment and you'll get right into the groove every time. Try practicing everyday at the same time to make it a routine.

You get better faster if you push yourself.


You'll plateau fairly quickly if you learn to play a couple songs and then only practice those songs over and over. It may feel comfortable to be able to play some songs well, but you have to get out of your comfort zone and learn to play new stuff. It's frustrating to practice hard pieces that you haven't memorized yet, or that have complicated passages that tie your fingers in knots. But you won't get better by only practicing what you know. You have to push into uncharted territory to grow.

Practices should consist of about 80% music that you know how to play and 20% music that's just beyond your current abilities. Any more hard stuff than that and the practices can get too frustrating; any less and you won't be progressing as fast as you could. And don't shy away from the hardest part of a piece. That is the part that you should be focusing on most. Sometimes it's a few especially fast measures or a few oddly spaced notes or a tricky chord transition that's causing the most trouble. Play through that particular trouble section. Then reset and play it again and again and again until you've engrained the motion into your muscle memory and can play it without thinking. Then play through the entire song and see if the same measures come right out without any effort. If not, then go back and practice some more. Sometimes you won't get it in one practice session. Try repeating the problem area a set number of times each session, and eventually the right motion will sink in, and you can move onto the next problem area.

Programming has potential problem areas, too. What parts of the language or libraries you're using are difficult to understand? What features are hard to remember or use effectively? What areas of programming do you avoid because you haven't put in the time to learn them? These are the areas where you should be pushing yourself.

The best musicians always practice the fundamentals.


My guitar teacher told me a story of a journalist who was attending a concert featuring a famous pianist. Unfortunately I cannot remember either of their names now. Anyway, the journalist was going to interview this pianist the night before the concert, but when he went to his hotel room, he heard the pianist practicing and decided to listen outside the door for awhile. He would hear a single chord played, then a few second pause, then another chord, and another pause. This went on for some time before the journalist realized that the chords actually were part of one of the pieces that would be played the next day. This famous pianist, one of the best in the world, was practicing his concert pieces one chord at a time, making sure that every key press was absolutely perfect. Even the night before a concert, he was practicing the fundamentals in intimate detail.

Now in that case it was a pianist, but I'm sure that the best guitar players practice the fundamentals just as intensely. Every chord fingering, strum, pick, arpeggio, slide, and hammer on is practiced until it can be played without thinking. The fingers know what to do on their own so that the mind can be free to think about higher level tasks such as composition and style.

What would be the fundamentals to practice in programming? Language constructs, data structures, and algorithms should all be known inside and out. If you know these things cold, you can spend your mental energy on the higher level tasks of software engineering. They are the tools that make up your programming toolbox, and the more tools you know how to use, the more you can do. There are plenty of ways to practice as well. You can go through problems in your favorite algorithms book, implementing them in the language you're practicing. You can get ideas from websites that specialize in practicing programming. You can make up your own exercises and flex your creative muscles while your practicing. The more you practice the fundamentals, the better you're going to get.

The best musicians make hard pieces look easy.


It is amazing to watch a great guitar player. They make even the most complicated pieces look effortless. They have played for so long and practiced with such dedication that their instrument seems like an extension of themselves. They can do things with a guitar that most people wouldn't think possible. The best programmers can do the same thing with their instruments. They have spent so much time learning their tools that they know their text editors, their programming languages, and their environments inside out. And they can make them sing.

The more you practice, the easier it gets.


One thing I started noticing after months of guitar practice was that I would improve without realizing it. After learning a new song, I would attempt to play along with the recording, trying my best to keep up, but failing completely. I would practice the song for days or weeks, feeling like I wasn't making any progress. Then I would try playing along with the recording again and surprisingly, find that I was playing too fast. The improvements snuck in under my radar. I wasn't able to see the progress I was making without some external baseline to compare against. My wife would often provide another baseline. Periodically while practicing a new song, she would say, "Hey, I know what song you're playing!" That's always a good sign.

The point is, as long as you are practicing the fundamentals and the hard parts and doing it consistently, you are getting better, even if it doesn't feel like it. Eventually you'll reach a point where you can do things with ease that used to be a constant struggle. In programming, don't shy away from the difficult concepts. Attack them relentlessly until you can use them effortlessly.

Start by copying from the best.


When starting out with guitar practice, I picked songs that I knew well and wanted to learn how to play myself. Since these were some of my favorite songs with strong guitar parts, I had a clear idea of how to reproduce them, I easily noticed mistakes when I made them, and I could tell I was playing them right when they sounded like the song in my head. As I get better, I try out more difficult songs and learn new techniques. All of this becomes part of my growing repertoire. At some point I'll be able to create my own music and learn improvisation, but the best way for me to progress right now is to imitate and learn from the best.

The same concept should be applied in programming. Seek out good, clean source code to read and learn from. There is a wealth of open source code out there, and you likely have a favorite program that you can get the source for. Read through it and try to understand how the programmers structured the code. What design patterns do they use? What is their coding style? How do they use the language to accomplish their goals. Good source code contains a wealth of knowledge for you to explore.

Music is about patterns and sequences.


A song is not made up of one long series of individual notes. If it was, it would be almost impossible to memorize. A song is made up of sequences of notes, called phrases, that are equivalent to code blocks in programming. There are repeating patterns similar to program loops. There are codas that act like code branches or functions. Many times phrases are repeated with slight variations or shifts up or down the scale to create larger phrases from similar smaller ones.

The guitar chords are full of patterns, too. Most chords are created from only a few basic finger formations that are slid up or down the frets or back and forth to different sets of strings. Sequences of chords tend to follow patterns, and combining them with different strumming patterns creates all kinds of rich, rhythmic sounds. Arpeggios are chords that are played by quickly picking the strings in a pattern instead of strumming. All of these different patterns and sequences, once learned, can be strung together to create very complex sounding music while still being relatively easy to remember.

Programming is quite similar with basic code blocks being built up to create massively complex systems. Without the patterns and sequences that we have developed in programming, code would be a garbled mess, and we couldn't possibly hope to create the software systems we have today.

When learning a new piece, break it into small pieces.


Knowledge that the structure of music is made up of simpler patterns and sequences offers a great way to learn new pieces. If you know the patterns and how they repeat, you can easily play along with a song after only a few practice sessions. I've noticed this ability improving as I learn more chords and techniques. Chord sequences that I learn from one song show up in other songs all the time, and the more I learn, the faster I pick up new songs. Practicing sequences greatly improves muscle memory as well. This is how great guitar players can play a new song after having only heard it once, or even jump in and play along after hearing only a few measures.

The parallels to programming should be fairly obvious by now - picking up new songs is like writing new programs - but the connection goes beyond that. Once you know the basic patterns and sequences of programming, it becomes progressively easier to learn new programming languages. Most knowledge in one language is transferable to others, and the more languages you know, the better programmer you become.

The Zone feels good.


When you get into The Zone, it's as if the world melts away and the only thing left is you, your instrument, and the music. Time stands still. Your fingers dance across the strings. The notes resonate with your soul. These are the moments that are most satisfying. At first it doesn't happen often, but the better you get, the more time you spend in The Zone. Programming is much the same.

The Evolution of a Software Program

Analogies, anecdotes, and parables are all incredibly powerful literary devices that can be used to deepen your understanding of a complex topic and increase your ability to recall more details about it when you need to. When exposed to a new idea, your brain needs something for the new idea to hold onto, otherwise it takes a lot of repetition to lodge it into your long term memory. These devices work by relating the new idea to something you already know so that you can make associations between this weird new thing that you're trying to plant in your mind and something familiar that already has strong roots in your memory. The stronger the connections, the faster you can understand the new idea, and the longer you're going to remember it.

Beyond the mental connections that they make, analogies, anecdotes, and parables all tell stories about what the writer is trying to convey to the reader, instead of droning on with technical prose that will most likely put the reader to sleep. Stories show you what the writer is conveying rather than tell you what you should know. It's a far more interesting way to learn something, and you are much more likely to stay engaged and actually absorb the ideas when you're interested in what you're reading. I felt like I got so much out of The Pragmatic Programmer, because of the authors' use of stories to make their points.

I especially like analogies for enhancing understanding because they are so easy to find in everyday objects and activities. Both of the books I talked about last week made analogies between software development and other endeavors. Andy and Dave likened it to gardening in The Pragmatic Programmer, and Steve related it to building construction in Code Complete 2. Other analogies abound; just do a Google search for what software development is like for a little light reading. I think the variety and sheer volume of associations is excellent. Anything that helps you make new insights and become a better programmer is a plus in my book.

One way to think about software development that I would like to explore is that it is like evolution. Much has been written about software evolution, as in how a software system evolves over time, or the evolutionary model of software development. Those ideas are definitely part of what I'm talking about, but I want to go further and compare software development directly with the theory of evolution. Let's start with some simple associations and see how far we can stretch this analogy.

In the beginning, the theory goes, there was the primordial soup. In it were various organic compounds that had resulted from chemical reactions in the atmosphere. Over time these compounds reacted and combined into more complex polymers and amino acids, the building blocks of life. In the same way, the building blocks of a program are the programming language, libraries, and frameworks that are used to create it. You could go really basic with the building blocks and think of them as the assembly language instructions, or even the machine code that makes up a program, but then we would be describing the evolution of software development in general from machine code to assembly language to higher level languages and abstractions. I think that's a valid association, but I want to look at the evolution of an individual program written in a particular language. It could be any language, but the language is not what's evolving.

Every program has to start somewhere. A simple little proof-of-concept program that takes some input and produces some output is like a single-celled organism, or bacterium, that consumes fuel and produces waste. Okay, maybe 'waste' isn't the best association for a program's output. How about by-product? No, that's not much better. The point is that our little bacterium takes inputs from its environment and converts them in some way to produce something that it emits back into its environment - just like a barely useful initial program does.

From this basic program, the designer can add code to increase its capabilities, either by added features or improving performance. These improvements are the mutations in the program's evolution. Some mutations will be successful and will be kept, saved in the historic record of the version control system. You are using version control, right? Other mutations won't work so well, and will be discarded as cancelled features or mutated further into bug fixes.

As the program grows and evolves, it will become increasingly complex and interconnected, with newer systems built on top of older systems, just like the human brain is built up from older nervous systems, starting with the spinal cord and brain stem, then adding the limbic system, cerebellum, and finally, the cerebrum. Often times code loses its usefulness, but it remains in the program, Or it becomes redundant, but it isn't optimized out. We see similar examples in our own evolutionary history with many redundant parts, and other parts that we can't quite explain.

The compiled code of a program is similar to an organism's DNA. It can be replicated easily, and the compiled code is an exact description of how to create an instance of a running program on a computer. The code can be copied from one computer to another through various methods, and there we have the equivalent of reproduction. Each instance of a running program can vary based on its configuration and unique inputs, which could equate to variations in an organism's DNA and the environment it grows up in.

Evolutionary history also goes through cycles of dramatic explosions of mutations and rapid evolutionary progress followed by periods of relative calm and stability that end with mass extinctions. Software development cycles follow a similar pattern with periods marked by rapid evolution of the code base followed by slower periods when programmers take a rest and hopefully go on vacation. Mass extinctions can be thought of as happening at the release of a new software version when it replaces much of the installed base of the old version, sometimes more effectively and sometimes less.

To really be a useful analogy, evolution should lead us to new insights about software development, and I think it does. Starting with a small proof-of-concept program and then building on it, growing it into something more useful and complex with each iteration, is a highly effective way to develop software. Having a working system at every step of development is extremely beneficial. It may seem like building on top of working systems results in a convoluted mess of software layers, but these systems usually have a deeper elegance that takes study and time to appreciate. And of course, these systems have the unmistakable advantage of actually working. How many times have project teams attempted to build monolithic monstrosities only to watch as they collapse under their own weight? Software that evolves incrementally from one working version to the next has a much better chance of succeeding in the long run.