From journeyman to master. How not to become an expert beginner programmer.

From journeyman to master. How not to become an expert beginner programmer.

good programmer

Written by Marcin Sztandarski, Technical Architect at PolSource

Graduates of engineering studies.

A couple of days before writing this article I was asked by one of the managers I knew to take part in a survey of a certain university of technology. The survey actually boiled down to the question of what skills engineering graduates taking their first steps in IT were lacking. This gave us the idea to elaborate on the subject and to write down my and my colleagues’ experiences in the form of a short essay.  The essay describes the characteristics of the candidates I had recruited who later proved to be the perfect project collaborators. In many cases the interview was not the last time I met the recruited employees, so I had plenty of opportunities to revise my initial observations. As a rule, you do not become a good programmer by chance; your professionalism is determined by your long-term efforts to achieve specific results. This essay is mainly addressed to beginners or those who feel that they are stuck with a too stable job, such as application maintenance. 

We are looking for beginner programmers

To answer the question about the expected skills of engineering graduates, we could make a list of requirements related to the technological stack used in projects, just like HR departments do when they post a job. In general, verifying a candidate’s knowledge of technology is not a hard task. On the other hand, when hiring a beginner programmer, we cannot expect them to have a profound and practical knowledge of the subject, as they simply had no way to acquire it. However, job postings fail to list the expectations that are often difficult to verbalize. The psychological profile of a candidate (team player, introvert…) is also important, and HR departments sometimes run a cursory check in this respect. Finally, the company’s specific requirements which are rarely disclosed in job postings are also important. They can determine quite a large part of your career. 

Pay attention to where you’re applying and to whom you’re offering your time. 

A good programmer does not waste their time in a negative environment. If a company doesn’t care that its employees need to develop, focusing only on their exploitation, it can derail your career from the very start.  When looking for a job it is worth checking whether your potential employer, aside from having requirements, will support your career development. Perhaps as a beginner you are not too certain of your skills and you don’t feel ready to ask such a question during an interview. However, let me assure you that in the case of a company with a continuous learning culture, questions about development opportunities will not be problematic for recruiters; on the contrary, such discussion will be more than welcome. This may indicate that this is not just a “contracting machine” focusing on body leasing and fast monetization.  Of course, there is nothing wrong with working in such companies for a fair wage as long as you are an experienced programmer and you can find the time and strength to develop in your free time. In any other case, whether you want to develop your career or you are taking your first steps in the industry, you would rather benefit from being part of an organization with a continuous learning culture. This does not necessarily mean attending courses or conferences. One-off training can of course help your career, but cyclical (e.g. weekly) practices related to improving qualifications are more important. They can take the form of weekly meetings where teams share their knowledge about solutions developed under current projects, or mandatory mentoring where you would receive support from a more experienced person. While there are many opportunities, it is crucial to devote a percentage of your time in the company to regular qualification improvement. 

Do developers write code?

If you ask a programmer what they do, their answer would probably be simple, “programming”. More enlightened colleagues may answer, “software engineering”. One could say that coding depends on what and how you think. We will not discuss here the increasingly rare profession of a “coder”, who replaces precise requirements with a code in a given language. Instead, let us focus on examples of practices that make a good programmer perform much better than an average, or worse, a poor programmer. In this essay, I would also like to elaborate on the concept that the profession of a programmer involves much more than just writing code (or possibly copying it from stack overflow), that is “doing projects”. The profession of a programmer has to follow specific rules, and the quality of work and development is possible by adhering to specific values and applying reliable benchmarks. I assume, based on my own experience and observations, that technical skills, knowledge of subsequent frameworks and workaholism are not enough to build a career in the longer term. If you think otherwise, I guarantee you that our industry is full of people who are now “benched” because of a burnout or who, despite ten years in the industry, are stuck having reached the dead end of being the “advanced beginner”.

A good programmer is a craftsman who cultivates their craft. (20th anniversary of publication of the book “The Pragmatic Programmer From Journeyman to Master”.)

As I have already discussed in the first paragraph, there are several dimensions of a programmer’s profile.  Career development (or, conversely, degradation) is influenced by conscious or accidental choices modelling those aspects in the course of one’s professional life. So, is there any fixed model allowing moving from a “university graduate” to an advanced senior developer in the possibly optimal way? By optimal way I mean continuous development without burning out or losing your passion for what you do. Yes, it’s a difficult question. With so many technologies, constantly changing market expectations, and often under the stress of “delivering a delayed project”, each career is a little different. A fixed career model may sound an oxymoron. So is there anything you can rely on? As banal as it may seem, the work of a programmer is a craft that needs to be cultivated, a craft based on certain values. Such an approach can be found e.g. in the book “The Pragmatic Programmer: From Journeyman to Master”. It is undoubtedly an exceptional work, discussing pragmatic attitude in detail. Its second revised edition has been recently published, twenty years after the original publication.  I assure you that the book is still relevant; it was also one of the books that radically changed my view on the profession of a programmer. Once a younger colleague of mine dismissed the book as outdated because it encouraged readers to use the Perl programming language. Nothing could be further from the truth. The book mainly discusses the universal values that a pragmatic programmer can apply under certain circumstances. This is not a cookbook that would give you a recipe for how to write using a specific technology. For example, it mentions the Eiffel language and the concept of Design-by-Contract, which may sound exotic to beginners. Understanding the meaning of this technique can change the way you code. I’m not going to summarize the book here. Just read it. Regardless of your level of advancement, “The Pragmatic Programmer: From Journeyman to Master” is a must-read, especially if you have not read it yet. And if, like me, you read it ten years ago, read it again. 

On the first steps to become a good programmer.

Can you make someone be good? I have yet to see a case like this. Being good comes from wanting to be better than you are now. This results in the willingness to learn and cultivate your craft, or even veneration for continuous learning and improvement of your skills. I know from experience that a good database administrator will sooner become a good programmer than a poor programmer with many years of experience who decides to “let go”.  Of course, seniority is important. Have you ever heard of the 10,000-Hour Rule myth popularized by Malcolm Gladwell in his book “Outliers: The Story of Success“? According to this myth, after a few years of programming you should become an expert. Unfortunately, in the case of developers, this model is getting much more complicated. Very often I meet people who claim to be senior developers due to their “seniority”. However, the interview usually reveals that it is not the case. Getting to the next level does not only depend on how many hours you spend using IntelliJ or Visual Studio. Things get even more complicated because some of the knowledge you acquire quite quickly becomes irrelevant. It’s not enough to just write the code.  During one interview, I asked a candidate, “What makes you a senior developer? How does your approach to programming differ from that of an average developer, for example?” The answer I got was ridiculous, but also honest, “Because that’s the position I got in the previous company”. I would like to emphasize, we will not be using the criterion of seniority or classification in the payroll scheme here. After many recruitment processes I know that it doesn’t work. If you consider yourself a senior developer, that means that you can solve both typical and atypical problems on your own, you see your code as a part of the whole, e.g. you can anticipate the results of certain design decisions. Adhering to high ethical standards is also important. This may mean you’re a member of the elite, e.g. 10% of programmers.

The role of retrospective

The time and project experience will be working in your favor as long as you run retrospectives and learn from your mistakes. How? Read Matthew Syed’s great book, “Black Box Thinking: The Surprising Truth About Success“. Although it is not a book about programming, it is a fascinating journey discussing rehabilitation of aviation industry, improving the effectiveness of medical practices, and even optimizing the performance of nozzles used for washing powder production. Contrary to what you can deduce from that description, such techniques prove to be very useful in programming. Actually, we can say that the black box is a closed-loop system for “fixing the world”, including programming. If you want to make the most of your many years of work, create your own “black box”. I can think of an example of a technique, a pre-mortem, which is completely “non-IT”. It is used both in management and healthcare. I implemented pre-mortem with my team for the purposes of one of the risky projects. The practice consists in re-modelling your thinking in such a way so as to assume that your code does not work or the release has led to a crash in your production system. You make a hypothesis, “It won’t work”, and you speculate on the causes. The aim is to compensate for certain cognitive errors during the analysis of the implemented solution. The technique is very simple and it has saved us a couple of times, or at least it has spared us a sleepless night after a failed implementation.

The next steps on becoming better according to the Dreyfus brothers.

At first I considered beginning this section with the profiles of programmers at the most common levels in corporations, i.e. junior, regular and senior developer. However, this scale seems to be insufficient. A well-known model used e.g. by the authors of the book “Pragmatic Thinking and Learning” is the classification known from the Dreyfus brothers’ research on skills acquisition by Air Force pilots. We will not carry out similar research nor discuss in detail each of the stages of skills development, as this would fall well beyond the scope of this article. Let’s focus on the beginner stages. The research carried out by the above mentioned authors revealed certain interesting facts about skills development: it is not only the matter of the amount of knowledge you acquire; the developments that take place during the “leap” to the next level are radical changes in thinking that make you see the domain of problems in a different light than at other levels of initiation. In other words, you see the world on different levels. If you want to learn more about the subject, I recommend reading “Pragmatic Thinking and Learning. Refactor Your Wetware” by A. Hunt. 

Novice – dealing with negative emotions 

Regardless of the motivation that drives you to become a programmer, by default this is the level where you start your career. You can’t program yet (or you’re doing it wrong). You get to know the platform, get an internship or land your first job as a junior developer.  At work you get “something to do”, e.g. a user story with one sentence of description and… you feel that your end is coming. You don’t understand business terminology, even if the case description is detailed, you have no idea how to approach the implementation. You need a structure or reliable guidelines from a senior colleague or architect. On the one hand, this stage is frustrating; on the other hand, it is exciting because of the abundance of innovations offered by technology. However, more often than not you will experience frustration. There will always be problems that would pose a challenge. As a novice, develop a passion for problem solving and learn how to deal with uncertainty. This will be the case for the rest of your career in IT, regardless of your level. Another frequent problem among some developers is perfectionism. It consists in creating endless abstractions, frameworks, libraries for trivial problems. I sometimes meet frustrated developers who have not managed to write “the perfect code” right away. The code evolves in the course of several iterations. Perhaps the experiment described in the book “Art & Fear” will explain it better. During the ceramics class, the teacher divided the students into two groups: the first group was to make as many pots as possible, while the second group was to make the most perfect pots. The first group was graded based on quantity, while the second group was graded based on quality. Although it seems unintuitive, pots of the best quality were ultimately produced by the first group. How is that possible? It turned out that, by producing large quantities of pots, the first group experimented with the material, thus gradually gaining knowledge and skills. The second group was paralyzed by the burden of the task. There can only be one conclusion: try, ruin, experiment. New ideas will emerge while you work once you approach the problem. If you don’t know where to start, write the worst code you can, try the most naive solution. You may have heard of Test Driven Development. This technique can help you to make your code evolve. One more thing. If you feel you are stuck, perhaps you should try pair programming. This technique is not exactly new; it was used in the era of Extreme Programming. As it turns out (there are studies on the subject), there is a visible synergy effect even when two beginners work on the code simultaneously. More on the subject can be found in the brief study “The Costs and Benefits of Pair Programming” by A. Cockburn, L. Williams.

Find a mentor as soon as possible

I hope you find yourself on a team where the senior developer will give you a code review.  The more mistakes you make at the beginning of your career, the better… provided you learn from them.  You need feedback. Personally, I am a fan of mentoring, which works perfectly in the company I work for. If your supervisor does not assign you a mentor (which is most often the case), find one yourself and learn to communicate with them properly (e.g. do not interrupt their work when they need to focus). Sometimes one expert advice (e.g. don’t do it synchronously because…) will save you many hours of pointless work. Of course, if you notice that no one is critical of your code (and not only code), find another job as soon as possible. Either you won’t learn anything there, or it would take you much longer. The teacher (or mentor) – student relationship functions in many disciplines of life and for a good reason, too. It is a pragmatic practice that just works. Learn to listen, because your mentor could be the whole team. Even if at first you don’t understand what they are talking about, in the future, once you fill in the gaps in your knowledge, those open space conversations will make sense and bring you many benefits. 

Don’t ignore the foundations

Being a beginner is the perfect moment to learn the foundations of programming. Understand the paradigms, methodologies, algorithms and data structures. Find out what happens “inside” a compiler or interpreter, how the database works, how to estimate the complexity of algorithms and e.g. what the consequences of the presence of a garbage collector in a specific JavaScript implementation can be. Even a brief knowledge of those topics will bring you many benefits in the near future, in particular when you come across a difficult problem e.g. related to platform performance.  You don’t have to read the thick books written by the “classics”. You can simply watch a ten-minute YouTube video outlining the topic. The technique of learning “step-by-step” is explained in the book “The Slight Edge“. The author emphasizes the role of doing even small things for a long time, which in consequence leads to a greater change, which as a beginner you may not even notice. When I interview candidates with “advanced JavaScript” in their resume, I often ask them, “What is hoisting?” Unbelievable as it may seem, most of them don’t know. How can you anticipate the consequences of your code without such basic knowledge?

Patchwork knowledge from tutorials and Stack Overflow

Another recruitment story: when asked about the last book about programming they had read, one of the candidates replied, “But everything is online, reading is a waste of time.” As for the first part of the answer, I agree. However, books on programming have a certain advantage: they are usually a coherent and structured lecture, the quality of which can be verified e.g. based on amazon.com reviews.  The problem with blogs is that as a beginner you are unable to judge whether the proposed solution is good (even though it works, it doesn’t have to be good). Of course, many experts have their own blogs (e.g. Martin Fowler’s blog), but I would recommend taking the information from random blogs with a grain of salt. A list of interesting books to start with has been presented below. Although the selection is subjective, it was consulted with some exceptional programmers. It may take you more than two or three years to read everything on the list, but this is an investment that will certainly generate abundant returns. You will keep coming back to some of these books for many years. According to my observations, people who read e.g. “Clean Code” or “Code Complete” create solutions of much better quality than developers who e.g. have no idea what S.O.L.I.D. principles are:

  1. The Pragmatic Programmer: From Journeyman to Master”, Andrew Hunt, David Thomas
  2. Pragmatic Thinking and Learning. Refactor Your Wetware”, Andy Hunt
  3. Apprenticeship Patterns. Guidance for the Aspiring Software Craftsman”, Dave Hoover, Adewale Oshineye
  4. “Clean Code: A Handbook of Agile Software Craftsmanship”, Robert C. Martin
  5. ”The Software Craftsman: Professionalism, Pragmatism, Pride”, Sandro Mancuso
  6. “Code Complete. A Practical Handbook of Software Construction”, 2nd edition, Steve McConnell
  7. “The Mythical Man-Month: Essays on Software Engineering”, 2nd edition, Frederick P. Brooks Jr.
  8. Programming Pearls”, 2nd edition, Jon Bentley
  9. The achievement habit. Stop wishing, start doing and take command of your life”, Bernard Roth

Search for patterns

That’s right: most of the problems you’ll encounter have already been solved by someone. Many of them have found their way into various types of pattern repositories: design patterns, implementation patterns, architectural patterns; there is also the concept of language idioms e.g. in Java. I often hear, “I’m using patterns, but I am unable to name them.” Nothing could be further from the truth. When using a pattern, it is important to keep the appropriate convention, as this allows you to communicate your intentions to other team members. If you refer to the Singleton class as the “Locker”, you probably won’t communicate to them your intention to maintain a single instance of an object. Don’t start with the Gang of Four classic, i.e. “Design Patterns: Elements of Reusable Object-Oriented Software”, this is not a good book for beginners. Instead, read e.g. “Head First Design Patterns“, or “Implementation Patterns” by Kent Beck.  If you want to learn a new programming language, make sure to start with the most common idioms. Lack of basic knowledge in this area often leads to a situation where a nightmarish JavaScript code is written by a C# programmer. However, patterns involve a certain trap. If you put them into every piece of code, or try to use patterns whatever the cost before you closely analyze the problem, you risk skipping a critical stage of discovering the essence of the problem. Don’t start writing the code by asking yourself the question, “What would be the pattern be here…?” Instead, focus on the business problem, apply the right abstraction layer. Perhaps you don’t know the pattern that would fit the solution. In such a case, “forcing” one of the patterns you know could be more or less illustrated by Abraham Maslow’s quote, “I suppose it is tempting, if the only tool you have is a hammer, to treat everything as if it were a nail…” In other words, the design patterns you know do not necessarily apply to the area of the problem you are solving. 

Finally, an anti-pattern: expert beginner and the illusory superiority

One of the cardinal sins that hamper the development of programmers is the phenomenon called the Dunning-Kruger effect. It is a nasty cognitive bias that can make you get stuck at the level only slightly higher than the starting point. Using the Dreyfus brothers’ model, you start as a novice and in a fairly short time you become an advanced beginner. In the process of learning, you may pick “low-hanging fruit”, which can give you a sense of agency and knowledge. In the meantime your pride may rise thanks to the few certificates you have obtained in three months. The Dreyfus brothers describe the next stage, “competent”, as the level where you move from a “rule-driven” work as a beginner to a more holistic concept. I will not discuss this stage in detail here, as many developers, despite their formal senior developer title, end up stuck between those stages for years. How to recognize such a person? I use a certain trick during recruitment. I ask the candidate, “What makes you different from your less experienced colleagues as a senior?” A senior developer can be easily recognized by the fact that at some point they will openly talk about what they can’t yet do. Being aware of your limitations and of what you don’t know is a signal that I am talking to someone who is at least competent. Going back to the person who “got stuck” in terms of development, in his blog, Erik Dietrich uses the term “expert beginner”. New certificates and careful selection of projects that do not pose too many challenges but where the rates is quite high (the market allows it nowadays) fail to confront the skills of such person with their actual seniors or experts. Pride and lack of feedback, as well as unwillingness to step out of your comfort zone, guarantee that you will stay where you are. If you secretly feel that you are such a person, well, one solution is to become the worst musician in the band, i.e. to join a team where you will be confronted with people better than you. If you’re not yet ready for such a radical leap, try to assess what is the reason for your reluctance. Perhaps as a backend developer you feel disgusted when thinking about front end programming or refactoring a nasty code. It may be a good opportunity to confront yourself. 

In any case, make sure to read “The Pragmatic Programmer“.

Want to become a good programmer at PolSource? Check out our career opportunities at the Poland Center of Excellence!