The first time I learned Java was during the first semester of my undergraduate studies. My perception of Java at that time was that Java is essentially C with some object-oriented principles. It was challenging for me to grasp the concept of everything being an object. It felt strange; I thought they were aiming for something akin to “Everything is a File” rule in Unix but failed in practice. During my undergraduate projects, we often had two options: Java or Python, and I consistently chose Java. I wasn’t fond of implementing algorithms in a dynamically typed language. With that experience, I believed I knew Java inside out. However, everything changed when I landed my first job as a software engineer at Balad Maps. I needed to add features to a routing engine named Graphhopeer, written in Java. Even setting up and running the code on my MacBook was a challenge. It was my first encounter with a build system (Maven) and dependency issues. Moreover, delving into their codebase and observing their design patterns made me realize there’s much more to Java than I initially thought. After a year, I became proficient in their codebase and understood how everything functioned. The code resembled something crafted by smart C developers, utilizing some useful object-oriented aspects, although not all of them. Time passed, and during my master’s studies, I embarked on a self-study course in Model Checking. We utilized Java Path Finder to identify deadlocks in Java code, which led me to thoroughly read standard Java libraries and Java language specifications for the first time. There was a lot to learn. Then, I transitioned to my second job in Capital Markets, where we worked on a middle layer application using the Spring framework. I learned numerous new concepts, with Dependency Injection being entirely new to me. It felt like Spring was performing magic behind the scenes. After a year, I began coding microservices with GoLang, and it appeared to be the ideal approach for everything. It retained the beneficial features of Object Orientation without the aspects that caused confusion and made code unreadable. Go felt like a refined version of {C++, Java}. I was thrilled and delved into Go design proposals, questioning why we weren’t using Go for all our projects. However, my perspective shifted when I worked with Java EE for the first time. Two months ago, we were tasked with rewriting an old Java EE application with a monolithic codebase supporting over 150 types of transactions. Understanding the application’s flow itself was a nightmare. Designed in 1998, it heavily relied on queues. Although nowadays, server request handling complexities are concealed from developers, it wasn’t the case back then. They employed an IBM Queue, acting as an API gateway, along with numerous JMS queues in transactions to support multiple threads. Consider Entity Beans, for example. Configuring bean settings in EJB XMLs was arguably the most daunting task for future developers to decipher. In the absence of ORMs, they utilized beans in a pool, managed by Java EE, for reading and storing data from databases. While this complex lifecycle solved various problems like caching and reducing DB queries, it introduced another issue—the complexity of their lifecycles. Despite these challenges, Java EE’s features piqued my interest in understanding the enterprise features of Java. It’s evident that Java is a mature language; while some design decisions may seem flawed, it’s a product of extensive work by software engineers, not merely coders.
One response to “Java is HUGE!”
What a journey!
I don’t have any experience in this field, but reading this post felt like riding on a roller coaster.
From my own experience, having worked with Python for 4+ years, revisiting some design patterns really made me miss Java.