Subscribe to PHP Freaks RSS

10 Ways to Avoid Writing Crappy Code

by John Kleijn on Jul 3, 2009 10:15:32 AM - 21,733 views

1. Learn OOP and common OO principles

This is an absolute requirement. If you are still coding procedural, this is no small task. What are you waiting for?

2. Employ Test Driven Design

Code that is buggy or simply doesn't work at all can safely be considered "crappy code". TDD gives you the confidence that your code works, and the side effects force better and more flexible software design.

If you are not familiar with TDD yet, and this post has prompted you to try it, be warned: at first it will seem very cumbersome. What definitely will help is this piece of advice, which is at the core of Test Driven Design: don't write tests afterwards, write them first. Without going to much into the details, and somewhat simplified the general mantra is this: write a test first, make it work by writing the application code, refactor, write another test, make it work, refactor, etc etc. It's a cycle. The application code follows the test code, not the other way around.

I recommend PHPUnit. It has the most features and the largest adoption.

3. Refactor, refactor, refactor

Refactoring means "to improve the design of existing code". Making changes to code results in an increasing loss of quality of that code, this is known as "software decay". To battle this phenomenon, you have to constantly evaluate if the code hasn't lost its quality, and look for opportunities to improve the design beyond its original. But there's a catch. And it isn't the time that refactoring takes, if you do it properly you'll save those hours by having avoided software decay. It is the risk of change.

I can understand if you are hesitant to change code that works (at least for now). But this is where number two comes back into play: as long as you've written the right tests, you can make sure your changes don't break anything.

4. Simpler is better

Your mind should constantly be waging a battle between simplicity and flexibility. Avoid unnecessary complication.

5. Use Design Patterns

Design Patterns describe real world software design problem and solutions. Make sure you are familiar with them, buy some books. If you encounter a design problem that seems familiar take your trusty GoF and PoEAA from the shelf and look it up.

6. Don't Use Design Patterns

Once you are familiar with Design Patterns, or even just with the existence of them, it can be tempting to start sprinkling pattern implementations over your application code, just because you can. Don't. Remember a Design Pattern consists of a problem and one or more solutions to that problem. Until you have the problem, don't use the solution.

7. Accept the limitations of your language

Believe me, I know that as a programmer it is difficult to accept limitations on bending your code to your will, but trying to change the behaviour of PHP is not the solution. PHP has limitations, you'll have to live with them. If you try to "patch" them, chances are you will do more harm than good.

8. Pretend you are writing a book

It has been said that "code should be easy to read rather than easy to write". Maybe somebody else will need to understand your code at some stage. Maybe two years from now, you will revisit this code and need to re-learn its inner workings.

Semantics, meaningful docblocks and clear execution flow are everything. Imagine reading an instruction manual without pictures, filled with meaningless abbreviations, and with the pages in arbitrary order, without page numbers. That's how someone, maybe you, will feel if you ignore this advice.

9. Peer Review

Believe it or not, you don't know everything and you aren't always right. Nobody is. Getting a "second opinion" can only improve the end result.

10. E_STRICT is your friend

Make sure your code runs properly with E_STRICT turned on. Although, if you have gotten this far, I don't think that will be a problem.

11. Create a distinction between "source code" and a "build"

Even though PHP is an interpreted language, this is an important distinction in my opinion, even though practically noone employs this in the PHP world. A build in PHP is a copy of (part of) the source code, which includes assets like HTML, CSS and JavaScript, and is stripped of anything not necessary for running the application. Maybe your build is a Phar file, or maybe you have combined some source files into a single file (like the guys at Doctrine do). Maybe you can provide different builds of the same project to serve different purposes..

How does this help you avoid crappy code? It allows you to have the source code and build differ, avoiding any compromises you might be tempted to make to facilitate runing or developing the application. Bonus points if you allow the user to choose between placing everything in the server document root or just a bootstrap and the static files.

There are various build tools available, personally I use PHPUnderControl, which is a patch for CruiseControl and gives you a variety of build server features. It uses Ant by default, but I also use Phing.

Yes, there are actually 11 ;)


fenoglma Jul 4, 2009 8:41:28 AM

(grammar problem corrected)

John Kleijn Jul 4, 2009 9:01:05 AM

I have made the corrections. Believe it or not, I am aware of the difference. Thanks for the Peer Review ;)

Daniel Jul 4, 2009 12:54:32 PM

It must be a good text if the only criticism you have is a minor misspelling...

fenoglma Jul 6, 2009 9:24:20 AM

The "Use Design Patterns" and "Don't Use Design Patterns" made me chuckle; I've fallen into that trap myself sometimes. An analogous one is "Use Inheritance" and "Don't Use Inheritance". When you first introduce students to inheritance, they want to subclass everything. ;)

br3nn4n Jul 9, 2009 5:07:57 AM

Regarding number 1, where can I find this? I'm just really getting started making my code into classes and such, and it's all new to me. Any help is incredibly appreciated.

John Kleijn Jul 9, 2009 5:10:43 AM

You can start with some of my tutorials. Just click on my name, it'll take you to my profile. Unfortunately the diagrams are temporarily missing though.

plainjane Jul 10, 2009 8:34:45 PM

I don't have a clue what you are getting at in No. 11. Could you explain a little more clearly?

soft10 Sep 24, 2009 2:45:32 AM

'Don't Use Design Patterns'.I am not clear about this point.Please explain it.
Overall nice article.


John Kleijn Sep 24, 2009 5:09:26 AM


Because PHP code doesn't need to be compiled, most people just run the code they use for development. But what's handy for development isn't necessarily handy for running the application. A typical example of this is an application layout where all source code is simply dumped into the document root, which isn't such a good idea. When you distinct between "source code" and "build" you can provide different versions of the same application prepared for installation. This allows you to make changes like include dependent libraries, strip debugging code and comments or other optimizations that will improve running the code, but would a pain to do on the code you use to develop the application. Makes more sense now?


Not sure what I can say to make it more obvious. Simply put 5 and 6 just say "use, don't overuse Design Patterns".

s0c0 Nov 12, 2009 4:51:38 PM

fantastic. There are some other things I would throw in there such as: Write scalable code over optimized code. You can always go back an optimize a query or fix an arrays structure so you don't have to loop through it so many times, but to rewrite entire portions of code because they don't scale well with future requirements is a headache and time consuming.

Add Comment

Login or register to post a comment.