Spring Annoyances and the Trouble with Big Frameworks
I'm going to pick on Spring a lot in this post because it has caused me the most frustration in the last few months, but the same arguments can be applied to many large and ungainly frameworks/libraries. This rant was sparked by trying to upgrade a production application from Spring Boot 1.1 to 1.2. It didn't work; it didn't tell me anything useful about why it didn't work; and the upgrade notes said nothing about the parts of the framework which are now completely broken (hint: ErrorController
).
There are many frameworks from massive to micro in the land of Java development. Spring is perhaps the largest and most mature of these. It provides libraries for just about everything these days with the promise that the many layers of magic should work together without too much developer pain.
But therein lies the problem. Spring is so large and fragmented that trying to use a few different Spring libraries together often exposes obscure compatibility problems. Sometimes things just work, but often the developer has to micro-manage the exact combination of specific library versions of their various dependencies in order to avoid bugs and rage-inducing compatibility errors.
Spring Boot steps in to solve this problem, repackaging many layers of Spring libraries and their dependencies as a single curated collection that works together, at least in theory. For the most part, Spring boot saves a lot of pain, but it is still subject to the same murderous upgrade path as the rest of Spring. The drill goes as follows:
- Change the dependency version in the build file.
- Compile and run all the tests.
- Swear loudly when it all blows up.
- Scour the release notes for the problem. Find nothing useful.
- Scream bloody murder at the Spring maintainers for breaking the world without documenting it.
With time and effort, these backwards compatibility issues can always be worked around, but there comes a point when I have to ask if it is worth the trouble. The JDK, such as it is, always maintains backward compatibility and all the parts work together in the same release. Spring's backward compatibility is shoddy at best and it can take a week to get two simple component libraries to work together.
Despite its merits, Spring Boot only seems to put lipstick on the pig while failing to address the underlying problems with Spring's many interdependent and frequently unusable libraries. I appreciate that the project tries to make Spring usable again. The frustration comes from it getting close enough to build a product with but not close enough to maintain said product without considerable effort.
In my own travels I'm starting to appreciate more the way JavaScript frameworks are going, building mini libraries for different tasks and letting developers pick and choose between them. Spring was once supposed to offer something similar, but has since grown into a many-headed hydra of cyclically interdependent magic boxes with inconsistent documentation and a 'throw it away and start again' upgrade path. Good application design will attempt to separate most of what the app does from the technology used to build it, but there is only so far this can go before the level of abstraction gets silly. Spring Boot can both help and hinder here, depending on how heavily it is relied upon and which layer of APIs the developer uses.
I look forward to the day when upgrading the technologies underlying an application is as simple as changing the dependency version numbers. For anything built with a big, complex framework that day has not yet come.