CHAPTER FIVE
Perpetual Learning
If we let ourselves, we shall always be waiting for some distraction or other to end before we can really get down to our work. The only people who achieve much are those who want knowledge so badly that they seek it while the conditions are still unfavourable. Favourable conditions never come.
C.S. Lewis, “Learning in War-Time”, The Weight of Glory and Other Addresses
Andy Hunt, a highly respected software craftsman, has asserted numerous times that software development is composed of two primary activities: learning and communication (Pragmatic Thinking and Learning, p. 3). We would build on that idea and assert that the core theme of an apprenticeship is learning and the dominant trait of a successful apprentice is a demonstration of her learning abilities. Apprentices are thirsty for opportunities to replace their ignorance with skill. This is no small feat when faced with the complexities of our work and the seemingly overwhelming amount of information that an apprentice must deal with. Beyond the fundamental act of learning Concrete Skills, an apprentice must also learn how to learn, for the transition to journeyman will certainly not remove the need for learning. One trait of a master craftsman is a willingness to set aside hard-won expertise in a specific domain in order to learn something new. Learning is a perpetual activity for those on The Long Road to mastery.
The Perpetual Learning patterns are applicable for your entire career, but with the apprentice’s emphasis on learning, it is critical that these patterns be applied early on in your journey. Expanding Your Bandwidth is the fundamental activity for apprentices looking to accelerate growth and facilitates several of the other Perpetual Learning patterns, such as Breakable Toys; Use the Source; and Practice, Practice, Practice. All three of these patterns grow out of an exposure to new information or a desire to acquire new knowledge: whether you’re practicing a new technique, building something in an effort to learn a new platform, or studying the source code of an innovative new open source tool. These more concrete patterns are followed by the softer self-discovery patterns that proceed from Reflect as You Work, which leads to Recording and Sharing what you’re learning. The critical patterns to take with you into the years beyond apprenticeship are Create Feedback Loops and Learn How You Fail. To transition to journeyman and ultimately master craftsman, you are going to need to be skilled at creating feedback loops, and also to be intimately familiar with your weaknesses.
Expand Your Bandwidth
[L]earning about what we don’t know is often more important than doing things we already know how to do.
Jim Highsmith, Agile Software Development Ecosystems
Solution
You have been drinking steadily through a straw. But there are seasons in an apprenticeship when one must drink from the fire hose of information available to most software developers.
Expanding your ability to take in new information is a critical, though sometimes overwhelming, step for apprentices. You must develop the discipline and techniques necessary to efficiently absorb new information, as well as to understand it, retain it, and apply it. This pattern means more than reading a book about an unfamiliar aspect of software development. It involves seeking out new knowledge and experiences in multiple dimensions. For example:
Sign up for Google Reader (or another blog aggregator) and begin subscribing to software development blogs. With modern machine translation technologies, you don’t even have to restrict yourself to those who write in English. You can follow Tim O’Reilly’s advice and track the blogs of what he calls “alpha geeks” across a variety of technology domains.1 These people aren’t necessarily the best programmers, but collectively they tend to sense new trends years before the rest of us. Consider using your own blog to reflect on the themes you pick up from these bloggers.
Start following some software luminaries on Twitter and pay attention to what they’re working on.
Subscribe to a moderately high-traffic online mailing list and try to answer people’s questions by reproducing their issues.
Join a newly formed local user group that is excited about a new technology. Don’t just attend silently—introduce yourself to the organizer and offer to help.
Persuade your employer to send you to a technical conference. Even if they won’t pay for you to attend, you can still read the slides on the website and download audio/video of the speeches.
After you read a book, contact the author with a note of appreciation and a question. Authors, speakers, and luminaries may seem intimidating or busy, but they often enjoy corresponding with readers.
Don’t forget that there are hundreds of online academic courses, podcasts, and videos (such as Google’s extensive series of Tech Talks) available for free through iTunes and YouTube.
As the priorities of your apprenticeship shift, you will eventually need to turn off the fire hose so that you can focus on project work. But there should be at least one season during your apprenticeship during which you use this pattern. It’s important not just because of the knowledge you will pick up during this time, but because it is actually a skill to be developed in and of itself. Journeymen and masters seek out opportunities where this pattern can be used to advance their careers and craftsmanship, particularly when they want to get into a new technology.
Once you understand how to Expand Your Bandwidth, the next step is to understand when to Expand Your Bandwidth. It’s possible to become obsessed with gathering and consuming new information, particularly as it becomes easier and easier to get at up-to-the-second thoughts on the most prolific thinkers in our industry. Some people could become lost in the sea of interesting information, and never come back to actually crafting software. While Expanding Your Bandwidth can be fun and is an interesting skill in and of itself, for the apprentice it is a means to an end. Use this pattern judiciously, for while it will accelerate your learning, it will slow down your development velocity, and therefore will have diminishing returns if applied for more than a few months.
Action
Attend a local user group within the next month. Research a related national conference you’d like to attend. Start reading a book by one of the conference speakers. Contact the author with some questions after you’re finished with the book.
Practice, Practice, Practice
The people we know as masters don’t devote themselves to their particular skill just to get better at it. The truth is, they love to practice—and because of this they do get better. And then to complete the circle, the better they get the more they enjoy performing the basic moves over and over again.
George Leonard, Mastery
Context
You want to get better at the things you do and you want to develop Concrete Skills in new areas.
Problem
The performance of your daily programming activities does not give you room to learn by making mistakes. It’s as if you’re always on stage.
Solution
Take the time to practice your craft without interruptions, in an environment where you can feel comfortable making mistakes.
In an ideal world we would use the technique of “deliberate practice” as described in K. Anders Ericsson’s research, and a mentor would assign you an exercise based on her understanding of your strengths and weaknesses. When you finished the exercise, the mentor would work with you to rate your performance using an objective metric and then work with you to devise the next exercise. Your mentor then would use her experience of teaching other students to devise new and more challenging exercises that would encourage you to reflect on your skills, find more effective work habits, and develop the ability to “see” in terms of ever more abstract “chunks” of knowledge. Over time, this chain of exercises would hone your strengths and correct your weaknesses. Sadly we do not live in an ideal world, and apprentices must fall back on their own resources to achieve the same effect.
“Pragmatic” Dave Thomas borrowed the concept of code katas from martial arts. A kata is a choreographed sequence of movements provided by a master to help his students internalize the fundamentals of the art. Katas are performed without opponents, emphasizing fluidity, power, speed, and control. Dave Thomas posted kata in his blog, encouraging craftsmen to use the kata to practice.
Laurent Bossavit and a group of software developers in Paris took the martial arts metaphor a step further and created a coder’s dojo, a place where people could meet regularly to publicly perform code katas. “Uncle” Bob Martin, inspired by the Paris dojo, also posts katas to his blog, espousing the merits of practicing the craft:
Obviously code kata are just one of the ways to Practice, Practice, Practice (Breakable Toys are another). The key to this pattern is to carve out some time to develop software in a stress-free and playful environment: no release dates, no production issues, no interruptions. As Dave Thomas says of practicing, “It has to be acceptable to relax, because if you aren’t relaxed you’re not going to learn from the practice.”
Short feedback loops need to be incorporated into your practice sessions. While practice is good in theory, if you’re not getting periodic feedback you’re probably developing bad habits. This is the beauty of the coder’s dojo: public performance within the context of a tight-knit community of craftsmen. This need for constant feedback lessens as you grow as a craftsman, and is gradually replaced by your duty to take on the role of a senior apprentice, modeling good habits by practicing with less experienced developers.
One of the reasons that the masters described by George Leonard love to practice is that they do something a little bit different each time an exercise is performed. The point is not to hone your memory, but to discover the nuances in even the simplest skilled activity. Your grandmother may have told you that practice makes perfect. She was wrong. In fact, practice makes permanent. So be careful what you practice, and constantly evaluate it to ensure you haven’t gone stale. Choosing the right thing to practice every day is a skill almost as important as the act of repeated practice. A good way to ensure you have interesting exercises to use in your practice sessions is to trawl through old books like Programming Pearls, More Programming Pearls, or Etudes for Programmers. They were written long enough ago that they had no choice but to focus on the fundamentals of computer science rather than the latest fashionable framework. Their authors understood that getting the fundamentals of algorithmic complexity and data structures deeply ingrained is seldom harmful and rarely stops being useful. These topics also offer a near-infinite source of interesting little problems to keep your practice sessions interesting, fresh, and educational.
Action
Find an exercise in one of the previously mentioned books or contrive one of your own. Make sure that it’s just a little harder than one you know you can easily solve. You should have to struggle to solve it the first time. Solve this exercise from scratch once a week for the next four weeks, and observe how your solutions evolve. What does this tell you about your strengths and weaknesses as a programmer? Take that knowledge and try to find or devise a new exercise that will have a measurable impact on your abilities. Repeat.
See Also
Breakable Toys
You can’t do anything really well unless you love it, and if you love to hack you’ll inevitably be working on projects of your own.
Paul Graham, Hackers & Painters
We can all benefit by doing occasional “toy” programs, when artificial restrictions are set up, so that we are forced to push our abilities to the limit.
Donald Knuth, The Art of Computer Programming
Context
Experience is built upon failure as much as (if not more than) success.
Solution
Budget for failure by designing and building toy systems that are similar in toolset, but not in scope to the systems you build at work.
If experience is built upon failure as much as success, then you need a more or less private space where you can seek out failure. In juggling, the three-ball juggler who never attempts five balls never makes the step up. Yet the one who gets backaches from having to pick up dropped balls for hours on end will eventually get it right. The same lesson applies to software. Just as the three-ball juggler would not attempt to juggle five balls during a performance, software developers need a safe place to make mistakes.
As a teenager working in Nova Scotia, Steve Baker was looked upon as a leader and an expert within his small development organization. Steve described how these expectations impacted him: “Everyone expected me to already know the right way to do it. Since I couldn’t use those projects as a learning experience, I had to stop learning.” This was similar to Ade’s consulting experiences, where he couldn’t afford to be wrong and he couldn’t just walk away from people who were depending on him to always be right. Ade knew that in order to learn, he needed the freedom to drop the ball. Like countless software developers before him, Ade used Breakable Toys to help him learn.
When implementing the Breakable Toys pattern, make your systems relevant and useful to your life as an apprentice. For example, build your own wiki, calendar, or address book. Your solutions might be massively overengineered for the problem they’re solving, and probably could easily be replaced by something off the shelf. However, these projects are where you are allowed to fail. They’re the projects where you can try ideas and techniques that might lead to catastrophic failure. But the only one who can be hurt by their failure is you.
A classic example of the use of this pattern is the multitude of people who have built their own wikis. A personal wiki is a great tool for the apprentice because you can use it to Record What You Learn. Wikis make good Breakable Toys because they can be incredibly simple4 and you can Use the Source to find countless examples to look. Over time, maintaining a wiki can teach you about HTTP, REST, parsing, web design, caching, full-text search, databases, and concurrency. If you stick with it long enough, it will also teach you about data migration when you eventually add a feature that requires a different storage format and you don’t want to throw away all your data.
Other examples of Breakable Toys include games like Tetris and Tic-Tac-Toe (one of our ex-colleagues is in the habit of writing a game in every new language he learns), blogging software, and IRC clients. The essential point is that building the toy involves learning new things, giving you an opportunity to gain a deeper understanding of your tools in an environment that is both safe (since you are the only or most important user) and where there is still room for you to better serve your own needs as a user than even the slickest of commercial alternatives.
These are your Breakable Toys. As you carry them with you from job to job, some of them will become living embodiments of your craftsmanship. Despite that, remember that they’re toys and as such should be fun. If they’re not fun, then after the initial burst of enthusiasm they will gather dust while you focus your energies on the things you actually enjoy building.
Often these toys are simple reimplementations of industry-standard tools that give you a deeper understanding of the forces that led to the current design of that tool. There’s even the possibility that one of your toys will take on a life of its own and acquire other users. In those cases you may find yourself having to seek out a new breakable toy.
Linus builds a toy OS5
From: torvalds@klaava.Helsinki.FI (Linus Benedict Torvalds) Newsgroups: comp.os.minix Subject: What would you like to see most in minix? Summary: small poll for my new operating system Message-ID: <1991Aug25.205708.9541@klaava.Helsinki.FI> Date: 25 Aug 91 20:57:08 GMT Organization: University of Helsinki Hello everybody out there using minix - I’m doing a (free) operating system (just a hobby, won’t be big and professional like gnu) for 386(486) AT clones. This has been brewing since april, and is starting to get ready. I’d like any feedback on things people like/dislike in minix, as my OS resembles it somewhat (same physical layout of the file-system (due to practical reasons) among other things). I’ve currently ported bash(1.08) and gcc(1.40), and things seem to work. This implies that I’ll get something practical within a few months, and I’d like to know what features most people would want. Any suggestions are welcome, but I won’t promise I’ll implement them :-) Linus (torvalds@kruuna.helsinki.fi) PS. Yes - it’s free of any minix code, and it has a multi-threaded fs. It is NOT protable (uses 386 task switching etc), and it probably never will support anything other than AT-harddisks, as that’s all I have :-(.
The Breakable Toys pattern is similar to Be the Worst, but that pattern is about finding a team where you can grow. Breakable Toys is more about deliberately creating opportunities to learn by stepping beyond your boundaries and single-handedly building complete software projects. It is also related to The White Belt and Confront Your Ignorance, but is less focused on letting go of your previous knowledge.
Action
Use your favorite tools to build the world’s simplest wiki while still maintaining the highest standards of quality. The initial version doesn’t need to have anything more than a simple user interface that lets you view and edit plain-text files. Over time, you can add more features and find interesting ways to distinguish your wiki from the thousands that already exist. Do not be constrained by existing implementations; instead, let your professional interests guide you. For instance, you might have an interest in search engines; in this case your wiki could experiment with ranking algorithms or tagging. It really doesn’t matter what you decide to do, as long as you experiment and learn.
Use the Source
The best way to prepare [to be a programmer] is to write programs, and to study great programs that other people have written. In my case, I went to the garbage cans at the Computer Science Center and fished out listings of their operating system.
Bill Gates, Programmers at Work
Context
Newcomers to the open source world often find that their questions are answered with the phrase “Use the source, Luke.” This expresses a fundamental truth about software: the code is the ultimate arbiter. The programmer’s intentions are irrelevant if the code disagrees. Only by reading the code can one truly understand a system.
Problem
Without exemplars of good practice to study and emulate, the Practice, Practice, Practice pattern only entrenches the bad habits you don’t know you have. If you never walk a mile in someone else’s moccasins, you may come to believe that all shoes are meant to have stones in them. So how do you find out if your work is any good, given that those around you may not have the ability to tell good code from bad?
Solution
Seek out other people’s code and read it. Start with the applications and tools you use every day. As an apprentice, one of the beliefs that can hold you back is the idea that the people who built the tools that you depend on are somehow different or special or better than you are. By reading their code you can learn to program like them, and more importantly, you can start to understand the thought processes that created the infrastructure that surrounds you.
When examining an open source project, get in the habit of downloading the current version of the source code (preferably from its source control system) so that you can inspect its history and track future progress. Examine the structure of the codebase and try to work out why the files were laid out that way. See if there is a rationale behind the way the developers modularized the codebase and compare it to the way you would have done it.
Try to refactor the codebases in order to understand why the programmers made the choices they did, and to see what the consequences would have been if you had been the one writing the code. This doesn’t just give you a better understanding of these projects; it also ensures that you can build the projects. And if you find a better way to do something, you are in a good position to contribute.
As you work through the codebase, you will inevitably come across decisions that you passionately disagree with. Ask yourself if perhaps the developers knew something you don’t or vice versa. Consider the possibility that this was a legacy design that needs to be refactored away, and think about whether putting together a toy implementation of the feature might be educational.
In addition to reading other people’s code (and, where requested, providing feedback), try to find people around you who are interested in reading your source code. If you can learn to embrace their feedback while filtering out personal idiosyncrasies, you will become a better programmer. And remember, to become a journeyman you have to help others grow, so be open to reading other people’s source code as well.
A common approach among the programmers we interviewed involves joining a team or project that uses code reviews or pair programming. These practices create environments in which the programmers could safely spend time reading other people’s code, having others read their code, and learning from each other. These groups tend to produce extremely strong programmers. Other environments, such as most academic computer science departments, tend to overlook the fact that working programmers spend far more time reading code than writing code. They take this approach because making every student reinvent the wheel creates artifacts that are easy to grade. However, training yourself to be better at the task that takes up most of your working day is an optimization that yields greater rewards in the long run. This is true even if the nonprogrammers who are often in charge of these environments don’t appreciate it.
By reading a wide variety of good, bad, and indifferent code written by other people you can start to learn about the idioms and subtleties of your particular language community. Over time, this will develop your ability to divine people’s intentions from the code they have written. It will also help you learn to deal with those occasions when the two have diverged. These skills will make you a more valuable part of a team, because you’ll be able to work on other people’s code without always having to rewrite it because you can’t tell what it does.
Eventually you’ll acquire a toolbox of tricks and subtleties gleaned from other people’s code. This hones your ability to solve small problems quickly and easily, just because you’ve seen something similar before. You’ll be able to tackle problems that others consider impossible because they don’t have access to your toolbox.
Take a look at Linus Torvalds’s code for the Git distributed source control system or anything written by Daniel J. Bernstein (commonly known as djb). Programmers like Linus and djb casually use data structures and algorithms most of us have never even heard about. They’re not magicians—they have merely spent time building a bigger and better toolbox than most people. The advantage of open source is that their toolboxes are open for you to inspect, and you can make their tools your own.
One of the problems with the field of software development is the lack of teachers. But thanks to the proliferation of open source projects on sites like sourceforge.net, GitHub, and Google Code, you can learn from a more or less representative sample of the global community of programmers. Unlike in traditional teaching, these are not toy projects designed to illustrate a point, rife with shortcuts and “exercises for the reader” when things get difficult. These are real projects that solve real problems and are constantly in flux. You can track a project as its developers learn and adapt to new requirements. By studying the way real codebases evolve, you can better appreciate the effects of design decisions without having to build hundreds of software projects yourself. This offers an opportunity to learn from other people’s mistakes and to acquire a more vital skill than mere code reading: the ability to learn without being taught.
In Programmers at Work, Bill Gates said that “one of the finest tests of programming ability is to hand the programmer about 30 pages of code and see how quickly he can read through and understand it.” He had realized something important. People who can quickly absorb knowledge directly from the code soon become much better programmers, because their teacher is every line of code written by every programmer ever born.
Action
Pick an algorithmically sophisticated open source project such as a source control—system, for example, Subversion, Git, or Mercurial. Browse the project’s source, noting down the algorithms, data structures, and design ideas that are new to you. Now write a blog post describing the architecture of the project and emphasizing the new ideas you have learned. Do you see places in your everyday work where the same ideas can be applied?
See Also
Reflect As You Work
Self-examination is hard, but I believe we can learn more from studying our failures than from our successes.
Norm Kerth, Project Retrospectives
Context
Anyone who is reasonably competent will find themselves being pushed up the promotion ladder over the years. Sooner or later you end up wearing the senior developer hat in a corporate team or open source project. If you do not take steps to prepare yourself for that elevation, you may suddenly find yourself a victim of the Peter Principle, where you are promoted to your “level of incompetence.”
Problem
As the number of years and projects you have under your belt increases, you find yourself awaiting the epiphany that will magically make you “experienced.”
Solution
Become a reflective practitioner of software development. This involves regular introspection into how you are working. Consider whether your practices are novel, innovative, or outdated. Ask yourself questions about the things that the rest of your team takes for granted. If there is something particularly painful or pleasant about your current work, ask yourself how it got that way, and if things are negative, how can they be improved? The goal is to extract the maximum amount of educational value from every experience by taking it apart and putting it back together in new and interesting ways.
One technique that’s useful in making this kind of reflection explicit is to use something like a Personal Practices Map. This is an idea that Joe Walnes introduced at London’s Extreme Tuesday Club. It involves people consciously writing down the things they do and the connections between them. After everybody has written down their practices, the group discusses the practices that have been identified. If you take a look at the web page “Maps of People’s Personal Practices,” 7 you will see maps created by Ade and several other developers.
One of the consequences of repeatedly using this technique is that it highlights the changes in your set of practices. So for example, in the years since 2003, Ade has moved from “never using debuggers” to practicing “test-driven debugging” to starting to deliberately use invariants when implementing complex algorithms. The existence of a tangible and visible map of your practices leads to deeper reflection about the effect of any one change in the techniques you use. In Ade’s case, the adoption of test-driven development led to the reevaluation of all the other practices, and the map became a tool for visualizing this change.
This process of observation, reflection, and change isn’t limited to just your own activities. Unobtrusively watch the journeymen and master craftsmen on your team. Reflect on the practices, processes, and techniques they use to see if they can be connected to other parts of your experience. Even as an apprentice, you can discover novel ideas simply by closely observing more experienced craftsmen as they go about their work.
In 2004, Dave was part of an XP team that contained several world-class developers. They had a fairly standard style of pair programming: one guy would write a test and slid the keyboard over to his pair, and his pair would make the test pass, immediately write a test, and slide the keyboard back to the first guy. The first guy would pass the test and so on. This style of pair programming was never really discussed; it just emerged out of their respective experiences.
Dave joined his next project, and while explaining this style of pair programming to his new teammates he realized that the style needed a name. Dave blogged about it, which kicked off a chain reaction that quickly led to an offer to write a few columns for StickyMinds.com. All this happened simply because Dave reflected on the practices introduced by more senior developers.
The Agile community has adopted a version of this process. Driven by Norm Kerth’s book Project Retrospectives, it involves the team periodically gathering to look back on the state of the project in order to find ways to improve. As such, it is more formal than the continual self-analysis that an apprentice will undertake. It also requires reasonably enlightened management willing to provide a safe environment by honoring Kerth’s prime directive: “Regardless of what we discover, we understand and truly believe that everyone did the best job they could, given what they knew at the time, their skills and abilities, the resources available, and the situation at hand.”8
Apprentices won’t always have the luxury of working in such environments, but the habit of productive reflection can be useful even in less forgiving corporate cultures.
If you hang on long enough, people will start calling you “experienced,” but that should not be your goal. All experience indicates is that you have been able to survive. It does not indicate the amount you have learned, only the time you have spent. In certain parts of our industry, it is quite easy to repeat the same year of experience 10 times without making significant progress in your abilities. In fact, this sometimes can turn into anti-experience: the phenomenon where every additional year or experience merely reinforces the bad habits you have picked up.9 This is why your goal should be to become skilled rather than experienced. The increase in your skill level is the only meaningful testament to the effort you have spent inspecting, adapting, and improving your working habits.
Action
Draw a Personal Practices Map for your working habits. Concentrate on the connections between any practices that have not changed in a while. Ask yourself how your map would change if you discovered that one of those practices was actually counterproductive. Closely examine one of those practices and find out if there are other ways to achieve the same goal. These don’t have to be better ways; it’s enough for them to be different. Now ask yourself what would happen to your map if you were to adopt one of these different practices.
Record What You Learn
You should not also underestimate the power of writing itself....You can lose your larger sense of purpose. But writing lets you step back and think through a problem. Even the angriest rant forces the writer to achieve a degree of thoughtfulness.
Atul Gawande, Better
Context
You learn the same lessons again and again. They never seem to stick. You often find yourself repeatedly doing things such as setting up CruiseControl, modeling hierarchies in SQL, or introducing patterns to a team. You remember doing very similar things in the past, but the exact details escape you.
Problem
Those who do not learn from history are doomed to repeat it.
Solution
Keep a record of your journey in a journal, personal wiki, or blog. A chronological record of the lessons you have learned can provide inspiration to those you mentor, since it makes your journey explicit, but it can also give you a vital resource to draw upon. Those who use this pattern sooner or later experience a moment when they’re searching for the answer to a tricky problem and their search engine gives them a link to their own wiki or blog.
Using a blog to record the lessons you’ve learned also has the side benefit of helping you meet Kindred Spirits, while a wiki that has accidental linking allows you to see the connections between your experiences.
Try to avoid falling into the trap of just writing down your lessons and forgetting them. Your notebook, blog, or wiki should be a nursery, not a graveyard—lessons should be born from this record, rather than going there to die. You make this happen by regularly going back to read what you’ve written. Try to make new connections every time you review the material. This process of creative review can lead you to reevaluate old decisions based on new data, or it can reinforce beliefs that were wavering. Either outcome is fine, as long as you don’t stagnate. By reviewing your journal, you can switch your past and your present around in order to generate your future.
Ade uses two instances of the same wiki, one for his private thoughts and the other for stuff he wants to share with the world. Keeping a private record as well as a public record means that you get the best of both worlds. Your public record becomes a means of sharing the lessons you have learned and gaining feedback from a wider community; the private record allows you to be painfully honest with yourself about the progress you are making. Having both internal and external feedback loops can give you increased confidence that you are maintaining an accurate self-assessment.
When Dave was Reading Constantly during his apprenticeship, he kept a text file in which he transcribed all the quotes that shaped his learning. Over the years, that file grew to contain over 500 quotes, and Dave eventually decided to upload it and share it online.10 This proved to be an excellent source of references when Dave started writing articles and this book.
Also keep in mind that your choice of record-keeping tool can also be an important Breakable Toy.
This pattern is similar to Share What You Learn, but there the emphasis is on preparing to become a journeyman by improving your ability to communicate with honesty and humility. Here the emphasis is on preserving the route you took to mastery so that in future you can extract new lessons from it.
Action
Grab a paper notebook and start jotting down your thoughts about this book and any ideas it inspires. Make sure your notes have a date on them. Once you’ve finished this book, keep using the same notebook in the same way for the other things you learn. Over time these entries may become the basis for blog posts, magazine articles, or even a book.
See Also
“Breakable Toys”, “Kindred Spirits”, “Read Constantly”, and “Share What You Learn”.
Create Feedback Loops
We in the software industry are working with a more or less invisible product, yet this very invisibility only heightens our need for feedback.
Jerry Weinberg in Norm Kerth’s Project Retropsectives
Context
You can’t tell if you’re suffering from “unconscious incompetence” since, as Justin Kruger and David Dunning put it in their article of the same name, those who are unskilled are often unaware of it. Moreover, the less skilled you are, the worse you are at assessing the skills of yourself and others. Success or failure tends to come as a surprise, and what little feedback you receive is an abrupt shock to your self-assessment instead of a support mechanism to help you improve.
Problem
Your self-assessment is only relative to the abilities you used to have, and will always lack objectivity. The teams you work with can easily skew your sense of your own competence. Being on an above-average team can either make you feel like a superstar when you’re really more of a backup singer, or destroy your self-confidence when everybody seems so much more competent than you. On the other hand, a below-average team can make you feel complacently smug. Even if you use Reflect as You Work, it will only help you analyze the past rather than inform you about the present.
Solution
Create mechanisms for regularly gathering more or less objective external data about your performance. By soliciting feedback early, often, and effectively, you increase the probability that you will at least be conscious of your incompetence.
There are a variety of mechanisms available for acquiring feedback. At one level these include using techniques like test-driven development or dynamically type-checked languages with interactive interpreters to cause your programs to fail fast. At another level you may acquire feedback by getting your code reviewed or by pair programming. Exams and certifications can also be useful metrics for gauging your ability compared to others, although these often test only your exam-taking technique rather than your skill. Another way of gaining feedback is to ask people how they think you are doing; for example, contact people who interview you for a new job or promotion and ask them their opinion of you. Even if you didn’t get the job, you can gain a lot from being told precisely why you were turned down. Sometimes this feedback will reveal facets (both positive and negative) of your personality that you were unaware of.
All of the mechanisms described above will be useless if you haven’t developed the ability to process the raw data. For instance, if your employer provides annual reviews, you have to be able to separate the wheat from the chaff in order to get to the useful feedback. Criticism on its own is seldom useful feedback because it doesn’t tell you what is expected of you. Other kinds of bad feedback include feedback that is more about the other person than you (e.g., “Do this because I did it when I was your age”), that is really disguised advice, or that is what Dave Winer calls “stop energy.”11 This usually manifests itself as well-meaning advice telling you why you can’t achieve your goals and should give up immediately rather than risking failure.
So what does useful feedback look like? Useful feedback is data that can be acted upon and that gives you the option of doing more or less of a certain behavior. If you can’t do anything about it, then it’s not useful feedback. Or at least it’s not useful today. If your circumstances change it may suddenly become highly relevant. Try to keep in mind the advice that “if you count something interesting, you will learn something interesting” (Better, p. 255).
It’s also important to be aware of the distinction that systems thinkers make between reinforcing and balancing feedback. Reinforcing feedback encourages you to do more of something. Balancing feedback encourages you to do less of something. By combining the two types of feedback, a system can be kept relatively stable by making lots of small adjustments. Successful apprentices learn to create situations where they can quickly and frequently receive data about whether they need to do more or less of an activity. This often means learning to communicate your ideas and listening without interrupting.
Acquiring the ability to avoid defending your current level of knowledge in favor of paying careful attention to any feedback is one of the ways in which this pattern overlaps with The White Belt. Both patterns emphasize the idea that the apprentice should strive to become more teachable so that the pool of potential teachers expands.
Action
Find something in your working environment that you can measure and, more importantly, affect. Track that metric for a while. As it changes, ask yourself what it’s telling you about your world. See if you can use it (and other metrics) to understand the effects of the changes you are making to your working environment.
See Also
Learn How You Fail
Ingenuity is often misunderstood. It is not a matter of superior intelligence but of character. It demands more than anything a willingness to recognize failure, to not paper over the cracks, and to change. It arises from deliberate, even obsessive, reflection on failure and a constant searching for new solutions.
Atul Gawande, Better
Problem
Your learning skills have enhanced your successes, but your failures and weaknesses remain.
Solution
Seek to identify the ways in which you tend to fail and try to resolve those that are worth fixing.
This is not about wallowing in self-pity about past mistakes nor is it an exercise in seeking perfection. Instead, the goal is to gain self-knowledge about the patterns, conditions, habits, and behaviors that lead you to failure. Armed with that self-knowledge, you can make conscious choices and temper the tendency toward idealism when applying “Draw Your Own Map” with an awareness of your boundaries and limitations.
By becoming conscious of the things that trip you up, you allow yourself the choice between working to fix these problems or cutting your losses. Accept that there will be some things that you’re not good at, or that would require a disproportionate investment of time and effort in order to make a small improvement.
This feeds into your accurate self-assessment, but it also enables you to set realistic limitations on your goals. You can’t excel at everything, and accepting these limitations is important, as it forces you to consciously acknowledge distractions and focus on your goals. It may mean accepting that you’re never going to make the time for that part-time PhD course, or it may mean letting go of old areas of expertise because you can’t devote the time to maintain those skills.
For example, Ade keeps a set of pages on his private wiki listing his current skillset and his limitations or boundaries. This enables him to select which boundaries to push outward (e.g., try maintaining a large codebase in a dynamically type-checked language) and where to stop wasting effort (e.g., accept that the 6502 assembler for the Commodore 64 is unlikely to undergo a massive resurgence).
Action
In the programming language of your choice, use a simple text editor (later on you will see why it’s important that you don’t use an IDE for this exercise) to write an implementation of binary search in one sitting. Do not compile or run it yet. Now, write all the tests that you think you will need to verify that you have a correct implementation. Keep note of the bugs and problems you discover at this stage. Now, still without compiling or running the tests, go back and fix all the problems that you have discovered so far. Iterate until you’re satisfied that the code and the tests are both perfect. Finally, try to compile and run the tests. Most people will discover corner cases they hadn’t thought of and trivial little errors. Before you fix these errors, try to understand how they could have occurred in something you were sure was perfect. What does that tell you about yourself? Write down what you learn in the iterations between what you thought was perfect code and the point when you have code that actually compiles and passes all the tests. If you’re feeling particularly brave, get a friend to review the code and see what else she can discover.
See Also
Wrapping Up
Perpetual Learning can be viewed as a blessing or a curse. Learning something new can be painful, especially when it is done under pressure and with little guidance. Yet, like the athlete who must endure muscle soreness after strenuous workouts, the software developer endures the mental dissonance that comes with learning something new. That dissonance can become a welcome sign of progress. Self-reflection, identifying failure through feedback loops, and learning your weaknesses all appear negative on the surface, but these patterns are helping you to reduce your ignorance. The alternative is to focus exclusively on what you already know, but this is not the way toward mastering software craftsmanship; it is the way to specialization in a single expertise. Phillip Armour, in his paper “The Five Orders of Ignorance,” focuses on the roles of ignorance and knowledge in software development:
1 Tim O’Reilly, “Watching the ‘Alpha Geeks’: OS X and the Next Big Thing.” Available at: http://www.linuxdevcenter.com/pub/a/mac/2002/05/14/oreilly_wwdc_keynote.html.
2 Dave Thomas on Code Kata: http://codekata.pragprog.com/2007/01/code_kata_backg.html.
3 Robert Martin on the Programming Dojo: http://butunclebob.com/ArticleS.UncleBob.TheProgrammingDojo.
4 Shortest Wiki Contest: http://c2.com/cgi/wiki?ShortestWikiContest.
5 The first public announcement of Linux http://groups.google.com/group/comp.os.minix/browse_thread/thread/76536d1fb451ac60/b813d52cbc5a044b.
6 Keynote at Ruby Hoedown 2008. Video at http://rubyhoedown2008.confreaks.com/08-chris-wanstrath-keynote.html. Transcript at http://gist.github.com/6443.
7 http://www.xpdeveloper.net/xpdwiki/Wiki.jsp?page=MapsOfPeoplesPersonalPractices
8 The Retrospective Prime Directive: http://www.retrospectives.com/pages/retroPrimeDirective.html.
9 Anti-Experience: http://c2.com/cgi/wiki/changes.cgi?AntiExperience.
10 http://redsquirrel.com/dave/quotes.html
11 “What is Stop Energy?” Available at: http://radio.weblogs.com/0107584/stories/2002/05/05/stopEnergyByDaveWiner.html.
Get Apprenticeship Patterns now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.