Before I get into today’s topic, a little flashback. Since December 29th, we’ve had 4 days with measurable snow. The first one, over 2 days was a wet, heavy (for Colorado) foot of snow, the other two were more typical front range snows, 2 inches of light powder. But it never got that warm and sunny, so it’s been building up. It’s also been melting and refreezing. Which reminded me of this post abut YAGNI. You ain’t gonna need it. Until you do, so be prepared.
Interestingly enough, this kind of relates to today’s topic as well. Backward compatibility is pretty easy to understand, and relatively easy to do. Essentially it means using a new format for your input, while retaining a way to recognize that your input is in some older format, then handling it correctly. The reason it’s easy is that you’re in control of all the variables You get to define the new format and how to handle it. You get to define how you’ll distinguish between the two formats. You get to define how to convert the old format into the new one. And the old format can’t change. Easy Peazy.
Forward compatibility, on the other hand, means defining your output in such a way that it works with code that hasn’t been written yet. That’s just a little bit harder. It’s not just that you’re not in control of the variables, it’s that the variable hasn’t been created yet. How can you be compatible with something that doesn’t even exist yet?
In the strictest sense, you can’t. There’s no way to be forward compatible in all cases. What forward compatibility really means is that you make some design choices up front that don’t constrain you (much). Instead, they put some very light requirements on the future. As long as the future follow those simple constraints then they’re backward compatible.
Consider HTML. The design of HTML and what browsers due with tags they don’t understand makes it forward compatible. It’s not going to be exactly what had hoped for, but older browsers can parse and display newer HTML documents, even if they include things like the
Communication protocols are often like that. Since you don’t know what you don’t know at the beginning you make room for learning and growing. If you’ve done any Windows system level programming, you’re probably familiar with APIs that take a structure that includes the size of the structure. That’s there for forward compatibility. It lets the receiver of the structure know what version it’s getting. While it might have been possible to determine it by inspection, adding the size of the structure makes it clear.
Another common way of making things forward compatible is by nesting things. Sure, you could have an API that takes 5 parameters, but if you add a sixth one then you need to not just rebuild everything, but in many languages, you need to change the code to add that 6th parameter, even if you’re going to go with the default value. You can make that forward compatible by passing that info as a unit (think C structure). If the definition of the structure changes, you might need to recompile the code, but you don’t need to change anything. That’s what the folks building the Windows API did, and it certainly worked for them.
It’s also important when you have a distributed system and need to transfer data from one computer to another over a wire. In many cases you have no influence, let alone control, over the computer that is sending the data. You need to come up with something that is extensible and forward compatible. Enter Protocol Buffers. Designed from the ground up to be both forward compatible and extensible. Follow the guidelines and you can add lots of extensions without impacting existing users. Send a newer version of data to something built with the old definition of the schema and it will happily ignore data it doesn’t understand.
That doesn’t mean you can ignore the issue. You still have to make sure that you don’t make breaking changes. You still have to make sure that ignoring the new data makes sense and gives reasonable answers. But you can do all that in the new code, where you have control and the ability to change.
You just have to think ahead and make sure you can accept those changes. Just like you need to plow a little bit wider than you need now, because something is going to change in the future.