Adam Culp posted the 3rd article in his Clean Development Series this week, Dirty Code (how to spot/smell it). When you read it, you should keep in mind that he is pointing out practices which correlate with poorly written code not prescribing a list of things to avoid. It's a good list of things to look for and engendered quite a discussion in our internal Musketeers IRC.
Comments are valuable
Using good names for variables, functions, and methods does make your code self commenting, but often times that is not sufficient. Writing good comments is an art, too many comments get in the way, but a lack of comments is just as bad. Code can be dense to parse where a comment will help you out. They also let you quickly scan through a longer code block, just skimming the comments, to find EXACTLY the bit you need to change/desbug/fix/etc. Of course, the latter you can also get by breaking up large blocks of code into functions.
Comments should not explain what the code does, but should capture the "why" of how you are solving a problem. For example, if you're looping over something a bad comment is "// loop through results", a good comment is "// loop through results and extract any image tags"
Using Switch Statements
You definitely should not take this item in his list to mean that "Switch statements are evil." You could have equally bad code if you use a long block of if/then/elseif statements. If you're using them within a class, you're better off using polymorphism, as he suggests, or maybe look at coding to an Interface instead of coding around multiple implementations.
Other code smells
In reviewing the article, I thought of other smells that indicate bad code. Some are minor, but if frequent, you know you're dealing with someone who knows little more than to copy-and-paste code from the Interwebs. These include:
- Error suppression with @. There are very, very, very few cases where its ok to suppress an error instead of handling the error or preventing it in the first place.
- Using globals directly. Anything in $_GET, $_POST, $_REQUEST, $_COOKIE should be filtered and validated before you use it. 'Nuff said
- Deep class hierarchy. A deep class hierarchy likely means you should be using composition instead of inheritance to change class behaviors.
- Lack of Prepared DB Statements. Building SQL queries as strings instead of using PDO or the mysqli extensions' prepared statements can open up sql injection vulnerabilities.
- Antiquated PHP Practices. A catch all for things we all did nearly a decade ago, includes depending on register globals being on, using "or die()" to catch errors, using the mysql_* functions. PHP has evolved, there's no reason for you not to evolve with it.
That's generally what I look for when evaluating code quality. What are some things I missed?