Hacker News new | past | comments | ask | show | jobs | submit login
Good code is cheap code (geekm.ag)
26 points by dicka_j on March 5, 2011 | hide | past | favorite | 9 comments



I've started seeing design patterns in a vastly different light once I realised that, in PHP, all of the Abstract Factory pattern can be replaced by a simple:

    $instance = new $className();


"Design Patterns" are conceptual repetitions in code. In a sense, a "design pattern" represents that which the programmer has failed to abstract away in a library using his programming language.

It may be a failure of the programmer, or a failure of the language.

Established "Design Patterns" are hard or impossible to abstract away in a library, or they would not have become standard "Design Patterns".

Instead of looking at conceptual repetitions (of nice design concepts) as a good thing, we should look at them as a workaround for the languages' inability to abstract away these things in a library.

Many design patterns in C++ or Java are just simple closures or dynamically-typed results in Python:

* The Visitor pattern is the combination of multiple-dispatch and inversion of control pattern. Multiple dispatch is possible to generalize in a library for all cases or is a language feature in various languages.

* The inversion of control pattern is just a higher-order function in a language that supports these properly.

* The singleton pattern is just a lazily-initialized global variable, and can be abstracted by a library in some languages.

Design Patterns are in this sense, "language smell". It is a good measure of what kinds of useful things are hard or impossible to implement as libraries.


Im not quite sure what you mean. Would you like to expand a little more?


He means that instead of implementing an Abstract Factory for creation of related objects you can simply use plain old KISS new keyword.


He's saying that PHP's ability to dynamically instantiate classes by using class-names stored in string variables obviates the need for more complex factory based patterns.

Schlepping around a particular factory instance is akin to keeping track of the class one desires to instantiate, which is easily achieved in PHP through the use of a string.

A lot of the canonical design patterns are applicable only for harshly statically typed languages such as Java, for dynamic languages like PHP many of those patterns are no longer applicable or useful. It's still quite possible to be a cargo cult programmer even if you happen to be using highfalutin' GoF design patterns.


amortize "cheap" over the expected lifetime of the code. If man hours to write is the primary criteria then you'll have an uncommented mess of crap. I doubt the author means for this to be taken to the extreme. It makes for a good sound bite, but there is no simple rule of thumb when deciding how much effort to allocate to various parts of a project.


He's right. Most of the expense in software development goes into bad code.

Consider: good code is less buggy, easier to debug when there is a problem, easier to maintain, easier to modify, easier to understand, etc. When devs work on good code it takes less effort and there are fewer problems so projects are done sooner. Good code is like a repellent for developer effort. Sometimes good code doesn't even need updating or maintenance, it just keeps working from version to version. In contrast, bad code is typically a time and effort sink. And because it's so difficult to work with, bad code typically doesn't improve in quality (merely in functionality) so it becomes more and more of an effort sink over time.

Time is money, developers spend more of their time mired in bad code, thus bad code is more expensive.


Full title: Good code is cheap code, provided you substitute the following non-standard definitions for "cheap" and "good".

How about instead, you simply say what you're saying, without forcing the rest of us to do algebra on the language:

"Maintainable code is brief" pretty much summarizes that entire article. Note, however, that if you'd used that as the title we wouldn't have needed all those paragraphs of definitions.


What has been helping me out is the phrase: "Code that cannot fail is infinitely easier to maintain then code that has many paths through it which might fail."

Murphy's law: "What can go wrong WILL go wrong". So go over every line of code and ask: "How might this function do something unintended?". If you find any answer to that question then you need to change how the function works until the answer is: "This function physically cannot do something unintended". If the hardware and compiler are working to specification then the ONLY path through this code is the correct way through (or a pretty exception/error that tells you what the programmer/user did wrong or what the hardware/compiler failure was).

For example: you have a function calculate() which takes a collection of Strings which represents items to process. The problem is that function foo() might run incorrectly and some String items may become invalid or incorrect. Then calculate() will make its best attempt, then calculate may throw an exception/error or worst of all, it may work. The solution here is to make it physically impossible for the items in the list to become invalid/wrong, don't use an array of String, use an array of class Student/Airplane/Book/ProcessItem which has a constructor which validates its own existence as soon as it is made, it will produce a runtime error (or better yet a compile time error) the instant the programmer/user made a mistake.

The millions of unintended paths through calculate() which may throw a cryptic runtime exception has been eliminated. Imagine how much easier it is to diagnose a "InputProcessItemException" than a cryptic off-by-one error inside calculate();




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: