Monday, September 16, 2013

Evolution of a developer

At first I wrote flexible code. I figured that because I couldn't predict the future, I better leave all the options open. The code was modularized, well-factored, with a lot of bells and whistles, and more than enough documentation. I was proud of it, until I learned that:
  • Things changed so rapidly that even my solidest assumptions became false. 
  • The small flexibilities in the code were too small to be really helpful, yet too many to be easily refactored.
  • In a world of 140 characters, nobody read my heavy documentation. Literate programming didn't work, if ever.
  • Longer code, no matter good or bad, is harder to maintain.
So, in another project, I switched to writing extremely tight code. I used a lot of functional abstractions and removed every single bit of redundancy. And documentation is, of course, left as an exercise for the reader. I figured that good code was deleted code, and short code could be easily refactored. I was proud of it, until I learned:
  • 80% of the efforts had been spent on reducing 20% of the redundancy. Like speeding, it didn't save much. 
  • Highly-factored, redundancy-free code can be difficult to document, understand and debug. 
  • The best way to compress some code is using gzip, not your hand.
Now I think, just like many things in life, a balanced position is the best. In other words: write simple code. I deeply believe that you can achieve simplicity without compromising on other aspects. I believe that applying the simplest solution which consumes minimal energy is how the whole universe works. When you get one simple answer, it may not be the right answer. However, once you find the right answer, it is usually also very simple. 
I think we should just make it easy. If you feel difficulty when writing a program, if you find yourself scratching your head, either because of intricate structural design or abstract code factorization, you are probably doing it wrong. After all, you should be able to enjoy programming, not suffer through it. There is more than one way to do it - any approach can be a good start, as long as you feel easy and comfortable about it, and you do not forget to keep improving it. If it's too fat, cut some; if it's too thin, grow some. Eventually you'll reach a point where you find ultimate simplicity. Call it fixed/optimal/equilibrium point as you like, it's all the same thing. It's just how the universe works.

--- Ming Lei, on the St. Louis Lambda Lounge list


  1. In order to make software dynamic and abstact, one must have a deep understanding of both the problem at hand and of the field the problem adheres to. If you haven't come across the problem enough times, then you simply lack the wisdom to abstractify the problem

    Even if one can indeed write a generic, dynamic software that solves the problem, then we must evaluate whether it is actually worth the time (relevant xkcd

    I generally prefer to use a KISS approach whenever it is appliable.

  2. Good post, really sums up my personal thoughts. Ultimately, someone will come back and look at your code. Having something small and clean will always win out. The best way to start is usually a language that gets things done quick when you can ... JS, ruby, python, groovy, etc. The next challenge with getting efficient code is always features. Even the simple features will kill you so every time you think, "oh I need to add X for case Y" that is when you ask, "how do I remove case Y".

    And like you said, don't try and optimize things to save 1 or 2 lines, but if you see ways to remove large chunks of code, go for it. With practice, you'll see places to refactor before you waste a lot of development time.