Guidance for the Aspiring Software Craftsman
by Dave Hoover, Adewale Oshineye
Read Status: Completed 📕
Last Updated : 09 Oct 2021
16 min read ☕️
- How I Discovered It
- Who Should Read it
- Key Ideas
- Pattern Lists
- Emptying the Cup
- Walking the Long Road
- Accurate Self-Assessment
- Perpetual Learning
- Construct Your Curriculum
In this book, the authors argued that there are no masters in software development yet. It is hard to assess a candidate for mastery. For now, the best way to detect mastery is by examining the quality of the person's work and that produced by his apprentices. There is much to explore in software development, and the authors hope that the 35 patterns in this book can help fellow craftsmen to navigate the long road ahead.
I discovered this book on GoodReads after I completed the book, Mastery by Robert Greene by Robert Greene. I was looking for an apprenticeship related book in the Software Engineering field, and this book came top on the list. Along with this discovery, I also found the Epic CTO Reading List, which contains other SWE-related books for future reading.
I feel that it is a good read for anyone in the software engineering field, regardless of experience. I would recommend this book for newcomers, especially students who are interning or looking for an internship as a software engineer. It really helps in putting you in the right mindset for the internship. It is one of the books that I have wished I had read earlier.
The authors emphasized this about the usage of this book, “This book is not meant to be used as a reference, but is more like an artist’s source book—you can dip into it for inspiration from time to time. You might even invent some new approach to using this book that we haven’t thought of.”
A pattern is a name for a recurring solution to a problem in a particular context.
Just like how we apply design patterns in our work to solve common engineering problems, the use of pattern language can help us rethink how we think about our career as a whole.
It is an important reminder that any pattern is intended to contain a family of solutions to a family of problems within a specific context. Patterns are meant to be modified to fit your needs rather than being applied mechanically. Be prepared to expect different results even when you apply them in a similar context. Instead of thinking them as algorithms that always return the same result, imagine apprenticeship patterns as tools to solve one set of problems while creating new ones. The trick is to use your discretion in selecting the problems you prefer.
A pattern language gives each person who uses it the power to create an infinite variety of new and unique buildings, just as his ordinary language gives him the power to create an infinite variety of sentences.
—The Timeless Way of Building, p. 167
The modern concept of apprenticeship is mainly a frame of mind: you recognize that you are still at the beginning, even if you’ve been programming for several years, and you are prepared to take steps to create your apprenticeship out of the circumstances you are in. ... In reality, most people have to claw and scratch their apprenticeships out of less-than-ideal situations. They might be facing overbearing and/or incompetent managers, de-motivated coworkers, impossible deadlines, and work environments that treat novice developers like workhorses, storing them in small, rectangular stalls with a PC and a crippled Internet connection.
An apprenticeship is a period in your career when your primary focus is on your own development rather than anything else. This is the time to prioritize learning opportunities over earning potential.
Have the mindset that there is always a better/smarter/faster way to do what you just did or what you're doing now: Keep a lookout for people, companies and situations that will force you to learn better/smarter/faster.
Value learning over the appearance of smartness, to enjoy a challenge, and to use mistakes as stepping stones to mastery.
Learn to grow yourself, learn how to learn
When that period is over, you will have to adapt. Despite the fact that you still have a lot to learn, you will no longer be an apprentice, and your priorities will need to shift towards more outward-looking responsibilities.
- An added focus on the connections between practitioners, the communication channels within and outside the team. This focus will eventually lead to the responsibility of mentoring those around you and communicating with the rest of the industry.
The journeyman is focused on building an ever-larger portfolio of applications that demonstrates his progress in the craft; he moves between projects and masters, seeking to diversify and deepen his portfolio; he seeks to elevate his status within the community; and he strives to become ready to be a master.
- Build a portfolio of applications to demonstrate your craftswork. Seek to diversify and deepen your expertise
- An focus on moving the industry forward. This could be in the form of developing new tools that get to the heart of software development, or it could be in the form of training a new generation of journeymen whose skills equal and then surpass your own.
A collection of values that the authors find in highly competent people and hope to see more in the dev community.
- Have a growth mindset
- Adaptive to feedback
- Choose pragmatic over dogmatic: This reminds me of Good Enough.
- Share knowledge
- A willingness to experiment and be proven wrong
- Have an internal locus of control: be in control and responsibility of what we can accomplish
- A focus on individuals rather than groups: This is not a movement with leaders and followers.
- A commitment to inclusiveness to identify and absorb the best ideas from all areas of the dev community.
- Choose skill-centric over process-centric: no process or tool is going to make everyone equally successful. It is more important to pick up valuable skills.
- Be in a community of practice
To make it easier for me to remember, I have simplified the patterns into standalone concepts (with some snippets of personal opinion from experience). Feel free to refer back to the book to identify the interconnectedness of these patterns.
The more experience you already have, the more effort you will need to put into “emptying your cup,” clearing your mind of bad habits, setting aside the pride you have in your skills, and opening yourself up to the different, often counterintuitive, approaches of your more experienced colleagues.
In this pattern section, ignorance is a central theme. Ignorance is not a bad thing if it is recognized and confronted. Avoid the Dunning–Kruger effect.
Pick your first language wisely. Become fluent in it. Make it a challenge to use this language to solve your problems for the next few years. The best way to learn is to have an actual problem to solve. Build side projects.
You shouldn’t be wedded to any particular technology, but have a broad enough background and experience base to allow you to choose good solutions in particular situations. — Dave Thomas and Andy Hunt, The Pragmatic Programmer, p. xviii
You have developed a deep understanding of your first language. However, your learning pace has also plateaued.
To move forward, have childlike thinking. Cultivate a beginner's mindset. For example, take a program you have written in one programming paradigm (e.g., imperative, object-oriented, functional, array/vector-oriented, etc.) and implement it in a language that uses a different paradigm.
Because of your inexperience, you bring some unique attributes to your team, including an infectious enthusiasm. Do not allow anyone to dampen your excitement for the craft. It is a precious commodity that will accelerate your learning.
There is a tendency for people to conform to the norm. They either repress their enthusiasm or unleash it outside of their jobs. However, unleashing your enthusiasm is one of the few responsibilities as a newbie. You may not bring deep knowledge or expertise, but you can inject excitement into your team and bring in a fresh perspective of seeing things.
Don't be afraid to propose new ideas or suggestions and persuade your team members to point out flaws to help you improve them.
Acquire and maintain concrete skills. Knowing is not the same as having the practical ability to execute the task. It is more than just getting past crude HR filters by strategically include tech buzzwords in your resume.
Collect the CVs of people whose skills you admire. Identify a few skills that would be immediately applicable in your circumstances. Find out the steps on how others have done to acquire these skills. Make a plan to implement a toy project that can demonstrate your practical skills.
Go through your CV regularly. Are you comfortable knowing that many hiring managers will only look at the items in this list rather than the sum of your experiences?
Get used to this learning process ... Expertise is a by-product of the long road we’re all on, but it is not the destination.
Because of your inexperience, you have many zones of ignorance. When working with other stakeholders, you can see the need for confidence when they ask you how long a feature will take you to finish. Your instincts tell you to hide your ignorance, to feign expert knowledge, but this only stunts your growth and inhibits the work you are trying to accomplish.
Show the stakeholders that the learning process is part of delivering software. Let them see you grow. Reassure them with your ability to learn, not by pretending to know something you don’t. Build your reputation upon your learning ability. This is the way to build strong relationships with your clients and colleagues.
After identifying gaps in your skillset for your daily work, actively fill these gaps in effective ways.
Build toy projects. Read articles. Go through tutorials. Join a like-minded study group. Seek mentors. Recognize that you don't have the time to hone all your skills to a high level, prioritize accordingly.
"Do scary stuff". Waiting until you’re ready can become a recipe for never doing a thing. So when you’re offered a high-profile role or a difficult problem, grasp it with both hands. Growth only happens by taking on difficult jobs and doing things that stretch you. Challenge yourself with bigger things. This may involve bigger projects, larger teams, more complex tasks, new and business domains, or new places.
Be careful not to drown. It is also your responsibility to create feedback loops, offset your risks by seeking help etc, if you find that the challenge is getting out of control.
Perhaps you have jumped into the deep end, and things aren't working out so well. Retreat briefly into your competence to regain your composure. Take some time to build something that you know how to make.
Going back to your comfort zone is risky if it is done too often or too long. Set reasonable limits to retreat, e.g. timeboxing, and bounce back when you are composed.
Do you keep a list of certifications to prove and reassure that you are "trained enough" or "prepared enough"? Take a peek at the forums and Github, and you realize there are so many other developers creating great software in ways you can't imagine. You are impressed. You get inspired. You get discouraged by how little you know. Recognize how far you can go. It is a long road. There are remarkable individuals ahead of you. Recognize that everyone is walking the same long road.
Conventional wisdom tells us to take the highest-paying job and take the first promotion. Instead, you should value learning and long-term growth opportunities over salary and traditional notions of leadership. Draw your own map and be aware of what you want to do.
Imagine the role you want to play in 10 years time. What kinds of experiences do you want to have tried? Work towards it, and remember that it takes time for you to grow.
The people who walk The Long Road are not the heroes who sprint for a few years and burn out—they are the people moving at a sustainable pace for decades.
You need to do your best work in ways that place the interests of your customers over your desire to display skill or pad your resume, while still adhering to the minimum standards of competence provided by the software development community.
Choose utility over artistry without compromising on quality.
Working in a real-world project is rigorous, sometimes exhausting, often frustrating, and frequently overly chaotic or constraining. There will be days when you love your jobs. There will be days when you are faced with bureaucracy, stuck with ambiguous requirements or spotty leadership. These are the days that you will start questioning your motivation. Is it money? Is it your enjoyment of programming? Keep a list of the most important things that motivate you. This list will come in handy when times get tough.
The authors also caution about motivation traps.
In More Secrets of Consulting, Dorset House, Jerry Weinberg describes this phenomenon as the Golden Lock: “I’d like to learn something new, but what I already know pays too well.”
Be wary of Golden Locks. You will be faced with tough decisions along your long road. Expand your toolset? Or stick with what is familiar?
In a presentation at O’Reilly’s Open Source Convention (OSCON) 2004 entitled Great Hackers, Paul Graham said, “The key to being a great hacker may be to work on what you like.... To do something well you have to love it. So to the extent that you can preserve hacking as something you love, you’re likely to do it well.”
Take steps to protect and grow your passion for software craftsmanship. Work on what you like, be it at work or during your free time. Create / join a like-minded group (using Knowledge Hydrant patterns) or build side projects.
If work is affecting you, set clear boundaries.
Identify a logical but ambitious next step for your career. List down a few jobs that your current role can lead to. What other roles could these possible jobs lead to? Do you find a path that resonates with you? If not, try to think out of the box. What if you are willing to move to another country, change programming language or even start your own business?
It is important to be constantly self-aware of your potential paths beyond your current role in the company. Does your current company allow you to do the work that you want to do? Perhaps you want to do a mix of dev and DevOps work. Maybe you want to work with a newer tech stack. Organizations tend to pigeonhole their people ("resources") into fixed roles. Work with your company to explore the work that you want to do. Otherwise, define small steps forward and TAKE THE FIRST STEP.
Do you feel that your job title doesn't match your skill levels? When introducing yourself, do you feel the need to explain the difference between your skill level and your job title?
Use your title to gauge your organization, not yourself.
Do not let impressive titles fool you that your apprenticeship is over. Do not be discouraged by the lack of recognition either.
Write down a descriptive version of your job title. Keep it updated and accurate. Imagine how you would view a stranger with this job title. Do you like what you see?
You have been offered a promotion into a role that will pull you away from programming. Most people equate promotion to management with success.
As Pete McBreen wrote, “as soon as a person stops practicing, her mastery fades.” Every day that you are not programming is another step away from becoming a journeyman. Work with your employer to seek other ways to reward you if possible.
You realize the path you want is no longer what you want. You want to pursue something else temporarily or permanently. Conventional companies may find these detours as suspicious gaps in your career. Despite this risk, don’t be afraid to do something different with your life. The habit of rigorous thinking from the SWE career will be useful wherever you go. Similarly, new experiences can broaden your thinking and perspective.
Are you a small fish in a big pond? Or are you a big fish in a small pond? Your goal isn’t to become slightly better than the “average developer”. You must fight the tendency towards mediocrity. You can seek out how other teams, master craftsmen, work at a proficiency level that an apprentice cannot even imagine.
Ambition and humility are key foundations of a successful apprenticeship.
Surround yourself with developers who are better than you. Find a stronger team where you are the weakest member and have room to grow. Being the worst on a team of outstanding developers can’t be compensated for with environment, equipment, or money.
The goal is not to stay the weakest but to work harder than anyone else and work your way up.
However, this pattern may not be for more experienced developers who are looking to become journeymen. You should be looking to mentor novices and give others the opportunities you had been given.
Seek advice from those who are ahead of the road than you. It may be simple in concept but hard in execution. These people may not be at the stage to take in apprentice. You may find it hard to reach out to ask for something as strange as an apprenticeship.
No one knows everything. You may be supervised by mentors who possess varying degrees of mastery.
You need camaraderie while walking the long road. Find a community of talented people working on related problems.
Find ways to work with another software developer to accomplish a hands-on task together, side-by-side. Some things like micro-techniques can only be learned while sitting with another software developer to achieve a shared objective.
The goal is to find ways to expose yourself to the daily working habits of other skilled people and observe how they gradually refine those habits into even greater skills. These habits extend beyond coding and into all aspects of software development.
You are new to the team. You are unsure of your place on the team, and the team is unsure of you.
Volunteer for simple, unglamorous, yet necessary tasks. Find the onboarding guide or some documentation outdated? Volunteer to update it. Find that nobody is taking down the feedback from the stakeholders during sprint review? Volunteer to take notes. Respond to simple maintenance requests and bug fixes. Write some script to automate some simple yet essential tasks.
You may end up as the team's gopher, condemned to do the menial tasks no one else will do. Look for opportunities to prove yourself worthy of higher-level work.
Perpetual Learning patterns are crucial in the early portion of your learning journey. Nonetheless, it is applicable throughout your career.
Your understanding of software development is narrow and focused only on the low-level details of what you’ve worked on in your day job.
Expand your ability to take in new information by attending tech conferences, follow software luminaries on Twitter, listen to podcasts and so on. The authors suggest following Tim O’Reilly’s advice and track the blogs of what he calls “alpha geeks” across a variety of technology domains.
Don't let the sea of new information overwhelm you affect your development velocity.
Practice Code Katas.
Software developers need a safe place to make mistakes. Build toy systems that are similar in toolset to the systems you build at work and experiment. This allows you to gain a deeper understanding of your tools in a safe environment.
Practice code reading. Read a wide variety of good, bad and indifferent code written by other people. Over time, this will develop your ability to divine people’s intentions from their written code. You will also acquire a toolbox of tricks and subtleties gleaned from other people’s code.
Code reading is the ability to learn without being taught.
Find people to read your code and provide feedback.
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.
Your goal should be to become skilled rather than experienced.
Draw a Personal Practices Map for your working habits. Consciously writing down the things you do and draw the connections between them. Google around and see what others draw on their map, e.g. this.
You remember doing very similar things in the past, but the exact details escape you. Write down your lessons and review the material. Use whatever medium that comes natural to you.
Write blog articles on what you have learnt and share the knowledge.
Create mechanisms for regularly gathering more or less objective external data about your performance. Gather feedback early, often, and effectively. Use the advice to identify blind spots to improve.
Code reviews, certifications, getting feedback from people around you are some ways to get this feedback.
Failure is inevitable. Seek to identify how you tend to fail and try to resolve those that are worth fixing.
Try this coding exercise. Write an implementation of a particular algorithm without IDE. Write all the tests that you will need to verify the algorithm. Take note of the problems you discover at this stage. Go back and fix all the problems. Iterate until you are confident to compile and run the tests. At each stage, study why certain mistakes are made.
Aim to be a knowledge-motivated person rather than a grade-motivated person. You are no longer in school. You don't need external factors to push you to learn. The motivation should come from within. Learn a little today, learn a little tomorrow. Switch to something else. The learner makes his own curriculum.
there is certain information that is mainly found in plain old low-tech books ... the vast amounts of wisdom captured in the books of experienced practitioners like Jerry Weinberg, Fred Brooks, Steve McConnell, and Kent Beck cannot be replaced.
Create a reading list of books to read based on your current context. Build an antilibrary. Preferably keep this list in a public space for sharing and collaboration. (Besides keeping a reading list, I think keeping book notes also helps immensely.)
Have a habit of reading constantly. Make use of little bits of dead time, such as train rides to read. Don't limit the medium. Read books, blogs and research papers to keep up to date with cutting edge ideas.
Recall the Lindy Effect. The classics stood the test of time for a reason.
Learn to dig deep into tools, technologies, and techniques. Know why certain things are designed that way. Understand the contexts that led to this design. It is not simply parroting the things you briefly read on Wikipedia. This understanding will set you away from other candidates who can't describe the software they have helped build. Avoid Programming by Coincidence or Cargo Cult Software Engineering.
Focus on being a cathedral builder. Cathedral builders are those who have built up a practiced understanding of the tools they use. They are the ones who seem to perform magic when solving the most difficult assignments.
To dig deep, aim to get your information from primary sources such as research papers.
Project changes, business domains changes. How do we assure our clients on your ability to deliver? Identify and keep a list of familiar tools. They are part of what sets you apart from other candidates in interviews. Know when to use them and when not to use them. Check this list routinely. Hunt around for tools that fill the gaps in your toolbox and switch out obsolete tools for better ones. In time, all of your favourite tools will become junk.
When we use the word skill, we don’t just mean how much computer science you know or the effectiveness of your development process or how much experience you have. We mean the union of all the things it takes to deliver working software.