When a developer joins a team, they need to become familiar with the codebase. It can seem a daunting task, but it will happen somehow. There are many approaches, with various levels of planning. There's no single right way, and different teams and developers should choose their own path. Here are some examples:
This isn't an exhaustive list. I've sorted it roughly according to how much preparation is required. There's a scale, which I shall pompously call Harriyott's Scale Of Onboarding Preparation, or SOOP. One end is fully prepared, and the other is fully reactive.
It's easy to assume the fully prepared end of the scale is the best end. After all, failing to plan is planning to flail. The new developer will have everything they need to understand the codebase, and be able to safely contribute. For very large teams, a training programme can be an efficient way to introduce a sizable influx of developers to the project. It can also create a good impression with the new developers, that they have joined a well-managed team.
It's not all butter and teapots though. It takes time to create a training programme, or comprehensive documentation. Most of the work will be done by the existing programmers, which means they won't be writing new code. The skills required are different to writing code, so the programmers may struggle to produce high quality materials, or be resistant to spending time on non-coding activities. If there is only one developer joining, it may be a hugely inefficient process.
There's no guarantee that it will be useful either. The new developer may not favour learning from a large set of documents. They might learn better from watching videos of conversations between developers, or by rooting around in the code itself.
The developer may learn about one area of the system, but not work on it for a year or two. It may be stable, and there are no feature requests or bug reports that enter that area. The time writing the materials was wasted, along with the time spent by the new developer reading them.
The more time is spent on this, the longer it is until the developer starts contributing code, which is expensive.
At the other end of the SOOP is very little preparation. The existing developers are fully productive fulfilling the needs of the business, and the status quo is maintained. The new developer is dropped in the deep end and has to sink or swim.
It can be a lonely time joining a new team. Without active support, the new developer may feel bad for interrupting the “important” developers, or not want to look stupid by asking too many questions. They may decide to undertake their own research, which would take considerably more time than had they just asked. Their research may not be accurate or complete. They may not grasp the context of the bug they are fixing, and then introduce regression bugs. This leads to more rework in code reviews, and a drop in confidence.
When they start a new piece of work, they have a new subsystem to learn, or be taught. This won't have been planned for, and will require either self-learning time or support from an existing developer.
Although the existing developers understand the newbie's predicament, they are frustrated by the interruptions, because it affects their concentration, and their deadlines. They may become resentful.
The result might be that newer developers are kept away from the existing developers, and given low priority work. It seems like a way of protecting the existing developers, but it delays the efficacy of the new developer, which is expensive. They may be put on greenfield projects instead. Again, it protects the existing developers, but they may be resentful that they aren't getting the fun jobs.
It's not all teapots and butter though. No time is wasted producing documentation that isn't read, or becomes out of date, or doesn't actually help the new developers. The new developers can start working on the system immediately, and experience the code and quickly see their work in the hands of the users. They'll only know what they need to know at the time. Many developers learn better by doing, and over time they'll have a complete picture of the system through exposure.
The Balance
Generally, without intervention, a team drifts towards the reactive end of the SOOP. Some decisions make themselves. This isn't necessarily a good or bad thing, but the team needs to understand the consequences, and be prepared to deal with them. If the decision is to avoid pair-programming, then the consequence will be intermittent questioning. This should be supported, as it was what the team (maybe inadvertently) decided would happen.
Conversations are needed from the moment the team decides to recruit a new developer. The existing developers should be asked how they want to be involved, and time allocated for them to do a good job. When interviewing candidates, ask them how they like to learn, and how they best get up to speed. If it is completely different to how the existing team works, then maybe they aren't right for the job.
As with many things, the way that developers are happiest working is the way that developers are the most productive. Unhappy developers have a habit of leaving.
Having been a contractor, I've been the new developer many times. I've found that I like to get to the code early on. I appreciate a quick overview of the company as a whole, meeting the stakeholders, and a brief tour of the UI.
I like a nice set of instructions for getting my machine set up so I can run a local version of the code.
My first piece of work is ideally a simple premise that touches all the layers of the system. Adding a text box to an existing form which is saved to the database is ideal. I don't need to understand complex business requirements, and I experience a lot of the codebase in one go. It's easy to follow the path of other text boxes on the form, so I get to see how the layers are set up, where the repositories are, how database scripts are generated and run, how the UI is built, and how the front-end talks to the server.
Once I've done a couple of those, I've pretty much learnt the basics, and can move on to some meatier problems. I'd only have the problem itself to worry about, and I'd be able to see where to put each part of it.
I don't like to read a lot of detailed documentation. My first week at one job was spent entirely on reading. Most of it didn't sink in. It was comprehensive and dry, and I didn't understand how it was relevant to me. It was only once I started coding that I could ask some questions and begin to understand how things worked.
The documentation I would like to see, but never have, would be a video of a previous new starter talking through the codebase with an experienced developer. These conversations are always the most revealing, and contain the good stuff that never makes it to the actual documents. “Oh, Terry added that module for the SpoonFeed client, but the other clients each wanted something different, which is why there are so many method overloads”
I've been the experienced developer too. I don't recall ever being given much time to prepare in advance for new starters. I like sitting with them and chatting through the main areas of the codebase, and giving them tasks to do. I like answering questions, and enjoy being helpful. I like making my new colleagues feel welcome, and it's a good way to feel like part of a team.
I was once made redundant with four months notice. Our office was being closed, and the work outsourced to Bulgaria. It was my job to write handover documentation. It was horrible. I wasn't told what kind of documentation, just what was needed for the new team to pick it up. I didn't know what that was. I'd look at a section of code, and wonder if the comments explained it enough, or whether I had to write about each method in the documentation. I didn't know how much of the business processes I had to explain to put the code into context. I resigned and started contracting. I forwent my redundancy pay.
Brooks' Law: “adding manpower to a late software project makes it later”. From 1975, and still true. It's not reassuring, but useful for planning. Accepting this, and gaining management approval for the delays in advance, makes for a happier process.
The Manifesto for Agile Software Development: “... we have come to value ... working software over comprehensive documentation”. So have I. Also, in their principles:
“The most efficient and effective method of conveying information to and within a development team is face-to-face conversation.”
Chesterton's fence: “Reforms should not be made until the reasoning behind the existing state of affairs is understood”. In this context, don't have a new developer work on a massive feature in a legacy codebase until they know how it works.
There are many ways to introduce developers to a team. Make sure everyone is happy with the plan.
Originally, a 10x developer was simply someone whose self-reported times to complete an assignment were 10x faster than the slowest, as described in Joel Spolsky's blog post. This was a set of solo projects, which were well-defined in scope, and the requirements didn't change.
I remember doing assignments at sixth-form college. There were some people who just didn't get it with the programming. I'd explain it, and they'd kind of understand but it wasn't really for them. I've deliberately made myself sound arrogant there. They were much better at other aspects of the course, and they'd help me with the business analysis module, or the systems specification coursework. I wasn't that interested in designing a network.
The people who “got” programming became programmers. The people who didn't, didn't. Like the programmers, they chose careers they were excited about and were good at.
There's no data to back it up, but I reckon none of the 1x developers from the Yale class became programmers. If so, then a 10x developer is someone who is 10x faster than someone who isn't a developer. Not really a useful comparison. Maybe the fastest were 2x or 3x faster than the students who decided to stick with it.
But, but, but! Joel's article doesn't say that one or two students were always the fastest, just that the fastest _times_ were significantly faster than the slowest. It does not say that Sammy was always the fastest: they might have been fast in two or three, but average in others.
These self-reported times are for static, solo projects. There is no data for agile, group projects. In my 20+ year programming career, I have never seen a static, solo project. Plenty of solo, zero static. Maybe a single agile ticket would count as one, but projects change regularly.
Speed is only one metric. Imagine coder top trumps. There would be other attributes: years of experience, bugs fixed, languages proficient in, salary, etc. If you were actually playing top trumps, it would be exciting to get the fastest on your turn, as that card would win against every other card. Hooray! But if it was your opponent's turn, and they chose helpfulness, you'd lose your best card to an average developer.
If you have a software team, you want team developers; you don't want a solo star.
10x developers don't exist, and if they did, they wouldn't be useful.
Rockstar developers exist. They sound exciting, and impress fans who see their best work on the internet. They don't impress people who have to work with them, and clear up TVs from outside their hotel room windows, get them to meetings, manage their egos, and get them to apologise to the bass player.
Developers now exist in teams. They have to be team players. It is no longer desirable to be a heads-down-talk-to-nobody developer.
I've been chatting to Leon about his upcoming book, Evergreen Skills For Software Developers. These are skills that are useful throughout a career, rather than a particular technology. Being a developer for over 20 years, I have thoughts on how to develop them.
n.b. I'm still working at some of these. I may never make it. I also have a couple of other posts with some other ideas.
Waiting for Angular to build is boring. I'm using ng build --watch
to trigger a build whenever I save a file, but it's hard to know when it's done. I don't like staring at the timestamp waiting for it to change:
I compare the time in the window with the actual time in the bottom corner of my screen, but if I'm making small changes, the minute is the same. If I'm distracted, I may look away briefly and miss when the build has finished and find I'm staring at it waiting for it to change, but it just doesn't.
I'm a big fan of Boggle, with the exception of the timer. When I'm busy writing words or looking at dice, I don't want to be wasting time glancing at the falling sand. Sometimes we all forget to look, and find that we missed the end, and the timer stopped at some unknown point in the past. I'm sure you all know how infuriating this is. Whenever I play, I set a timer on my phone to beep when the three minutes is up. We can all concentrate, and we get to play with less frustration.
Being as smart as you are, I'm sure you've deduced by now that I wanted the Angular build process to beep when it had finished. The initial problem was that the process wasn't finishing, because the --watch flag keeps it running. Had it been a single process, I could have put it in a batch file with an echo ^G
afterwards. (Those who didn't spend their teenage years on an Amstrad PC1512 may not know that Ctrl+G is ASCII 7, i.e. BEL (a beep)). You can type echo Ctrl+g
into a command prompt to make a beep, which is more pleasing than it should be.
However, there's no post-build hook in Angular (that I could find), so I needed something else. Twelve years ago I discovered C#'s FileSystemWatcher
for a project I was working on. It's the only time I've used it, but now was the time to bring it out again. I think of it often, but it sits there in a drawer, waiting for a special occasion, next to my bowtie. A FileSystemWatcher
keeps an eye on a file or directory, and if a file changes, it fires an event. My plan was to get this dude to camp out with his binoculars looking at the Angular output directory and if anything happens, send me an E in morse code.
So in a new console app, I lovingly sculpted a new watcher:
When it fires, it makes just the right kind of beep.
I ran it, saved an Angular file, and it beeped when it finished. Several times, in fact, as several files changed. I wanted just the one, so I used a short timer to catch the changes:
This timer delays the beep for 0.3 seconds, and doesn't let any other file changes trigger a new beep in the interim. As an aside, when you're playing Boggle, and you see the word TIMER, it's Levidrome is REMIT, so you can write that immediately. Obviously there's TIME too, whose Levidrome is EMIT, so you've got four words from one without thinking about it.
So now I'm happily coding in Angular in Visual Studio, pressing Ctrl+Shift+S
, clicking on the browser window containing the app, hovering my finger over the F5
key, and then staring out of the window until I hear the beep, when I tap the F5
key immediately. Problem solved; happy Simon.
I have an Angular 5 app talking to a C# api. Having magic strings for the end-points in both the TypeScript and the C# route attributes seems fragile to me:
I wanted a single source of urls, so the first step was to create a C# class of constants and use them in the controller.
Manually typing an equivalent TypeScript class may make the code a fraction less fragile, but it would still be writing the same code twice. Ideally the Angular app would be able to access the C# constants, but there's no direct way. I've been a big fan of code generation over the years, using NimbleText, CodeSmith, Resharper templates and T4. My plan was to generate a TypeScript class from the C# class. I plumped for T4.
This uses reflection on the class to get a list of the class's constants containing the urls. It loops round them, checking for parameters, e.g. {kittenId}
. If there are any, the template generates a function that accepts the parameters and returns the formatted string. If there are no paramters, then a property is generated instead. The output of this template is included in the Angular app, and is accessible from the rest of the code.
A much less fragile way of linking front- and back-ends through code generation.