Pippin Williamson of pippinsplugins fame did a presentation on backwards compatibility and WordPress plugins at LoopConf. In the presentation he showed a couple of examples of where developers have a tendency to break backwards compatibility. In this article I will give my thoughts on what he said and also give some ideas on how you can prevent breaking things in the first place.
Hide how things are stored
In the presentation Pippin gives an example of get_post_meta and changing the key used for storage or how its stored all together like a taxonomy or separate table.
This is not information that should be available to the developer. The developer should not know how things are stored or even have to care. It is not something they in most cases need to know. The value should be accessed using a wrapper function or be a property of a class. Some developers make the case that developers should not know about the classes themselves and argue that only basic structures should be used to communicate data, such as stdClass, arrays and so on. Instead of returning a class with properties you return an array representation of the information. A minimal class without functionality and with public properties can also be used. This has the advantage over arrays and stdClass of providing autocompletion when using code editors. They are also easier to document.
Don’t encourage direct inclusion of files
If it's possible, try to use autoloading of your classes. You can also add a wrapper function that includes a file containing functions since functions cannot be autoloaded. The files should preferably be included by default on load. Doing require_once on all the plugin files is not a recommended approach and its not something developers should do on your plugin files. If you have to use require_once to include files you have a bad structure in your plugin or theme. Having a wrapper function to include files and also discourage use of require_once? Yes, well I like paradoxes. Run tortoise run.
Don’t hard code any HTML code in your plugin
Pippin says to be careful with HTML structure in plugins since you can break extensions later on if you change the tags and so forth. However there are ways to minimize this risk. One way is to provide filters for wrapping tags etc if you are for example showing a list.
Tag inclusion can be used in conjunction with actions as well.
Of course the above method does not work if you go from one column of data to multiple columns of data. Such as going from a list with a single value to a table with a two column layout with more data displayed. One way to handle variable columns is to use a placeholder system. This works as long as the objects to display all adhere to the same contract. I personally loath plugins that print hard coded HTML. It's my data. I should decide how it's displayed.
If a theme, plugin or you have changed the tag for that list to a div now you have breaking HTML. Instead try to make use of events so you can better separate the various parts of your code to separate files. It also enables any themes or plugins to remove your default DOM manipulating code and replace it with their own. Of course this is a two-edged sword. To separate responsibilities you can make use of jQuery trigger() and on() functions.
Write unit and functional tests
Write acceptance tests
Let the developers know
Write good documentation of your code and how its meant to be used. If certain class properties are meant to be read only use @property-read. If a class or function is meant only to be used by the plugin itself mark it as internal. If developers disregards the instructions that is not your concern. Provide the developers with a best practice extension so they can see how things are meant to work.
If you foresee breaking changes you can do as Pippins says in the talk and introduce the changes version by version. It all depends on what kind of changes you are making. This of course relies on the end users actually updating the plugin to each version in the first place.
When backwards compatibility can’t be kept
Depending on how big the changes are you might be better off forking your own plugin or theme if the changes are really big. If you do not want to do that and still want to make bigger changes don’t rely on the default update functionality in WordPress. Hook into it and give users a step by step form to complete inorder for the upgrade to be made. You know what version they are upgrading from and can adjust accordingly. You can also present a screen with the changes before upgrading that they need to accept. This of course relies on you having added these capabilities to your plugin beforehand.
The main thing is to write tests for your code and try not to hardcode things. Remaining backwards capable and having a good structure in your code goes, from my perspective, hand in hand. If you have good structure you can also make bigger changes if the need arises. Writing more complex functionality sometimes requires you to do some thinking before you get going. Especially if you write code that you think people will expand upon with new functionality.
If you have comments or other ideas on the subject of backwards capability and code structure please leave a comment I would love to learn more about it. If you think my thoughts on the subject are completely bonkers I don’t mind hearing about that as well. Just try to do the shredding as politely as possible.