Standards & Gatekeepers & Fitted Bathrooms

One thing I’ve learned from 10 years on Twitter is that whenever you dare to suggest that the software development profession should have minimum basic standards of competence, people will descend on you from a great height accusing you of being “elitist” and a “gatekeeper”.

Evil Jason wants to keep people out of software development. BAD JASON!

Well, okay: sure. I admit it. I want to keep people out of software development. Specifically, I want to keep people who can’t do the job out of software development. Mwuhahahahahaha etc.

That’s a very different proposition from suggesting that I want to stop people from becoming good, competent software developers, though. If you know me, then you know I’ve long advocated proper, long-term, in-depth paid software developer apprenticeships. I’ve advocated proper on-the-job training and mentoring. (Heck, it’s my entire business these days.) I’ve advocated schools and colleges and code clubs encouraging enthusiasts to build basic software development skills – because fundamentals are the building blocks of fun (or something pithy like that.)

I advocate every entry avenue into this profession except one – turning up claiming to be a software developer, without the basic competencies, and expecting to get paid a high salary for messing up someone’s IT.

If you can’t do the basic job yet, then you’re a trainee – an apprentice, if you prefer – software developer. And yes, that is gatekeeping. The gates to training should be wide open to anyone with aptitude. Money, social background, ethnicity, gender, sexual orientation, age or disabilities should be no barrier.

But…

I don’t believe the gates should be wide open to practicing as a software developer – unsupervised by experienced and competent mentors – on real software and systems with real end users and real consequences for the kinds of salaries we can earn – just for anyone who fancies that job title. I think we should have to earn it. I think I should have had to earn it when I started out. Crikey, the damage I probably did before I accidentally fell into a nest of experienced software engineers who fixed me…

Here’s the thing; when I was 23, I didn’t know that I wasn’t a competent software developer. I thought I was aces. Even though I’d never used version control, never written a unit test, never refactored code – not once – and thought that a 300-line function with nested IFs running 10 deep was super spiffy and jolly clever. I needed people to show me. I was lucky to find them, though I certainly didn’t seek them out.

And who the heck am I to say our profession should have gates, anyway? Nobody. I have no power over hiring anywhere. And, for sure, when I’ve been involved in the hiring process, bosses have ignored my advice many times. And many times, they’ve paid the price for letting someone who lacked basic dev skills loose on their production code. And a few times they’ve even admitted it afterwards.

But I’ve rarely said “Don’t hire that person”. Usually, I say “Train that person”. Most employers choose not to, of course. They want them ready-made and fully-formed. And, ideally, cheap. Someone else can train them. Hell, they can train themselves. And many of us do.

In that landscape, insisting on basic standards is difficult – because where do would-be professional developers go to get real-world experience, high-quality training and long-term mentoring? Would-be plumbers and would-be veterinarians and would-be hairdressers have well-defined routes from aspiration to profession. We’re still very much at the “If You Say You’re A Software Developer Then You’re A Software Developer” stage.

So that’s where we are right now. We can stay at that level, and things will never improve. Or we can do something about it. I maintain that long-term paid apprenticeships – leading to recognised qualifications – are the way to go. I maintain that on-the-job training and mentoring are essential. You can’t learn this job from books. You’ve got to see it and do it for real, and you need people around you who’ve done lots of it to guide you and set an example.

I maintain that apprenticeships and training and mentoring should be the norm for people entering the profession – be it straight of high school or after a degree or after decades of experience working in other industries or after raising children. This route should be open to all. But there should be a bar they need to jump at the end before being allowed to work unsupervised on production code. I wish I’d had that from the start. I should have had that.

And, yes, how unfair it is for someone who blundered into software development largely self-taught to look back and say “Young folk today must qualify first!” But there must have been a generation of self-taught physicians who one day declared “Okay, from now on, doctors have to qualify.” If not my generation, or your generation, then whose generation? We can’t keep kicking this can down the road forever.

As software “eats the world”, more and more people are going to enter the profession. More and more of our daily lives will be run by software, and the consequences of system failures and high costs of changing code will hurt society more and more. This problem isn’t going away.

I hope to Bod that the people coming to fit my bathroom next week don’t just say they’re builders and plumbers and electricians. I hope to Bod they did proper apprenticeships and had plenty of good training and mentoring. I hope to Bod that their professions have basic standards of competence.

And I hope to Bod that those standards are enforced by… gatekeepers.

Overcoming Solution Bias

Just a short post this morning about a phenomenon I’ve seen many times in software development – which, for want of a better name, I’m calling solution bias.

It’s the tendency of developers, once they’ve settled on a solution to a problem, to refuse to let go of it – regardless of what facts may come to light that suggest it’s the wrong solution.

I’ve even watched teams argue with their customer to try to get them to change their requirements to fit a solution design the team have come up with. It seems once we have a solution in our heads (or in a Git repository) we can become so invested in it that – to borrow a metaphor – everything looks like a nail.

The damage this can do is obvious. Remember your backlog? That’s a solution design. And once a backlog’s been established, it has a kind of inertia that makes it unlikely to change much. We may fiddle at the edges, but once the blueprints have been drawn up, they don’t change significantly. It’s vanishingly rare to see teams throw their designs away and start afresh, even when it’s screamingly obvious that what they’re building isn’t going to work.

I think this is just human nature: when the facts don’t fit the theory, our inclination is to change the facts and not the theory. That’s why we have the scientific method: because humans are deeply flawed in this kind of way.

In software development, it’s important – if we want to avoid solution bias – to first accept that it exists, and that our approach must actively take steps to counteract it.

Here’s what I’ve seen work:

  • Testable Goals – sounds obvious, but it still amazes me how many teams have no goals they’re working towards other than “deliver on the plan”. A much more objective picture of whether the plan actually works can help enormously, especially when it’s put front-and-centre in all the team’s activities. Try something. Test it against the goal. See if it really works. Adapt if it doesn’t.
  • Multiple Designs – teams get especially invested in a solution design when it’s the only one they’ve got. Early development of candidate solutions should explore multiple design avenues, tested against the customer’s goals, and selected for extinction if they don’t measure up. Evolutionary design requires sufficiently diverse populations of possible solutions.
  • Small, Frequent Releases – a team that’s invested a year in a solution is going to resist that solution being rejected with far more energy than a team who invested a week in it. If we accept that an evolutionary design process is going to have failed experiments, we should seek to keep those experiments short and cheap.
  • Discourage Over-Specialisation – solution architectures can define professional territory. If the best solution is a browser-based application, that can be good news for JavaScript folks, but bad news for C++ developers. I often see teams try to steer the solution in a direction that favours their skill sets over others. This is understandable, of course. But when the solution to sorting a list of surnames is to write them into a database and use SQL because that’s what the developers know how to do, it can lead to some pretty inappropriate architectures. Much better, I’ve found, to invest in bringing teams up to speed on whatever technology will work best. If it needs to be done in JavaScript, give the Java folks a couple of weeks to learn enough JavaScript to make them productive. Don’t put developers in a position where the choice of solution architecture threatens their job.
  • Provide Safety – I can’t help feeling that a good deal of solution bias is the result of fear. Fear of failure.  Fear of blame. Fear of being sidelined. Fear of losing your job. If we accept that the design process is going to involve failed experiments, and engineer the process so that teams fail fast and fail cheaply – with no personal or professional ramifications when they do – then we can get on with the business of trying shit and seeing if it works. I’ve long felt that confidence isn’t being sure you’ll succeed, it’s not being afraid to fail. Reassure teams that failure is part of the process. We expect it. We know that – especially early on in the process of exploring the solution space – candidate solutions will get rejected. Importantly: the solutions get rejected, not the people who designed them.

As we learn from each experiment, we’ll hopefully converge on the likeliest candidate solution, and the whole team will be drawn in to building on that, picking up whatever technical skills are required as they do. At the end, we may not also deliver a good working solution, but a stronger team of people who have grown through this process.

 

Old Dogs, Old Tricks

Given what I do for a living, I tend to get pretty much daily practice at the fundamentals of code craft like TDD and refactoring. And, after 27 years of professional programming, I would probably still make time every day or once a week to mindfully practice this stuff.

Why? Because – from experience – I believe that these aren’t skills you learn once and then retain indefinitely. On occasions when I’ve been away from code for an extended period, coming back to it I found myself doing sloppy work. I’d forget to do things. I’d fallen out of certain habits.

And I also don’t believe these are binary skills. There’s unit testing, and then there’s unit testing. Not all unit tests are created equal. Some are easier to understand than others. Some are less coupled to the implementation than others. Some run faster than others. Some cover more examples with less code than others. Some teams say “We do unit testing” and their code is still riddled with bugs. Some say “We do unit testing” and their code hasn’t had a bug reported since it went live.

No matter how good we think we are at writing tests or making design decisions or refactoring our code and so on, there’s almost always room for improvement. And as we gain experience in these skills, improving takes more and more work.

As a guitar player of some 30 years, I know that the hour or two of practice I get maybe twice a week these days barely keeps me at the level of technical ability I reached 20 years ago. Most of the visible progress I made happened in the first 5 years of playing. But there’s no top to that hill. If I stop practicing for a while – which I have for the last year or so for various reasons – the ball rolls back down. It takes some ongoing effort just to keep it where it is.

It feels the same with code craft: so many managers who came from programming backgrounds tell me that they lost their skills after a few years away from the code. Indeed, many put themselves on my courses just to try and keep their hand in. Use it or lose it.

An hour or two of mindful practice keeps me where I am as a programmer. It takes an hour or two more to move the ball uphill a bit. This is why I’m such a strong advocate of 20% time for developers. At the very least, half a day a week needs to be set aside to learn, to practice, and to try new things. Or an hour a day. Or however you want to slice it.

Putting aside no time – and I’ve seen this so many times – doesn’t just lead to dev teams who don’t improve, it leads to dev teams who progressively get worse. The code craft muscles atrophy, habits get lost, teams get sloppy, code gets crappy, and delivery slows down to a crawl.

If you prefer a mechanical analogy, think of development as a steamboat. Your goal is to deliver goods from London to New York, sailing every two weeks back and forth across the Atlantic. How much time do you set aside to maintain the engine? None? That’s just not sustainable. How many trips could you expect to make before the engine failed?

The developers on your team are the delivery engine of your software and systems. Their skills – not just technical – need regular maintenance, or the engine breaks down. Set aside some time and put aside some budget to help keep the team in good delivery shape. Not just the occasional training day once or twice a year; a regular investment in building and maintaining their skills. Once a week, or an hour a day – whatever works in your organisation.

(You may be thinking “Hey, we pay them to work. They can learn in their own time.” And that might explain why your efforts to increase diversity on your teams haven’t worked.)

My closing message here is that it’s not just junior programmers who need to work on the fundamentals. We all do.

Here’s a tip from an old dog: a great way to reinforce knowledge and skill is to teach them. My advice for managers is to combine regular practice with mentoring. Your more experienced developers mentoring new hires will find – as I have – that the mentoring process forces us to really think about not just what we’re doing, but why we’re doing it. And it encourages us to be perhaps that little bit more exacting about how we do do it, because we’re trying to set a good example. It’s us as programmers, but in our Sunday best.

Just 3 1-day Client Site Workshops Left

A quick plug for the remaining 1-day client site workshops I’m running to celebrate 10 years of Codemanship.

These code craft training workshops are for groups of up to 20 developers, and can be delivered anywhere in the UK for the never-to-be-repeated price of £1,995. That’s as little as £99.75 per person.

Dates remaining are Thurs Aug 15th, Tues Aug 27th and Thurs Aug 29th. You can choose from an action-packed TDD workshop, refactoring workshop or unit testing workshop. All hands-on and jammed full of practical and useful ideas.

Booking’s easy: whip out that company credit card and visit our Eventbrite page.

Code Craft is More Throws Of The Dice

On the occasions founders ask me about the business case for code craft practices like unit testing, Continuous Integration and refactoring, we get to a crunch moment: will this guarantee success for my business?

Honestly? No. Nobody can guarantee that.

Unit testing can’t guarantee that. Test-Driven Development can’t guarantee that. Refactoring can’t guarantee it. Automated builds can’t guarantee it. Microservices can’t. The Cloud can’t. Event sourcing can’t. NoSQL can’t. Lean can’t. Scrum can’t. Kanban can’t. Agile can’t. Nothing can.

And that is the whole point of code craft. In the crap game of technology, every release of our product or system is almost certainly not a winning throw of the dice. You’re going to need to throw again. And again. And again. And again.

What code craft offers is more throws of the dice. It’s a very simple value proposition. Releasing working software sooner, more often and for longer improves your chances of hitting the jackpot. More so than any other discipline in software development.

The Mentoring Paradox

I recently ran a pair of Twitter polls asking experienced developers if mentoring was an official part of their duties, and asking inexperienced developers if they received regular dedicated mentoring.

It’s a tale in two parts: 3/4 experienced devs said mentoring was part of their job, 8/9 inexperienced devs said they don’t get regular dedicated mentoring.

At first glance, this might appear to be a paradox. But I think it can be explained with two extra pieces of information:

  • Our profession is a pyramid, with the most experienced developers greatly outnumbered by less experienced developers
  • Opinions differ widely on what we mean by “mentoring”

Some developers equate mentoring with practices like pair programming. If an experienced developer pairs with a less experienced developer, they might class that as “mentoring”. What we’ve found at Codemanship, though, is that pairing != mentoring necessarily. It’s unstructured, lacks clear goals for what the mentee needs or wants to learn, and is often done in a naive way by people who may well be technically strong but who lack mentoring skills and experience. And we also need to remember that pair programming’s still pretty rare. Most employers don’t allow it.

A lot of new developers report that pair programming with experienced developers can be a frustrating and demoralising experience. Being a great violinist doesn’t necessarily make you a good violin teacher. In a lot of cases, whatever the mentor thinks they’re doing, the mentee doesn’t see it as mentoring.

The other problem with this kind of ad hoc it’s-kind-of-mentoring-but-not-in-a-structured-way mentoring is that it promotes mostly reactive learning. Mentees learn stuff that just happens to come up. To give a developer a solid and well-rounded foundation in dev fundamentals, there needs to be a game plan, and thought needs to be put into creating the necessary learning opportunities within a reasonable timeframe. This necessitates a balance with proactive learning. Even some of the most advanced employers I speak to admit they have no such plan, and little time and resources dedicated to creating the necessary learning opportunities.

To give you an example, let’s imagine we agree it’s time a new hire learns how to refactor Feature Envy. In a reactive environment, we wait until Feature Envy crops up. In coaching developers, I’ve learned that it can be a long wait. And when it does crop up, we may be too busy or distracted dealing with the 1,001 other things we need to think about to take advantage of the opportunity. You need to be super-super on the ball. It’s far easier to enccourage the team to “bottle” code smells* before they eliminate them, so a learning opportunity like this comes ready-made and easy to locate.

*Check in the code with a commit message that identifies the location of the code smell

We found that devs learn refactoring skills much faster when the opportunities to practice come ready-made like this. (There’s also the side effect when a team does a lot of refactoring that certain code smells get eliminated completely from the code base. Like diseases we wiped out, there is value in keeping some samples in the freezer to experiment on.)

Bottling code smells takes extra thought and effort. Practicing refactoring on code smells that have already been eliminated adds no value to the current code base. Proactive learning comes at a cost that most employers are unwilling to pay. So, instead, they pay in an increased cost of changing code, with the knock-on effect that has on their business. (And I’ve seen a high cost of changing code kill some pretty big businesses.)

Effective long-term mentoring of junior developers costs time and money. There’s no way around that – no magic fix, no silver bullet. You’ll need to give junior developers time out for proactive learning. You’ll need to sacrifice the “productive” time of senior developers to provide good mentoring – which includes time to plan and prepare to mentor. (I spend a good deal of my time learning stuff so I can stay one step ahead of devs I’m mentoring – learning the shiny new languages, tools and techniques – filling the gaps in my knowledge before I try to fill the gaps in theirs.)

Nowhere is this more evident than in the UK government’s Software Developer Apprenticeship programme. While there are some shining beacons who do a superb job with apprentices, I hear from many employers who grossly underestimated the investment they’d have to make – especially in dedicated structured mentoring. There are too many places where apprentices are left to figure it out for themselves.

I would argue that possibly the most productive way experienced developers could use their time is in helping less experienced developers build their skills. At my level of experience, I choose to be almost completely dedicated to it. Devs with more than two decades of professional experience are outnumbered 13 to 1, and I’m not a 13x developer.

The way I see it, if companies are happy to promote their most experienced developers into non-technical management roles – losing most of the benefit of that experience – they might as well promote them into hands-on mentoring roles instead. Either way, less experienced developers will be writing the code. At least this way, they’ll be writing better code sooner.

I also genuinely believe that mentoring has many benefits for even the most experienced developers. I’ve had to learn a tonne of stuff specifically so I can explain and demonstrate it to someone else. And to explain it, you’ve really got to wrap your head around it. There’s all sorts of things I kind-of-sort-of understood, but not really, that I’m now 100% clear on purely because I had to get my story straight before I told it to other people. It’s taken me many years to build my Explaining Fu – and while I’m no Richard Feynman, that clarity has definitely benefitted me and my mentees. It also finds its way into my code quite often. I’m way more S.O.L.I.D. aware than I used to be, for example. That’s because I’ve done example after example after example. It’s like ear training for musicians.

These experiences have built my confidence, as well. I’ve given the fundamentals so much thought, and explained and demonstrated them so many times in front of so many very different audiences, that I feel my horizons have widened considerably. Need to learn Kotlin? No probs. Need to prepare a workshop? No worries. Need to present to the board? No sweat. I’m much more fearless after two decades of teaching and mentoring. Sure, it scared the crap out of me in 1999. In 2019, give me a spear and show me where the mammoth’s are at.

So, not only are there people out there who are better developers because of my mentoring, I’m also a better developer for it, too.

This is why I believe structured mentoring needs to be part of the developer journey. First, as a mentee, and then eventually as a dedicated mentor. Our profession needs to be structured so this is normal: the rule and not the exception.

 

If you’d like to talk about developer training and mentoring in your team or organisation, drop me a line.

 

 

Software Development – What Are The ‘Basics’?

Okay, so here’s a hot take…

I’ve been grappling for more than a year now on what I would focus on in a guide to software development for people progressing from learning programming to building more complex systems for real end users.

I’m acutely aware – based on my own experience, and the accounts of many others – of the skills I really wish I’d learned when I started out. As a trainer and coach, I’m also very aware just how many developers get through seemingly their entire careers without being exposed to some of these foundational skills. Hence the need for a “Software Development 101” introduction.

I’m clear in my own mind about some of these things:

  • A developer should know how to drive design directly from users’ needs
  • A developer should know how to use version control (basically, seatbelts for programmers)
  • A developer should be capable of enumerating test cases given either a set of requirements, some behavioural model of the system (e.g., a UX flow diagram), or a copy of the code itself (e.g., what could go wrong with this line of code?)
  • A developer should be capable of automating the execution of their tests so they run fast and consistently
  • A developer should be capable of writing code that’s open to change (that’s a whole can of worms in itself)
  • A developer should recognise potential code quality issues when they see them, and know how to fix them
  • A developer should be capable of changing code without breaking it
  • A developer should be capable of visualising and clearly communicating multiple aspects of their work and their ideas – e.g., architecture/design, workflow, UI/UX, business rules etc. Partly because it can help enormously in bulding understanding, and also because communicating with pictures tends to be so much more effective in many instances.
  • A developer should be capable of automating their software delivery “pipeline” so that getting working code from their desktop to end users is as frictionless as possible
  • A developer should be capable of rapidly iterating their designs based on real user feedback
  • A DEVELOPER SHOULD BE CAPABLE OF A DIRECT, CONSTRUCTIVE WORKING RELATIONSHIP WITH THEIR CUSTOMERS & END USERS
  • A DEVELOPER SHOULD BE CAPABLE OF WORKING HARMONIOUSLY & CONSTRUCTIVELY WITH OTHER DEVELOPERS
  • A developer should be capable of research – nobody arrives on the job knowing everything they need to know for that particular job. A tonne of stuff must be learned along the way. A developer needs to be an auto-didact, because ain’t nobody gonna teach you everything.
  • A developer should be capable of setting themselves goals and managing their own time and resources – contentious, I know. But so many of the issues I see devs and dev teams facing can be boiled down to the perceived need of organisations to micro-manage them, and developers surrendering control over themselves and their work.
  • A developer should be capable of objectively, honestly and transparently communicating progress and making projections about how long it might be before a feature or release is ready. Again, a whole can of worms. But, at the very least, developers can build a reputation for actually being done when they said they were done, even if they’re unable to predict in advance when that might be. It’s bad when the train is late. It’s worse when we claim it’s still on time.

A software developer should be a competent programmer who can be trusted to reliably deliver what customers need, when they need it.

They deliver working software frequently. They listen and are responsive to customer feedback.

They don’t deliver broken software. They don’t wander far from working, shippable code. They don’t make irreversible changes to code. They test their software continuously, and never assume it’s working – either on their machine or anyone else’s.

They can sustain the pace of innovation on a system far beyond a first release, for as long as the customer needs.

They know problem code when they see it. They know how to improve code to reduce or eliminate those problems, without breaking it. They don’t let large batches of problems build up. They address issues early, and continuously.

They build a close working relationship with their customers, and earn trust by delivering what they promised. They don’t make promises they don’t know they can keep.

They can work effectively with other developers, and are open to collaboration. They make sensible, informed choices based on the customer’s and the team’s needs.

They learn what they need to learn, and when they don’t know, they say “I don’t know”. Then they do what they need to find out.

They report progress honestly and objectively, and never say “Take my word for it.”

They work hard to make themselves clearly understood – face-to-face, with pictures, in writing, and especially in code. They work hard to understand what others are telling them, and are constantly testing their own understanding (e.g., with examples).

They are largely self-managing. They set themselves goals. They prioritise and manage their own time effectively. They make time to learn and improve at their job. (And they don’t ask for permission to do that.)

What I’ve learned, after nearly three decades as a software developer, is that all of these skills are needed, and all of them can be learned. Probably not overnight, for sure.

It may take a few years to build a set of skills like this to a level of competency where you can be trusted to just get on with it. Which, I think, would be my single-sentence definition of a “software developer” – as opposed to a trainee or apprentice. And, yes, I know there are lots of people out there who say “Hey, if you’re getting paid to write code, you’re a software developer.” I certainly don’t own the term, and they’re welcome to their own interpretations. This is not my attempt to legally define it. I’m just getting things clear in my head, about what I mean when I say someone is a software developer. And, if there was an introductory guide for that, what would I include?

You are now free to start throwing the furniture around.