This is a blog post I've had on my "to write" list for a while. At the end of December Buzz Andersen posted a link on twitter that outlined why he doesn't feel comfortable with Pair Programming or the Agile ideal. A conversation followed between several developers, including myself, which was nicely archived by Manton Reece using his Tweet Library app. I recommend reading through the archive to get an idea of what was said.
Now a few weeks later when Manton posted the archive a thought occurred to me. There is a lot of stuff out there which developers need to look at. Lots of concepts, lots of patterns, lots of tools. With this massive jumble of stuff it can be quite easy to lose sight of what might be the core principles.
There are very few absolutes in programming, very few things that, if you don't do them, then eventually things will blow up. These are the core principles of development. There are lots of things out there that claim to be core principles, but you can develop good software without them, and they are usually just one way of using the core principles. The problem is that it is hard to figure out what these core principles are. I don't know what they all are, I doubt anyone does. But you can tell a core principle when you see it. I'm going to go through two examples of things that some consider core and what about them is actually core.
Test Driven Development
Test Driven Development, or put another way: test first, code later. You write your software by writing a test for a method or function or component and then writing code to make it pass. There are a lot of people out there who swear by TDD and some of the more extreme TDD advocates go as far to say that TDD is the way everyone should write code. Now it is true that TDD has advantages, but it also has disadvantages. There are also some things that depend on your view of the world.
As one example, TDD solidifies the interface for a method/function very early on as. Some may consider this good, it helps lock things down, it makes you think things through more in advance. However, some (including myself) consider this early solidification annoying. It just doesn't feel right, we prefer things to stay fluid in the early stages and so we want to be able to tinker. As such, when we decide to make a change, we don't wan't to also have to update all our tests to cope with that.
People like me tend to do the opposite of TDD: code first, test later. Whereas a TDD user would write their test, run the test, write the code, re-run the test, I follow the somewhat simpler tactic of write the code, run the code, write the test when the code works. Of course, even I find TDD can be very helpful in some circumstance, such as writing a framework of library from scratch.
The basic point is, there are different views of testing here. The first is that tests are a development aid, they help you build software. The other view is that they are simply a testing aid, they help you from breaking stuff that already works. Neither view is wrong. There has been plenty of good software shipped that doesn't use TDD and plenty of good software that has been shipped with TDD. You can get away with using either view. There are even more views as well. Sometimes I don't write a test at all, I just test manually. Automated tests are better, but sometimes I simply don't have the time, or maybe the need (especially if it's a test/toy project).
So we have all these concepts, plus many others. They all seem different, and people have long and heated discussions about them and which is better. But there is one underlying theme in all of them and it is a core dev principle: you should be testing your code. Be it writing tests first, writing tests later or just manually running the code, you should be testing. How you approach testing is entirely up to you, but the benefit of any form of testing over the other is minuscule compared to the benefit of any testing over not testing at all. If you just write code and ship it, there is almost guaranteed to be bugs. You cannot survive long without any testing.
Pair Programming is a where you have two people looking at the same code at the same time. They don't necessarily have to be in the same room, or even on the same continent, just as long as they're both looking at the same code. The idea is that the whole is greater than the sum of its parts, i.e. two programmers working together on the same code produces better results than two programmers working separately on different code.
A lot of people swear by Pair Programming and do it everywhere. And pretty much every developer has pair programmed at some point in their life. But like TDD, it isn't necessary for writing great software. You don't need two pairs of eyes on the same code all the time. Some people prefer it, but quite a few don't. They feel uncomfortable with Pair Programming, they don't feel as free or as creative. Ultimately it leads to them not being as productive as they would be if they coded alone.
In the archive I linked to above there is a tweet of mine where I say that "I've found the only useful pairing sessions start with the words 'I cannot figure this out'". For everyone, Pair Programming has its benefits, but they aren't there all the time. Due to this is cannot be a core dev principle. Think of all the great code that has been written by a single person. It's not going to completely fall apart in the near future. But there obviously is something behind Pair Programming that is a core principle, as everyone finds it useful at some point.
That core principle is code review. Now this doesn't have to be where a whole team gets together. You don't even need another person. It can just be yourself, review code you wrote last week, last month, last year. If you can get someone else to help then great, having a fresh pair of eyes can find problems you've missed. It also doesn't need to be comprehensive or on a fixed schedule. You don't need to review the entire codebase before each release.
Now you might say "well I can ship without reviewing code". To a degree, sure. But for how long. If you never read over code you've already written, how long before something falls apart. Of course I would also say that it is almost impossible to ship without review code. You're constantly reviewing the code you write. It is a natural part of writing code, that you read it back.
Don't miss the forest for the trees
When someone says "if you aren't doing X then you're a bad programmer" then listen to them, but don't believe them. Question what X is. Can you write good software without doing it? If yes then you aren't a bad programmer, just a different type. If the answer is no, as with testing or code review, then you have found a core principle and yes, if you aren't doing them you're a bad programmer.
There are many core principles out there, but I wouldn't be naive enough to think I can list them all. It can also be hard when there are loud voices speaking against you to not believe you're doing something wrong. There are also lots of things there may seem like core principles because everyone agrees you should do them, but they can be generalised. Take for example commenting your code and using logical names for variables and methods/functions. They all fall under the umbrella of "write readable code".
The vast majority of patterns and techniques out there are simply different manifestations of these core principles. You should feel free to use whichever one you wish, as each will have its own pros and cons. There is also a large degree of subjectivity, where one technique can feel better than another. Use what you find helps you the most and don't listen to the evangelising from others. As long as you have the core principles covered, you can write good software.