Why upgrading software libraries is imperative
Image by Tolu Olubode on Unsplash
Applications primarily run on front- and back-end programming languages, including library dependencies. Operating systems and programming languages can be periodically updated to run on the latest version, but what about the many libraries being used in the app’s front and backend? As we all know, it can be quite a daunting task to maintain and individually update a long list of software dependencies like the examples later in this post. Still, it is important to keep them updated.
This post dives into our experience upgrading a complex app with a full software stack and lots of dependencies. We’ll examine the benefits of upgrading, what you will need, and how to go about such an upgrade as simply as possible.
The app in question contained decade-old software and included extensive libraries when we received it from our client. The app used languages including Java, Scala, Kotlin, and JavaScript along with many libraries. The initial plan was to upgrade the complete software stack and libraries all at once due to the gap between versions. This proved to be more difficult than expected due to a host of deprecated and removed functionality as well as interdependence of a few of the libraries.
Conflict approach: “Don’t update unless you have to”
While this can be sustainable in the short term, it quickly becomes less applicable in the long run. One important purpose of updates is to (hopefully) protect from new vulnerabilities and cyber attacks. Scenarios arise where particular library fixes are implemented on the latest version, yet require upgrading other libraries to the latest version in a chain. Because upgraded libraries need extensive testing and preparation for new issues, this directly impacts whether the app attempts to resolve an issue.
Therefore, smaller and more frequent updates are more sustainable in the long run. Larger and less frequent upgrades will not only result in unexpected errors, but also require more complete regression testing to deliver a bug-free update. The following reasons justify the necessity of software and library upgrades:
- They apply timely security patches to reduce vulnerabilities and defend from cyberattack
- You can identify deprecated functionality earlier and use alternatives
- They can apply fixes for known bugs in the library
- They’re based on the latest versions of software or library, encouraging stability
In addition, staying on the latest major version yields the benefit of applying minor and patch releases seamlessly without risk. Most software and libraries use semantic versioning, formatted as MAJOR.MINOR.PATCH:
- MAJOR version - Incompatible API changes
- MINOR version - Add functionality with backward compatiblity
- PATCH version - Bug fixes with backward compatibility
So being on the latest major versions of libraries allows applying minor and patch releases without breaking existing functionalities of the app.
Benefits
The benefits of keeping software and libraries updated include bug fixes, new features, boosted performance, as well as better stability, compatibility, and security measures. We can often ignore upgrades in projects because we don’t perceive significant effects in appearance or usage. But on closer inspection, frequent updates deliver important advantages.
Real-time difficulties
In real-life scenarios, bug fixes and performance optimization of an app often take a higher priority than upgrading libraries. In many cases, this results in a discrepancy between the app’s version and the current version. This discrepancy can lead to the following issues when upgrading libraries:
- Unexpected error handling in new releases
- Unexpected unsupported library dependencies
- Need for complete end-to-end testing due to major version of library upgrade
- Lack of work being visibly completed can lead to a lack of confidence from client
- Difficulty in estimating workload due to major unexpected errors
The following passages offer guidance in how to adequately prepare for these issues.
Get prepared
Much can be learned from preparing for a major upgrade on both a business and technical level. First, a complete list of libraries from the entire app should be compiled. This list should include the latest and current version of the library in the app. Reviewing the changelog of both versions will help identify potential incompatibilities or problems. Visiting the “issue report page” of the library to monitor any version-specific issues is also recommended.
Once you’ve adequately prepared the libraries for upgrading, you can use any method of your choosing to upgrade and maintain the list. Once the roadmap is established, upgrading can commence and compatibility issues that arise can be dealt with as they arise. Finally, thorough end-to-end testing is necessary once the upgrade process is complete.
Below are some examples of software lists you might have for a project (we left out the latest versions for brevity in this post, but it’s helpful to have a column for those too!).
Programming software & servers
Software | Running | Release date |
---|---|---|
Ubuntu Linux | 12.04.5 | 2017-04-28 |
nginx web server | 1.12.2 | 2017-10-17 |
Jetty Java Servlet container | 9.2.3 | 2014-09-05 |
JVM/Java | 1.7u79 | 2015-04-14 |
Scala | 2.11 | 2014-04-21 |
Kotlin | 0.9.223 | 2014-10-23 |
Lucene | 4.10.0 | 2014-09-03 |
PostgreSQL database | 9.3.10 | 2015-10-08 |
Java libraries
Software | Running | Release date |
---|---|---|
joda-convert | 1.3.1 | 2013-03-01 |
joda-time | 2.2 | 2013-03-01 |
play-json | 2.7.0 | 2019-01 |
httpclient | 4.1.2 | 2011-07-10 |
httpcore | 4.1.2 | 2011-07-22 |
httpmime | 4.1.2 | 2011-07-29 |
commons-codec | 1.3 | 2005-10-01 |
jooq | 3.1.0 | 2013-06-30 |
jooq-codegen | 3.1.0 | 2013-06-30 |
jooq-meta | 3.1.0 | 2013-06-30 |
jtds | 1.3.0 | 2012-10-27 |
servlet-api | 3.1 | 2013-04-25 |
play-json-joda | 2.11-2.6.9 | 2018-03-01 |
lucene-core | 4.10.0 | 2014-09-02 |
lucene-memory | 4.10.0 | 2014-09-02 |
lucene-queries | 4.10.0 | 2014-09-02 |
lucene-queryparser | 4.10.0 | 2014-09-02 |
lucene-highilghter | 4.10.0 | 2014-09-02 |
lucene-analyzers-common | 4.10.0 | 2014-09-02 |
postgresql | 9.2-1003-jdbc4 | 2013-05-27 |
jsoup | 1.7.3 | 2013-11-11 |
jetty-util | 9.2.5.v20141112 | 2014-11-12 |
tika-core | 1.16 | 2017-07-07 |
commons-fileupload | 1.3 | 2013-03-24 |
commons-beanutils | 1.6 | 2005-11-08 |
commons-collections | 2.1 | 2005-11-08 |
commons-digester | 2.1 | 2010-09-24 |
commons-io | 1.1 | 2005-11-24 |
commons-lang | 1.0.1 | 2005-11-24 |
commons-logging | 1.0.3 | 2005-11-17 |
commons-validator | 1.0.2 | 2005-11-24 |
slf4j-api | 1.6.4 | 2011-10-31 |
slf4j-nop | 1.6.4 | 2011-10-31 |
JavaScript libraries
Software | Running | Release date |
---|---|---|
angular | 1.2.11 | 2014-02-03 |
jQuery | 1.10.2 | 2013-07-03 |
calendar | 1.51 | 2005-03-07 |
calendar-setup | 1.25 | 2005-03-07 |
fckeditor | 2.6.11 | 2014-06-02 |
dom-drag | — | 2001-10-28 |
jt_DialogBox | 29 | 2012-08 |
jt_AppDialogs | 9 | 2005-05 |
ng-grid | 2.0.7 | 2013-06-07 |
ng-grid-flexible-height | 2.0.7 | 2013-06-07 |
ng-grid.css | 2.0.7 | 2013-06-07 |
Recommendations
Once the app’s software stack and libraries are up to date it’s important to regularly update. The complete upgrade experience can be a rigorous and involved process that includes juggling numerous issues and intensive testing.
From a client’s perspective, a major upgrade project often doesn’t obviously demonstrate improvement to appearance or function. Because it is not recommended to keep outdated software and major upgrades (such as the one described above) are tedious, the following update options are preferable in order to keep software libraries as up-to-date as possible:
- Interval Based: Particular interval periods are implemented to check versions of software. This minimizes frequency of problems while ensuring a manageable gap between the current and latest software version.
- Module Based: Whenever work is performed on any module for new features or bug fixes, software and library versions are reviewed. This allows for relevant libraries to be updated, tested, and deployed along with development changes within the module.
Conclusion
Even if new features and improvements are not pertinent to the new release, frequent upgrades to software and libraries are crucial in order to ensure the most secure and debugged versions. Please feel free to share your methods of managing software updates in a comment!
Comments