Tom Butler's programming blog

Hazard 4: You are not clairvoyant

This is part 4 of my guide to writing better code

Warning signs

You have become stuck in this hazard if you write code:

  • That cannot be used on a different website without modifying a single byte in the file
  • Assuming that it does not need to be changed in the future
  • Couples logic that's useful on multiple projects with logic that's only useful on the website you are currently working on
  • Assume you're not going to need to do something

The root of all (programming) evil

This is fundamentally the argument against all programming "bad practices". You have no way to know how things are going to change in the future and if you write code expecting no changes to be required you get caught out when they do.

In theory your boss saying The site needs to be moved from joomla to wordpress or Symfony to Zend should not invoke horror. If your code is written in such a way that it is not tightly coupled to the framework the move should only involve changing the way the framework interacts with the business logic, a somewhat painless job.

That's not true for most code, and why most code is crap. Most frameworks are designed in a way that makes it near impossible to move code from one to another. 90% of everything is crap, code included.

Anything you do that makes your code more difficult to modify, move between projects or ties you into a specific library is a problem. Symfony might be popular today but it's only in the same position that CakePHP and CodeIgniter were several years ago.

How many times have you had to work on legacy code (insert horror movie scream) and find it overwhelming difficult? Often it results in a complete rewrite using the framework du jour. In 5-10 years someone looks at your code, calls it legacy and the same thing happens.

Writing inflexible code is the enemy of all programmers. Singletons, Inheritance, Static Methods, Global Variables, these are all bad because they make the code difficult to change in the future

When you use global variables and singletons you assume you'll only need a single value/instance. As soon as that's no longer true your code is fundamentally broken and needs rewriting.

These assumptions about what the code will or will not need to do in the future are the root of all evil in programming. There is no way for you to know.

Code is almost never finished

This is true for a lot of software developers but especially true for web developers. You build a site, you put it live. You are not done. Over time you need to add new functionality, update the site to fit new business requirements and keep it up to date with the latest security practices. New versions of your scripting language or database may come out and with them, new best practices and broken backwards compatibility.

Like it or not, you will need to keep working with the code and making changes to it. The more difficult the code is to modify, the more difficult your job is. As such, "bad practices" are practices which make modifying existing code more difficult.

If your code is adaptable to changes, it makes working with it easier and you as a developer more efficient. Anything which makes your code difficult to modify is considered bad practice.

Code can be copied

Unlike a sculptor or a baker, you can reuse anything you've built before. You can take a website as-is and change it into a new website. In fact, that's the workflow of a lot of developers whether your base website is the default Wordpress install or an empty Smyfony framework, you're taking what's been done before and using it.

Because of this, and this is a point I stress to all my students, when coding anything don't just think about the website you're working on today but consider websites you may be working on tomorrow. If you're building a shopping cart, that functionality will be useful on a lot of websites. Anything you do that locks it in to the

Copy files, paste, modify

When you reach an intermediate level and have a few websites under your belt a common workflow is taking the last site you built, copying all the files, pasting them to the new site and then changing them to fit the new requirements.

Your files contain code that's useful on both the current site and the other sites. You can change all the database field names, the HTML to brand each site but this is a problem.

If you find a bug while working on the new site, you can't just overwrite the file containing the bug on the old site (or last ten sites you built) because each of the files is subtly different.

If you cannot take a file and use it on another website without modifying a single byte, any code in the file is not reusable

Database table names, database column names, strings of text, anything that is different on different sites should be a variable and separated out from the underlying logic.

This is a point which I repeatedly hammer home in my book. Separate out anything that's specific to one site from anything you can use on multiple sites. Anything that is useful on multiple sites should be able usable on multiple sites without modifying a single byte in the file

This is the main sticking point that prevents people fully grasping OOP and moving to Milestone 1.

"But I'm not going to need that"

"But my dependencies aren't going to change"

"We'll always be using a MySQL database"

"This page will always run on the URL /products/"

"I don't need to be able to substitute the validation"

"We'll always use Symfony's router"

"Wordpress will always be supported"

Any assumption you make and express in in your code prevents you from reusing the code on future projects.

Conclusion

All those best practices you hear about exist because people have realised that these kind of assumptions cause problems. There's no way to know what your code is going to need to do tomorrow or in five years time.