Discussion on boilerplate for code tightly bound to OOP
Julian Waters
tanksherman27 at gmail.com
Thu May 12 03:56:25 UTC 2022
(cc'ed to amber-spec-observers at openjdk.java.net)
Hey everyone,
Previously I submitted a post for discussing potential new ways to reduce
boilerplate in Java for all sorts of applications, ranging from simple
experiments a newcomer to the language may create to large and complex
systems in production (
https://mail.openjdk.java.net/pipermail/amber-dev/2022-April/007303.html).
It's been pointed out to me that the issue hasn't been properly defined
though, so I'd like to discuss that here instead, without jumping the gun
like in the previous post.
The problem is something that Java's had for quite some time, and is one of
the main issues that earns it quite a bad reputation[1] amongst developers
(Even if some of that disdain is outdated and has already been rectified in
newer Java releases)- The language is simply too verbose/has too much
boilerplate, and Java code itself is too tightly linked to classes[1] (at
least on the semantic level; Languages like Kotlin support other paradigms
like functional code even though they ultimately compile down to Java
classfiles).
Of course, like I did mention above, quite a number of these issues are
already being tackled (records, accessors for arbitrary classes, talks
about deconstructors, with expressions, future reified generics, potential
operator overloading in Valhalla with values and primitives), which is a
great thing, but Java is still having trouble catching up with modern
developer expectations and other languages as a whole. While many of these
complaints are often fueled by hype and personal opinion and provide no
constructive value as feedback whatsoever, there are still many salient
points to address, in this case it's how the language is too forceful with
OOP.
It's not much of a secret that if one wants to write simple, procedural
Java, they have to fight the language substantially to do so. Classes have
to be marked as final, their constructors privated and made to throw an
exception if reflection is used on them anyway, and every method has to be
marked as static. At first glance, this might just seem like a mild
inconvenience and one would wonder why this is an issue, but this becomes
incredibly repetitive and frustrating when made to scale, which will
undoubtedly drive developers off when considering it as a language of
choice (Even with a simple "Hello World" jar, many newcomers are often put
off with how much code is required, which is the last thing we'd want to
happen). Much of this extra verbosity from having procedural code (unlike
with statically typing a variable or a method's return type for instance)
is also a tradeoff without any benefit as well, and there doesn't seem to
be much of a reason to make developers pay such heavy penalties if we can
help them out with new language features, even more so since "mutating"
value classes was already considered too painful in the amber drafts (Also
from[2] "You get more typing practice?" "The shares for keyboard
manufacturers go up?" "You can sell software to generate this <Expletive
omitted> automatically?").
It could be argued that this could all be avoided by embracing OOP
entirely, which is certainly one of Java's biggest strengths, but there are
many instances where the procedural approach would be significantly easier
to implement the program's logic in (think the number of Java codebases
that have static only utility classes), or where forcing OOP would actually
degrade both code quality and performance (deeply nested chains of object
pointers or pointless object allocations for instance). There's also
another problem in that this forceful approach also causes newer developers
to learn rather harmful and over-the-top notions of OOP and how everything
must be a class and object- To the point that there is even an entire talk
for how to unlearn the rigid and incorrect concepts of OOP for people
coming to other languages from Java[3]. Given how popular of a language
Java already is despite the number of complaints against it, we should be
careful to not be the ones responsible for "poisoning" individuals new to
programming with the idea that everything has to be in a class- This does
no one any favours, not us, nor the learning programmers who may end up
harming the ecosystem at large once their assumptions are deeply rooted.
Maybe Java's current verbosity when it comes to procedural code could still
be an advantage for enterprise applications, where being as explicit as
possible with boilerplate can be helpful when reading a codebase, but that
would be a rather shortsighted view. It would be favourable for Java to
become a well liked choice for general purpose utilities such as regular
desktop applications or quick and small ones written out of convenience for
instance, and limiting it to enterprise-only would make its ideal users
only a very specific group- Not good if we want it to stay competitive. Not
to mention that a new language feature for facilitating procedural code can
indeed be explicit without much of the boilerplate of static only
classes, if designed properly. This would also help in hiding the
implementation detail of ultimately compiling down to classfiles, bypassing
the issue mentioned above entirely, since to the developer there is
technically no class involved whatsoever- Just methods. You could even get
IDE support for checking whether reflection attempted to call a constructor
at compile time too!
In the end, it certainly doesn't help with Java's image (and potential
newcomers to the language) that a common view of it by many developers out
there is that it's reluctant to include newer language features
because "<Expletive
omitted> you, I'm Java"[2], which is a reputation we can do without, and I
feel that this discussion would be a good place to start in dispelling that
view of Java that many developers have today.
best regards,
Julian
P.S. On an unrelated note, personally I feel that it'd be slightly better
if "with" expressions were declared with a -> or with any other existing
keyword instead of reserving an entirely new one for this purpose. I
digress however, this is just a personal viewpoint.
Links:
[1] https://www.youtube.com/watch?v=m4-HM_sCvtQ&ab_channel=Fireship
[2]
https://www.reddit.com/r/learnprogramming/comments/1cv8rb/why_does_java_get_such_a_bad_rep/
[3] https://www.youtube.com/watch?v=o9pEzgHorH0
More information about the amber-dev
mailing list