Pseudo-Productivity In Java

I do like Java, and I'm sure that is an unpopular opinion in Geminispace. But I have noticed a side-effect of its verbosity that frustrates me to no end. While in a well applied form, the verbosity of Java can serve to make code that is fairly immediately obvious and "self-documenting" to a degree. This is a large appeal to me when writing business software, where I cannot guarantee every pair of eyes on the code is competent or capable as a programmer. This verbosity however has a counterside to it when used by those aforementioned people.

A lot of Java programmers seem to fall into habits that they themselves don't even think about. I'm sure this happens plenty across language boundaries, but never have I seen it more obvious than in a Java software stack. Everything must be separated into "Controller -> Server -> Repository", which each having their own interface that is implemented once and only ever once. It's a madness that is only overtaken by the insanity that occurs within C# software stacks, and the generally outlandish code I have encountered in Microsoft shops.

All of these weird design patterns and overreliance on habit can make it appear like you're doing a lot, when in fact you have written extremely little.

Do You Need A Contract?

To start off, let's discuss the overuse of single-implementation interfaces. Interfaces, for anybody who does not know, are types that define a contract an object must implement. They also, in modern Java, define default methods that can utilize that contract to build a nicer API without relying on every implementation to also add them. The benefit of interfaces is obvious: You do not have to reference a concrete implementation of a concept, only the concept itself. If I define a "SortAlgorithm" interface, I can use any concrete algorithm as I need without any restructuring.

But this also leads into the madness: If there is a single implementation of an interface, the interface need not exist. Over-architecting your software by doubling your file count to interface every concrete class does nothing but add noise. That service, until told otherwise, will always be the only service implementing that interface. And if that turns out to be untrue extracting an interface and adjusting your application should be a short endeavor. If not, that is a sign of your application design failing, not of a need to pre-define interfaces.

If you need a contract to allow multiple concrete implementations of a concept, use an interface. But don't assume everything you write will require this.

What Does This Service Do?

The service pattern in Java applications, notably JEE and Spring, seems extremely misguided. Service patterns seem to commonly build an abstraction that breeds single method call chains, where either the service is just a wrapper for a repository call, or a controller is just a wrapper for a service call.

I'm not even sure what this pattern is attempting to solve. Controllers should operate as a list of higher-order operations to satisfy a request, and produce a response. This definition encompasses at least 80% of service classes I have encountered. A service class may make sense to abstract interaction with another... service, or to box complex behaviors that multiple controllers may need. But to always add them as a default layer, even if they end up doing nothing but being abstractions for the sake of "best practice", is bizarre.

It's Not Java 7 Anymore

A small tangent, but the amount of people who still program as though Stream<>, Optional<>, and other very helpful things aren't present in the standard library is astronomical. It's a replay of those people who stopped learning after high school, except now they're considered "skilled labor".

Switch expressions, record classes, and the aforementioned Java 8 features have done a lot to make Java an ergonomic and effective tool in writing high-level applications. To avoid them or ignore them because you can write it "how you know" is a disservice to yourself, and your coworkers. Furthermore, it is not everybody elses job to educate you and bring you up to speed. This information is public, available, and well documented. Take a day and learn something new.

The Illusion of Productivity

As a result of all of these aforementioned design issues and poor code patterns, I encounter people who appear and feel productive when they aren't a lot. By following these patterns blindly, they write an unfathomable amount of code that boils down into almost nothing of substance. Perhaps this is a side effect of companies who measure productivity by lines/words of code written, I do not know. But I do know that these design patterns build unfathomable machinations, and it leads to a quick and inevitable slowdown and blockage of development as people can no longer easily understand where a concept or feature belongs, or what the application is doing.

Then, as programming becomes too difficult, meetings are scheduled so that people can still feel productive without actually doing work. Which inevitably leads to business being confused as technical teams "work so hard", but so little gets done. And then things get pushed back, technical staff burnout and perhaps leave, until its approved to "start fresh" or "stop and refactor", and the cycle continues.

Conclusions

I am certain that the overlying issue, that of over-architecting and bad design leading to bad code, is omnipresent in the industry. That much is obvious to anybody with the knowledge to analyze software. However, this article remains specific to Java for the simple fact that I have never seen such an aggressive overuse and misuse of design patterns in another tech stack. Perhaps I just got lucky previously, however.

The truest conclusion is obvious though: Don't overuse patterns and tools without knowing what they are for. A "best practice" is only one when applied to the problem it is meant to solve, and unilaterally applying them does nothing but add cruft. Over-architecting an application doesn't build a better application, it adds places for poor code to hide. Your application must prioritize clarity and simplicity over any other "best practice", unless another requirement such as performance exists.

But whatever you do, don't add undue noise to an application, to feel productive or otherwise.

=> Back to Index

Proxy Information
Original URL
gemini://jun.skein.city/journal/software/pseudo-productivity-in-java.gmi
Status Code
Success (20)
Meta
text/gemini
Capsule Response Time
564.388661 milliseconds
Gemini-to-HTML Time
0.664875 milliseconds

This content has been proxied by September (ba2dc).