A decade ago, when I started at ING (my previous job), I was placed in a team that used TIBCO Businessworks for its development. With Businessworks, TIBCO (The Information Bus Company) provided a mostly graphical way to program applications. As a “programmer”, I had to create flows by placing different building blocks, represented by colourful icons, in a diagram with arrows connecting them, a bit like UML. These icons represented different pre-made functions, such as database interfaces and network connections.
When connecting two icons, a table appeared below the diagram in which you had to connect all the different fields. I spend most of my time in those tables. TIBCO would allow inserting actual code here and there, but this was never needed. This is what is called a low code environment.
Where was the fun in that?
After two or three sprints, I knocked on my manager’s door and asked him to transfer me to a team that did actual coding. As it happened, he was at that moment creating a new team with Java developers that I could join. That team had to create new APIs from scratch, so I was happy.
Continuous improvement
Call it my fixed mindset, but I feel Businessworks and other such environments make programming boring and more tedious than necessary. Dragging icons and filling out tables feels more like configuring than programming. Programming is writing maintainable code and creating elegant solutions.
Even when you have to create the same code over and over again (so-called boilerplate code) every time you do, there is a chance to improve on what you created last time. If millions of programmers worldwide, all thoroughly aware of HTTP, JDBC and other specifications, are creating so-called endpoints to have systems talk to each other, you’d imagine a world where both these specifications and their implementations would get better all the time.
We do not live in that world.
Instead, while twenty years ago, at university we were taught how HTTP works by having to create our own protocols from scratch, we now live in a world where millions of developers work daily with the protocol without knowing the first thing about it.
Spring
Spring is a framework for Java, Groovy and Kotlin that replaces boilerplate and other code with its own patterns, abstracting away that which otherwise would be repeated code. But what it ignores is the fact that corporate code spends >90% of its life cycle in maintenance, maintenance that is done by someone new in a team while those who created the code in the first place moved on years ago.
Spring uses something called Convention over Configuration to keep things simple, but intransparent to whomever isn't aware of the convention. Spring has code injection, interceptors, declarative configuration, overrides and sane, but changing, defaults. It is Spring that is deciding how and when to execute each part of your code and while that makes coding fast, it does so at the expense of maintaining it, because it becomes impossible to follow a flow by reading the code.
Rapid development
The other day, I explained to a colleague that this is partly why I use Linux instead of Windows and Arch instead of Ubuntu. It takes more time to install, but if something breaks, I know what it does and why I put it there, so I can fix it. It is also one of the main reasons for me to ride a mechanical bike instead of an electrical one. I can maintain it myself, even if it takes more time and effort to get to my destination.
This is precisely the problem that I felt with TIBCO Businessworks. Spring is clearly moving Java toward a low code environment as well, where focus is with rapid development, ignoring maintenance. Generating code based on specifications and using LLMs to write the rest doesn’t exactly help.
Take the following fragment and take a guess what it does.
spring: application: name: my-application cloud: function: definition: myFunctionNeither did I, but this isn’t code. It’s a declaration, which has very little meaning by itself. There are other lines at different points in this and other files that make it so that a function called MyFunction is triggered, in this case, when a certain type of message is received. From the fragment alone, there is no way to find that out without knowing it already.
Risks
To even be able to write the above, you either have to go through quite a lot of documentation, or ask an LLM to write it for you. If the result doesn’t work as expected, you have no choice but to inspect Spring’s code itself to see how it handles your configuration, ignoring the point that the functionality was abstracted away from you in the first place so that you didn’t have to spend time on how it worked. If you had asked an LLM to write it, someone else wrote it, or you found a badly documented example online, you will have no idea where to start.
When debugging a failing test, a colleague (not in my team) actually suggested to fully recreate the entire API, since that would be faster. Though I didn’t, she was probably right.
Spring is open source but primarily developed by Broadcom, which you also know and love from VMWare. It is modular, and since, again, not every coder is intimately aware with HTTP and other important specifications, I’m not against using it here and there, but just as with LLMs, if you use it for one thing, you run the risk of outsourcing more and more of what you once did yourself. Spring has modules for nearly everything you need. And with that, you lose control, the ability to improve code, you make understanding code difficult and you slowly erode your own ability to program.
Also, it takes away the fun of coding.
.png)
