Yesterday at Barcamp Philly, I led a conversation around a simple question: what makes a good programmer?
I started by rejecting the idea that the technology is the hardest part. Getting good at anything is a thousand-hour problem, if not more. So I dumped the terms "hard skills" and "soft skills" in favor of "computer skills" and "people skills."
But of course lots of things are in the middle. And in the end, they are all in the middle: we use computers for a reason. And that reason is people.
"What's with the ghost and the clock?" I was listed in the official program as "Thomas Boubell." I explained that Thomas Boubell is a ghost who lives in a clock tower.
Everyone has an opinion about what makes a good programmer. And I made clear that all of those opinions are welcome. Because if you work in design, UX, management or business development you know a lot about the process and what good outcomes look like.
The first hand raised for the "computer skills" program was for SQL. OK, yes, absolutely. It's pretty likely you'll need to talk to a SQL database at some point. But after that, things were much more meta. Much more universal.
Our computer skills list:
Then we dove into people skills. A program that doesn't solve the right problem is the buggiest problem ever. How do we get to the right solution without burning people out? How do we work together in a sustainable way?
Our people skills list quickly grew:
UX is an entire discipline in itself, but the basics are valuable for any developer to know. UX is rooted in humility ("we need to find out what the customer really wants and needs") and empathy ("we need to keep improving based on real-world experience"), two skills that go a long way for programmers who want to avoid wasted weeks shaving the wrong yak.
The skills in the middle are the most interesting to me:
Writing readable code
Know what you don't know (humility)
Writing user stories
All of these take time and practice to learn but greatly improve your value to the team, the project and the organization. Even, yes, productive laziness, which I would define as a willingness to see when the fastest code is actually the slowest: choosing the solution you can implement correctly in the time available that will work just fine for the problem at hand. And also the DRY principle: Don't Repeat Yourself; write reusable code and reuse it.
The emphasis on people skills led us to dive more deeply into what helps developers work effectively with one another and with adjacent professions, like UX:
As a senior developer, I'm especially familiar with both the failure to delegate and the desire to "hero it out" and paper over big gaps in time and resources by throwing my own body... and evenings... and weekends... on the tracks. But ultimately this is bad for the company, not just for you. And it's really, really bad for you.
I don't intend this to mean that you should never pursue something you're passionate about in your personal time, just because it's work-related. Different things engage different people. But if you feel like you must work on weekends, that's a bad sign.
As a dancer, I know my first job is not to step on my partner's feet. Followed by not colliding with everybody else on the dance floor. Followed by making my partner feel great about the dance. And... oh yeah, having fun myself.
The same priorities apply to programming. Version control, the process of managing the contributions of many developers to the same code, is a big part of the answer. And nearly everyone at Barcamp had opinions about it and git, the (almost) universal version control system of modern developers.
Our list included:
Branching is a huge win of modern version control systems like git: it's very, very easy to say "hey, I'm going to code in my own little space for a while, and merge my changes back to the master branch later." And you should do it. Every time.
But people forget. So git is designed so that you can even branch at the last minute, after you've already made lots of changes but before you've committed them:
git checkout -b cool-new-feature
Then we got into the specifics of branching. There should be feature branches — a branch for each new feature added! Everything should arrive in master via a git "pull request!" There should be release branches, and nothing should land in master until it's been deployed! There should be "dev," "staging" and "production" branches, to run the code through testing by the developers, then by the users, and finally make it live!
There's more than one answer here. The right path depends on the complexity of the project, the number of stakeholders, and the risks involved in deploying a mistake to production.
But git makes branching so easy that at an absolute bare minimum, you should always create feature branches, and have a second person review them before they are merged to master, even on the smallest team project. We were all firmly in agreement on that.
Folks also suggested specific techniques to make code review nicer:
The latter is easy and I'd agree you should always do it, especially if your branch is around for a long time. That way you don't face a monumental struggle to merge the code at the end. Squashing and rebasing on the other hand, is a nice touch that makes it easier to review the history of a project later. But since github does such a nice job displaying the total set of changes to your project based on all of the commits in a pull request, squashing and rebasing aren't essential for every project.
When it comes to coding together, version control isn't the end of the story. There was great enthusiasm for pair programming at Barcamp. Pair programming is a technique in which developers sit together at the same computer... and only one of them has control of the keyboard at any given time.
This might seem like it cuts productivity in half, but it often does the opposite. Programmers, even the most experienced, make mistakes constantly. A second human being, working together in a constructive environment, often spots these right away. And pairing also leads to ideas and approaches that would never have been considered by a single person. Without pair programming, our Apostrophe CMS wouldn't have cursors.
The benefits of pairing as a mentorship technique are also considerable.
More than 50% of the room had tried pair programming at some point. Just a handful worked that way at least 50% of the time. But quite a few more wanted to. Having built most of Apostrophe in pair-programming sprints, I strongly agree.
But what makes a good pair programmer? Here's our list from Barcamp:
We couldn't get to everything in a 45-minute conversation. But with a few minutes left on the clock, I suggested we have a quick conversation about testing.
And the response came back right away: "that's always when testing finally comes up!"
So that's mistake number one: don't put off thinking about testing. Write unit tests (automated tests of each part of your program) early. Ideally, engage in test driven development (TDD): write the unit tests first, and the code second, so that as you write the code your tests begin to pass.
This works better for some types of code than others, but if you're writing back-end code like a REST API it's silly not to use TDD. Plus, it's enormously relaxing to know that your code already passes a complete test suite when you first hand it to another programmer to use.
Of course, automated "unit testing" isn't the only relevant type of testing. "Regression testing" in which a human being steps through the functions of the program before each new deployment to production... even if everybody swears up and down they changed "only one thing..." is enormously helpful in finding unexpected bugs and interactions.
In the middle stands automated interface testing, in which a program clicks simulated buttons to walk through your interface. This is valuable too. But while it catches bugs, it's easier to avoid bugs in the first place with unit testing. And no matter how good your automated testing is, there will always be situations where a button "works..." but the button is hidden under another button. People are a necessary part of the process. People are the point of the process.
Here's our list of thoughts on testing from Barcamp:
In the end, it all comes down to people. Get to know your team, get to know your customer, get to know the human purpose of your project. Those things lead directly to a sense of ownership, an emphasis on quality and a better result for everyone. Which leads to healthier, happier programmers with the skills to take on new challenges.
Opportunities to do that are easy to find. Make time to participate in the early UX conversations with the client, so that you grasp what is important to them and why it should matter to you too.
Institute regular "best practices" conversations with other developers in your workplace; share what you know and learn what you don't.
Schedule regular conversations with your client... don't just wait for the phone to ring.
Mentor less experienced developers in your workplace, through pair programming, listening and advising, not just monologuing.
Attend an unconference.
Pick up the phone and call your customer. It helps.
And don't save the quality-assurance conversation for the last minute. Because nothing says "I care about the outcome of this project" quite like taking the time to make sure things work.