Imagine you’re ACME Parcel Delivery. You’ve got a system that can take orders for deliveries at the store, through your website, or through a mobile app. And let’s say A1 Delivery Service takes a certain order, but they don’t do that type of delivery. So A1 wants to push these types of deliveries to you. Be careful. You’re about to fall prey to the #1 mistake made by software developers.

You’re happy to have more business, so you assign your brightest junior engineer to write a bunch of code for a new feature that will accept incoming orders from A1. He writes gorgeous bug-free code, thinks through all the various problems, and gets it working smoothly so that your system will accept orders from A1 Delivery Service.

What’s the problem?

Your junior engineer never asked, “What if we need to do this for another provider in the future?” All the code he’s written, as bug-free as it is, was wrapped around A1 Delivery Service. All the variables, reports, default parameters, and database columns are A1-specific. What happens when you need to add a second provider to the system?

Implementing vs. architecting new features

This lack of generalization is the one of the biggest mistakes that junior engineers make. They see the new feature as an isolated task. But down the road, when you need to add another provider, it becomes an enormous pain that chews up your budget and adds wasted time to the project. Everything was tied to this one specific solution, rather than a generic solution with an instance for A1.

Your engineer saw the feature as a one-off solution, but it may actually be worse than a one-off because in this case, fixing the mistake is more difficult than if it weren’t there in the first place. You’ve got to reverse-engineer what he originally did and fix it—or write another one-off solution for the next provider, which makes the situation even worse.

It’s not that new software developers lack technical skills. They just don’t have the experience yet to see the larger landscape. They’re given a task, and they’re eager to do it. So they put all of their energies into fulfilling that task as amazingly as they can. It seems like a good approach at the time, but it’s usually not until the third or fourth time that you start realizing you need to step back a bit and ask, “How can I do this so I won’t get burned when I need to do it again?”

Eventually you learn to say, “Yes, I need to integrate to A1 Delivery Service, but that’s really just one instance of integrating with another company. So let me figure out how to integrate with another company, and then just provide one instance of that for A1.”

It’s a subtle thing, but it’s hugely important. This kind of thinking only comes with experience.

How to avoid rookie coding mistakes made by software developers

Unfortunately, there’s no way of avoiding these rookie mistakes completely. But you can help them learn fast how to make fewer errors. Here are four ways I coach them up.

1) Give them more information than they need

As a project leader, I’ll walk into people’s offices unprompted and give them an information dump. I’ll say, “I know you’ve got this one task to do, but let me explain to you why you’re doing it and what it means in the larger context—not just what you have to do.”

I do that a lot with changes, too. I’ll walk around and tell the whole team, “Just so you know, we just made this decision over there, and you should be aware of it. You don’t need it now, but you might need it in the future at some point. So just be conscious of it.”

If you explain a lot more than your team needs to solve a problem, and how it fits into the whole process, you nudge them in the direction of thinking about it in a larger context. So when they attack their little piece of the puzzle, they’ll already be thinking about how it impacts the whole thing.

Many times I find that software developers will make better decisions for the project as a whole if they understand the decisions that are being made in other areas, because when they finally have to merge them together, it already was developed with that larger context in mind.

2) Be open and available

Keep your door open and always make yourself available to your engineers. At AVI, we’re very open and inviting. My office is sometimes like Grand Central Station where people just walk in and ask questions on the fly. It fosters collaboration and communication, and it helps everyone to know what everyone else is doing and wrestling with. When your engineers are connected like that, they can make better-informed decisions during development.

It takes a lot of energy to maintain this kind of openness and availability, but it works. And it’s a lot easier if you’re a small company.

3) Create a Culture of Doing Good

It’s absolutely essential to have a general desire of the company to do good, not to just do. When everyone on the team is thinking about how the end user will experience the product, and not just about meeting spec, you end up creating a stronger, better product.

Your junior engineers will catch on really quick that they need to think about what’s best for the product and the user. They can learn to slow down and consider how their changes will impact the project down the road.

4) Haunt the Code

I’ve been known to haunt the codebase at 2:00 a.m., just to review the code. Then I’ll come in the next day and ask a developer, “Why did you do it this way? What happens if you do this or that? If such-and-such happens down the road, how do you think this could be done better now, so it’s much easier later on?” If you do that enough (but not too much—you don’t want to be annoying!), engineers start asking those questions on their own. They’ll say to themselves, “If I just make this a little more generic, I get the feeling it might be useful down the road.”

Once you get to that stage, good things begin to happen.

 

Next Steps