There are few developers who give themselves the luxury of never programming outside of work time. Indeed most developers, even if trained in some part academically, will have learned most of what they know working in their spare time, whether early on as a student or whilst working in another profession. The ability to code, and to produce good products, rarely comes without significant amounts of our own time invested. Neither is this time usually given grudgingly - as we develop our skills we increase our power to create, to use our imaginations to invent “products out of sheer thought stuff” as one famous software engineer put it. For those looking to hire employees into any software development team, whether for a large or small company, people who spend at least some time working on code which they are not obligated to work on are often preferred - those people may be ahead of the curve on new technologies, have better subconscious knowledge of their favourite languages and more easily recognise good from bad practice. As developers, working on our own projects is unquestionably a good thing.
Another way that developers can end up working alone is in the bold new world of freelance - coders without an office, a boss, a pension or even, sometimes, a pair of shoes. Whilst many freelancers end up being brought in to support an existing team, or even as pseudo-consultants, tasked with more responsibility than just raw programming, others will find themselves working on totally new projects. These may be existing companies trying out a new idea, or we may encounter founders of a startup business who are unlucky enough to have a great idea and no way to build it themselves. These projects straddle the line with much of the creative freedom of our own projects but also additional financial reward, and possibly more in the way of penalties for doing “cowboy” work, writing bad code that someone else will have to pick up in future.
For some of us our personal projects may become more than just a way to hone our skills, try something new or produce a product for personal consumption - they may become businesses in their own right. For the freelancer striking out with new ideas for an existing company or helping develop a Minimum Viable Product (MVP) for a startup, the business case might actually work and your experiment is used by internal staff or external customers of the business. At these points you might be set for an interesting trajectory, as requirements and pressures necessitate more hands on deck to keep building this product - the challenge of going from one to many.
I remember the train journey to a team meeting in London the first day we had our first employee working for us. Sitting on the train I went over our code and said to myself - “oh crap, they’re going to HATE working with this”. Without very good self control and likely the experience of writing unmaintainable code at least once, it’s hard to produce work on your own which someone else doesn’t have the immediate instinct to rewrite. As I poured over our application in all it’s legacy-code-glory I said something that may seem odd in the world of microservices, continuous integration, endless new frameworks: “this code is OK, because it works”. The first step to bringing in new people shouldn’t be arrogance - “that’s how we do it here”, but nor should it be self-deprecation. Our business was built on that code. We had traction, customers, users and had convinced investors to place their bets on us. Yes bad code will make your future job harder - but a senior developer or CTO needs to show confidence to new hires, and show them a clear path to how the codebase will improve.
Once your first hire(s) come through the door, how do you introduce them? You have 100,000 lines of code and most of it is compartmentalised inside your head. After a rather awkward “deep dive” attempt to go over the whole structure of the code (which got sidetracked into operations of the most minor and unimportant functions) we tried an alternative “deep end” approach - give the new person a simple task that can be easily explained on the live site, and tell them to get on with it. Doing this required some more common sense from our new employee, but now looking back this approach has led not only to a better understanding of how code is written, but also of better understanding of the experience we want our users to have, and a greater sense of ownership of individual features.
Letting people mess with your code can be hard. They do things you don’t expect - sometimes clever things that make you jealous, other times frustrating things that “I’d have done differently”. Learning what to allow into your codebase and what to push back on is hard, but the experience is helpful to teach you the boundaries of your own knowledge, and to show how you’ve been influenced in your own learning:
- You might like using
foreachloops with references or you might not - but if the code is properly encapsulated, tested and type hinted is it a problem worth challenging your employees on? Probably not.
- A new feature needs delivering tomorrow but no tests are written - should it be pushed back or should you write a quick integration test that covers the primary use case? That’s a business decision only you can make.
extract()inside a controller? (sorry non-PHP folks) OK, that’s probably the time to put your foot down, but make sure you explain why - your developers can have different experience and different former patterns they’re used to working in, so make clear what’s wrong, what’s personal preference and what you’ll agree to disagree on.
One way to ensure that all of the above comes together, and something I’m glad we tried from the start (probably one of the first things I’ve got right without needing to be told I was wrong first) is proper code reviews. No code goes into
master without being checked, line by line, in the original pull request. With GitHub, BitBucket and various other studly-caps-named products available, doing code reviews has never been easier.
Only last week a team told me they’d switched from doing “code reviews” to “proper code reviews” - leading me to wonder what the former has to differentiate it! When you’re developing your own project you can hold the entire structure in your head and probably jump near enough to a line if you need to. As your team grows this gets harder, but with insight over the code structure you can maintain a surprising amount of this ability, which can differentiate a former solo developer from other companies whose highest level of technical management has never worked alone on their codebase - going from one to many isn’t just a challenge, but can actually be an advantage.
You’re now at a point where you have new staff using your code, not hating working with it, bringing their own style into it’s progression and being carefully managed to give you the best visibility of how the project changes. Our problems at the start haven’t gone away yet - you’re not ashamed of it but you know that better structured and better tested code is going to serve your business well, and keep you out of the line of fire (or the news) if things should go wrong. We’ve used the hiring of development staff to re-architect our back end without throwing away our logic; to migrate our database access to allow for better testing & security, and to introduce a whole batch of unit, implementation, acceptance and API level tests.
We’ve had a few things to help us on this pathway, some of which have surprised me.
- Firstly, and controversially, procedural code, written well, is really easy to read. It’s hard to maintain, keep DRY and test, but having your entire app flow readable is an advantage - if you don’t believe me, go into the Wordpress source and tell me how a single article is output. As we migrated into an OO framework we had a policy to keep things readable, which allowed the team to use the same mindset writing new code as they’d use to maintain old code, and avoid both mistakes and extra cognitive load from switching often. We’ve also used existing feedback paths to write tests, rather than set out on a 1,000 mile hike to get 100% code coverage.
- We already had a bug board, and so as bugs have appeared the first goal of any developer working on a solution (or if the dev is the one reporting the bug) is to write a failing test. This has sometimes led to problems with management, as a bug is marked fixed which then appears elsewhere from a different cause (i.e. a different test case) but it has kept our tests lean and our fixes quick to deploy live, something of greater advantage than investing all our resources to build a bug free system at a time when we still have markets and sales to capture with new developments.
- Finally we’ve (accidentally) hired a team from very different backgrounds. The team has given us a rare mix of high level oversight, insight into obscure edge cases and fast iteration of new features - all of which has been a challenge to manage but a recipe for producing well-written innovative products quickly.
The pathway from working on a project for years as a lone wolf to leading a team of developers has not been easy. It has stretched my abilities as a developer and taught me without doubt that management is indeed a skill - a valuable and hard-to-learn one. There’s no silver bullet in growing a team but there’s no developer who wouldn’t be better off for the experience, even if you eventually decide to return to being “just a coder”.
Push boundaries, but be proud of what you’ve written on your own. Let people do things their way & influence the direction, but keep control & direct responsibly. Improve your process, your stack, and your architecture, but don’t throw out valuable learning.
Enjoy the journey from one to many.