Thursday, September 24, 2009

Zen Programming

Are you tired of moving methods around to “improve” design? Are you tired of trying to understand other developers’ code? Are you struggling to learn IDE shortcuts? Don’t know what to do with automated refactorings in “Refactor” menu? There is good news, you don’t need it all. Acknowledge the true nature of software. The only thing you need is to know the problem you’re solving and write code.

I knew I was out of place from the very beginning. I started the application and after splash screen it displayed an error. “What’s is wrong with it?” I asked another developer. “It’s ok. Just try starting it several more times, and it will work,” he said. I was, and still am, proponent of technical practices which are often used under “agile” term. Almost everything in this place was contradictory to my believes. (I will omit non-technical problems.)

  • There was no up-to-date documentation and no one could cohesively explain what application does, what are the inputs and outputs. (I don’t mean no one knew, only that no one could explain.)
  • There was only one development environment shared between everyone. (To make the matters worse databases were located far away and application start-up time was more than 10 minutes.)
  • At times application won’t start at all for unapparent external reasons.
  • There was no dedicated build server.
  • There were no unit tests (existing ones were broken and abandoned long ago). The only meaning of the world “test” was to test things manually.
  • There were no full-time testers on the project.
  • There were a lot of classes with 1000 lines and more. Sometimes with mixed business logic, UI and inputs.
  • The worst thing was that no one cared about it. And there was a reason…

While my productivity sunk, most of other developers were making good constant progress. If application wouldn’t start, they would know which dependent-on services to restart and who could do it. They could test code manually in debugger and it would work just fine. They could make sense of huge piles of multi-threaded code by just stepping through it in debugger. They were not writing clean or perfect code. They were making mistakes sometimes, but non-critical ones). They were adding features in time and bringing business value in spite of everything.

It’s said “change your organization or change your organization”. I believe there is another option. You can learn what others are doing and do exactly that. This is what I’ve been trying to do over the last year. I called this “zen-programming” (name inspired by this book) and from my humble observation here is the most contradictory things Zen Programmers do.

You discard complicated tools, because you don’t need them. They are distraction.

You don’t automate tasks, because you can do them yourself fast enough.

You don’t write documentation, because source code is the best and the only credible documentation.

You don’t pay much attention to your code appearance, because the essence is not in how it looks, but how it works.

You don’t let code drive you, because you’re the master of code. Beautiful cloud castles from code are waste of your time.

You never rely on UML-like pictures to explain a program. They are inaccurate and misleading.

You are not afraid of duplication, because you know well enough where it is.

You don’t spend time beatifying code and making it easier to understand, you live in code, you know it too well.

When working with someone else’s code, you don’t think “why” you think “how”.

You don’t need to double-check your ideas, because you know you’re right. Even though your solution may not be perfect, it will work just fine. You totally trust yourself.

You never attempt to try create anything perfect, because it costs too much and no one needs it. “Most useful” doesn’t mean “perfect” (far from this).

As a Zen Programmer you acknowledge messy and chaotic nature of software. You don’t struggle with it, but embrace it by becoming a part of it. While there is a value in well designed, thought through systems, code is not the purpose of software nor they reflect what software really is.

Update: what I meant by Zen Programmers seems similar to Duct Tape Programmers except that zen-guys are not in the least afraid of "C++, templates, multiple inheritance, multithreading".

9 comments:

Jose said...

You missed one:

You leave the project and someone else has the misfortune to try and figure out what your code is supposed to do.

It is not the messy and chaotic nature of software you're trying to deal with, but the messy and chaotic nature of the previous programmers. Attempting to find zen in the mess you were left with is admirable, but like coming to terms with having cancer, it still doesn't make the underlying issue a net positive.

Bruno Cassol said...

You also missed:

You will never, ever release open source software. If you do just sit back, relax and meditate on why people think your software is useless.

You give up ever trying to implement large projects.

You can do good testing manually faster than automated tests because we all are Chuck Norris children.

You know your clients will have no alternatives for maintaining the software other than you. And if time passes probably even you will not be able to do it.

Again you know you have Chuck's DNA, so you don't need those "complicated tools", documentation, readable code, code reuse mentality, comments.

Because we all know:
from chaos came software,
there it should stay,
like that it should be.

Good luck!

Dmitry Kandalov said...

I see your points, but actually I was not 100% jocking. Although, these things are contradictory to what considered to be good style of programming, in practice they seem to work.

Bill said...
This comment has been removed by the author.
Bill said...

Acknowledging the messy and chaotic nature of software is important. A lot of attempts are made trying to get rid of it by making abstraction layers, but in the end, code will always by messy.

All those attempts only made developers stacking layer over layer, and software that could be done in 5k lines now takes 50k lines. On average software has a bug every 150 lines, so the 'better' code will end up a lot buggier.

Loosing all the tools and documentation will force you to rethink code, and come up with better ways to write easy readable and thus better maintainable code.

Of course mentioning any of this will attract angry hordes of corporate drones, just like Joel Spolky's Duct Tape Programmer post of last week went like a shock wave through the community.

But the fact is, TDD and other so called good practices are mostly evil.

TDD for example, requires you to write tests first, then fill in code later. When I read that, my stomach turned. In my opinion that is the complete opposite of what I think good practice is.

I don't want to have code that passes tests, I want code of which I exactly know what it does.

Tests are rarely complete, and are also subject to the average bug per line (just as documentation). A single pass step-by-step debug will tell more than 10 unit tests could.

So in short less is more. This way you can write code in a day that otherwise would have taken weeks, with much less bugs.

Jose said...

@ Bill

"... stacking layer over layer, and software that could be done in 5k lines now takes 50k lines. On average software has a bug every 150 lines, so the 'better' code will end up a lot buggier."

Sorry Bill, but any such metric is a falsehood. The number of lines of code has nothing to do code quality. You could write hideously confusing code in one line or in 100. Applying it equally to every project as you did here doesn't take into account programmer skill, the verboseness or terseness of any libraries used, or the complexity of the language(s) used.

"I don't want to have code that passes tests, I want code of which I exactly know what it does."

Sorry again, but I don't think you've studied the topic of TDD. Generally, it's 1) write test, 2) write bare minimum code that passes, and 3) refactor.

Ideally, by the time you reached step 3 the tests have defined the functionality in your code, so you know exactly what it does. The tests also serve as proof that the code is successful. With the tests supporting you, refactoring is easy as you don't have to worry about side effects.

It's not suitable for every project, and successful realization depends on the quality of the implementation, but it's still better than "just wing it".

Bill said...

@Jose

Jose: "You could write hideously confusing code in one line or in 100. Applying it equally to every project as you did here doesn't take into account programmer skill, the verboseness or terseness of any libraries used, or the complexity of the language(s) used."

Completely irrelevant. I was talking about averages, so assume the same language and same skilled developer.



Jose: "Sorry again, but I don't think you've studied the topic of TDD. Generally, it's 1) write test, 2) write bare minimum code that passes, and 3) refactor."

So then I do understand, and yes I am convinced this method produces garbage code.

Dmitry Kandalov said...

I like TDD. In some cases it helped me to write code I was totally satisfied with and had confidence in. In other cases it was a terrible waste of time and huge efforts which never paid off. Probably, just like with any other tool I should've known how and when to use it.

I believe it's possible to write crap code using any methodology and beautiful code without any. (And what is "beautiful" anyway?)

Bill said...

@Dmitry Kandalov: "I believe it's possible to write crap code using any methodology and beautiful code without any."

It's not about the beauty of code, it's the idea behind TDD that is wrong. It's the complete confidence in the tests this method requires. But if you accept it's impossible to write bug free code, than it's logical to assume tests are bugged and incomplete as well.

Also depending on what you are developing, the use of tests can be quite limited to fairly easy problems

I don't say don't do tests ever, but writing the outcome first, and do the bare minimum to pass that test is not a valid method to develop code or is proof your software works.