What I Believe About Writing Software

So. I left ATG consulting so I could get a better understanding of what different environments are like. I've worked at a variety of startups, and written some Ruby, some Scala, even some Flex and Actionscript, and done a fair amount of fixing, writing and rewriting different systems and architectures.

The good news is that all in all, I don't suck. I'm very much of the "Domain Driven Design" school of development: I think that the domain and the concerns of the business team are a (if not THE) priority and I believe that it's possible to write code in such a way that makes it hard to write bugs. I've tried different styles, and while the style of code I prefer has been charitably described as "verbose and up front," I think it is clear and leaves little room for ambiguity. If there are bugs, it's not a mystery where they are -- I don't like metaprogramming and I don't like using any more tricks than I have to, so I can live with the occasional verbosity. In fact, some of the code is actually better than I remember. It's a nice feeling to read code and be impressed by the writer... and then realize the writer was you.

It turns out that the biggest problem I have is not a technical problem. It's that I believe different things than other people. Some people believe different things than me, and are surprised and concerned when they find that I have a different background than them and don't believe the same things they do.

I've been told that some of the things on the list are "not agile" (not XP, technically) and that "you aren't going to need this." I don't believe XP prescribes or proscribes any programming technique: I don't believe that YouAintGonnaNeedIt is an automatic veto, just as TheSimplestThingThatCouldPossiblyWork isn't a green light to do what you want: I've heard "simplest thing" used as a justification for everything from never using transactions to checking in over a gigabyte of binaries into a project (including both Linux and MacOS binaries of Apache and MySQL) to "simplify" the developer's build environment.

So. Here's what I believe.

I believe that loosely coupled, encapsulated systems are the way to go, for many reasons. I believe that they are easier to mock, easier to debug, and easier to use.
I believe that good strong interfaces make for good neighbors.
I believe in separation of concerns. Specifically, I believe in separation of content from presentation.
I believe in the SOLID principles.

I believe that programming languages have their strengths and weaknesses. Arguing which is better is like asking if a hammer is better than a trowel.
I believe that operating systems have their strengths and weaknesses. Given the right toolset, I'm as happy programming in Windows as I am in Linux or MacOS.
I believe that editors have their strengths and weaknesses. On a given day, I'll use vim, jEdit, Textmate, Eclipse and IDEA to edit files. I'm fine with all of them.
I believe that frameworks have their strengths and weaknesses. J2EE works in its context. Rails works in its context. They both suck outside their context.
I believe that design by contract, program functions and static analysis tools such as ESC/2 are going to be the next wave of programming.
I believe that weak typing is good, because it speeds rapid prototyping and code flexibility.
I believe that strong typing is good, because it limits the number of possible bugs that the programmer can generate and provides a rich abstract syntax tree that can be used by tools.

I believe that simple database constraints are a good thing. Specifically, I believe that adding NOT NULL directly to your tables is a good thing.
I believe that referential integrity can, in some cases, be a good thing. I think that used properly, they reduce the amount of bugs and bad data possible.
I believe that database transactions are a good thing. You may have concurrency bugs when you scale your app if you don't use them.
I believe that 99% of the time, a decent SQL database with transaction and constraint support (i.e. not MySQL) will serve your needs, and that NoSQL is required only in some exceptional scenarios.

I believe that designing systems using finite state machines and explicit state transition can be a good way to tightly define a system and eliminate bugs.
I believe that validating an object is good, validating a state change is better, and validating a system is best.
I believe in PMD, Checkstyle, and Findbugs. I believe in Flog, Heckle, and Saikuro.
I believe in Release It, in its entirety. I believe in fail fast. I believe in bulkheads. I believe in circuit breakers.

I believe that most of the really nasty bugs come from miscommunication between different parts of a system.
I believe that defensive programming is a good thing, because it flushes out hidden assumptions between the different parts of a system.
I believe that code is not finished until you have thought about how the system responds to invalid input and exceptions.
I believe that, on some level, unit tests, assertions, defensive programming, design by contract and validation logic are all the same thing.
I believe that that a good solid configurable logging framework is a requirement for production code.
I believe that having diagnostic logging statements in production code is a good thing.
I believe that code is not finished until you have thought about how someone else is going to have to debug it.
I believe that comments can be valuable and worthwhile when they augment and not repeat the source code.
I believe that tests are not documentation. Documentation is for a human audience first, and tests have to work first and be readable second.

I believe that some tests are inherently useless, notably when they test the underlying library code and not the system under test.
I believe that any testing done by a programmer, automated or otherwise, is inherently biased in ways that don't reflect a user.
I believe that automated tests can be useful, but they can only show you the programmer's intent. Even end to end system tests will only look for specific areas of a page.
I believe that 100% code coverage provides little advantage over 80% code coverage.
I believe that a good integration test suite is better than a great unit test suite.
I believe that there is no substitute for a good QA team.

Finally, I believe that two people pair programming are no more efficient or effective than two people programming alone. The most cited study points to a 15% development time cost, but mentions that the co-workers believed that code was consistently at a higher level of design quality and had fewer defects. This has not been my experience: just looking back at the rate and quality of work produced, I can't see a substantive improvement over a regular team. To be clear, I don't think it's markedly LESS efficient or effective, just that I haven't seen it take teams to a different level. Which is saddening, but I'm not going to go into it.

Thank you.

Comments