Blog: 10 Ways to Avoid Writing Crappy Code


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 ;)