Many developers cringe at the idea of having to introduce new technology into an existing application. This is often the case even when the developer has previous experience with the technology, be it moderate or extensive.
For the sake of simplicity, let’s start by limiting our discussion to software. Things like libraries, frameworks and any corresponding infrastructure – think Google App Engine or Elastic Beanstalk for a Java web application or the backing message queues for message publishing.
So why do we feel some anxiety when it comes to these things? It’s not because we’re averse to using new tech. Good developers love using things that make their lives easier. Now it’s true that even good developers are susceptible to inappropriate Not Invented Here thinking. But I would also argue that for seasoned software professionals, experience has often taught us the hard lessons of using these solutions and there are many times where the right solution is one you write yourself, whether it’s because the options are costly or otherwise lacking in some significant way.
But if we read about something new, can see its potential and can envision it fitting in our software stack, our preference would be to incorporate it quickly and easily so as to simplify our day-to-day lives.
But the reality is that introducing a new library or framework is often very painful and time-consuming despite the fact that it is meant solve problems for us, not give us new ones. This can still be the case just in upgrading to a new version of an existing piece of tech; in fact, this is often worse than the initial implementation. If the designers and authors of these things intend to solve problems for us, why is the actual adoption so challenging?
I’d like to focus on just two of the more common reasons. In my next post, I’ll focus on what those of us that are behind these technologies can do to mitigate or eliminate these issues. We won’t bother discussing the most obvious one, bad software; it exists and we’ve all experienced it, but we should just reject using those.
So let’s start by discussing documentation. Documentation is one of those things that developers generally dislike writing and yet we rely on so much. Reading the introductory or marketing material sells us on the tech, but it’s the documentation that it makes it usable and useful.
Sometimes the documentation suffers because it’s an afterthought. Most of the team’s efforts are put into completing the initial release or adding new features. Despite it having great features, perhaps even being our best choice, we’re often left relying on other public sources of information to adopt it and we seem to be fighting with it every step of the way. In some of the worst public projects I’ve been exposed to, the documentation was so bad, yes, because it was an afterthought, but also because they just implemented new features or made significant changes without tracking anything. So they didn’t even completely know what documentation needed to be written or updated. You might assume that the release notes were close to non-existent or useless and you’d be right.
Other times though, it’s the culture of the team that prioritizes features above all else. In those cases, even if there are members of the team that want to write high-quality documentation, they’re not given the opportunity to do so or there is little concern for the end-user. As a result, whatever is produced ends up being low-quality and likely provides the reader with inaccurate information that can be worse than not having any documentation at all.
The other big issue we often encounter are breaking changes. And coincidentally, these are often made worse because of poor documentation. I will admit that there are times when breaking changes are unavoidable. But it seems to have become all too common to introduce breaking changes without providing an identified corresponding upgrade path, or if it is, it’s not reasonable as it essentially amounts to a rewrite. Sometimes too, breaking changes are introduced without good reason. For example, in applying one recent JavaScript library upgrade, a breaking change that was introduced was completely unnecessary; someone decided to swap the order of the two arguments for an event handler.
Lamentably, some projects introduce breaking changes because they made poor decisions during an earlier design cycle and do not want to put forth the effort to correct them in a way that keeps us, the consumer of their tech, in mind. They implement a completely new approach that they feel corrects their previous error(s) with what feels like complete disregard for the upgrade path. This results in low adoption rates due to high costs and low return. It also results in suspicion of the team behind the tech. If they lacked the experience and made decisions the first time that couldn’t even be salvaged, why should we trust them now? Are they going to do the same thing with the next major version? How much time am I going to continue to spend just to keep current with their tech?
So what is to be done? It’s easy to say write better documentation and don’t introduce needless breaking changes. But doing so is more complex than that. Stay tuned for my next post that will dive into how we can meet those challenges properly.