Is Javascript eating Java?

Developments in Javascript till 2018

When it comes to employing full stack engineers, we normally look at having a separate team for the mobile division, the browser application team, and the backend or the server-side team. With Javascript, especially NodeJS, this is changing. All you now need to know is Javascript and you can have a team with the same skill set working on the backend, front end, and the mobile app. Say in a Javascript world, that would mean NodeJS on the server side, Javascript frameworks on the client side, and JS frameworks for the mobile (with cross-platform frameworks like React). Javascript has become ubiquitous, getting adopted by the web, mobile, embedded, server, devops, and database world. The force is rising! You could say Javascript is eating the world! At least it seems so, with the hype the framework is getting.

Of late, you even have TensorFlow in Javascript! You have machine learning capabilities inside the browser. NodeJS is very popular on the server side because of the LTS (long term support) because of which it is very popular with large enterprises.

So is Java getting eaten up by Javascript? Going by the trends which most major players are showing, it seems like a Yes. Some of the major players to move to Javascript, (especially NodeJS) are Netflix, LinkedIN, Uber, PayPal, AOL, eBay, and Zappos.

So here are some of the metrics under which we will try to make a more objective comparison of this debate.

Developer Productivity

Simple server-side applications can be created quickly in NodeJS. One can put together prototypes pretty quickly and it works well for teams which work in client-side frameworks to dabble in server-side frameworks and quickly get productive.

Java is NOT a framework and does not provide anything on the client side which Javascript does - in terms of frameworks like Vue, Angular, React, JQuery etc. Javascript is the default browser language of choice for web and browser development.

Performance

Both platforms - Java and Javascript are (infinitely) scalable. It is however the “threading” model which Java application servers take versus NodeJS multithreaded servers which can impact the architectural choice.

Java application servers create a multithreaded application but all the threads belong to one (operating system) “process”. In case of a thread hangup, if it impacts any shared resource which the process is sharing amongst other threads, it can block all the threads (and as a result hangup the process running all the threads in the application server). However, this multithreaded paradigm allows Java to have shared state amongst threads and allow concurrent and multi-threaded applications where thread concurrency, synchronization, and parallelization can be controlled programmatically. Writing such applications need to be debugged for dead-lock or thread starvation situations.

NodeJS approach is different. It follows the thread per process architecture where no resources are shared between processes. Even if one thread fails, other threads are not impacted (since one thread is equivalent to one server process) which can die in the background but other processes (or threads) still keep serving user requests. This however makes sharing of variables between threads (in this case processes) difficult. There is no shared state or at least its difficult to implement.

Skills and Experience

Finding Java guys with a few decades of experience is not a problem. It is a fairly mature, old, and stable platform with developers having rich experience. Finding mature Javascript developers is still a tough ask. The language has had an upsurge of late and finding developers with as much experience is a challenging requirement.

Even a decade back, basic Java topics had fairly comprehensive documentation (thanks to the Sun Microsystems promoting Java at all levels) but Javascript documentation was still obscure and not that well organized. Developer forums had to be reached out to learn different tricks, tweaks, and language semantics which was known to a few select set of Gurus. There was no single “organized” and “well documented” source of truth for learning all Javascript nuances.

Over the last few years, there has been an explosion in the Javascript developer community whose participation in online forums like StackOverflow and StackExchange has led to a lot of documentation and language nuances being available. Javascript best practices have evolved and become more mature than a decade back.

Resource Availability

Traditionally, Javascript resources have been UI developers who had not delved into server-side Javascript much. The transition from a UI developer to a full stack developer is a fairly recent development. Just like Python, Javascript has had some demand in the last five years because of the popularity of frameworks like React and NodeJS. However, there is still a dearth of good resources in the Javascript world and this is a gap which is still getting filled up. Over the next few years, however, because of the availability of rich online resources, the supply of skilled resources should increase. Java being a mature platform, the resources are fairly easily available since over the last two decades, the language has been promoted fairly well at the school and university level courses for learning programming. The same cannot be said to be true for Javascript.

Features and Capabilities

  • Exception handling and debugging in Javascript/NodeJS are still evolving. Java handles both in a much more robust and mature way since Java was touted and brought up as a server-side technology of choice. So while you get explicit log files in Java or IDEs which support debugging, Javascript frameworks still resort a lot to the Console.log() style of debugging which needs to evolve as this can affect productivity. With tools like node-inspector, some of these problems are getting resolved for the Javascript developers.
  • Since Java is statically typed language, it is more amenable to debug it than a dynamically typed language like Javascript. Since the variable types can change at runtime in Javascript, fixing defects can be more challenging. Although Typescript is trying to bridge a lot of gaps in Javascript from that perspective, it is still far from where Java is in its evolution.
  • Node.js and other Javascript server-side frameworks currently do not support multi-threading support natively. Java has a rich set of API availability for multi-threaded applications like Thread Pools, multi-tenancy etc. Node JS provides a “hack” around this lack of support by providing a “event driven architecture” where events are consumed the moment they are produced.
  • Java thanks to Eclipse and JetBrains has a more robust and rich (plugin based) IDE support than what we currently see for Javascript for whom the IDEs are still evolving.
  • For mobile platforms, Javascript has frameworks like React which allow increased productivity in terms of allowing cross-platform apps to be developed (for both iOS and Android platforms). Java / Kotlin can only cater to one platform - which is Android.
  • Java has very comprehensive package managers like gradle and maven which are pretty mature and great dependency management and build tools. “npm” for Javascript / NodeJS is still evolving and errors generated during the build or package installation stages are many times incomprehensible and difficult to troubleshoot.
  • Type safety in Java is assured since it is a “statically typed” language. This can become a problem for Javascript frameworks especially when consuming them as APIs or third-party packages. In case the documentation is lacking, figuring out the right usage or data type which a third-party library is returning can be a big pain!
  • While Object Oriented programming paradigm is strongly encouraged in Java and other statically typed languages like C# etc, the same is not true for a lot of Javascript frameworks. They instead prefer more functional, event-driven, or procedural style of coding. Although this is more a matter of personal style or taste, but for very large projects, the reason why the OOPS tsunami came about in the 90s and early 2000s was for a particular reason which the Node community chooses to overlook.
  • When it comes to heavy-duty industrial-grade features like transactional logic, loaders, and external services,

Deployment Speed

Java has complex build tools like Maven and Gradle which can create some of the most complex build processes possible. Build process in the NodeJS paradigm could be as simple as deploying the right packages using the npm package manager and copying the scripts onto the server. Just configure an Apache or nginx server and you are good to go. Javascript on the server side has a long way to go in terms of complex build management tools. Indirectly, this also means that it takes considerably less time and effort to deploy the code on a production server!

While a Java web application would need to be deployed using an app server which would then need to be configured using a web server, Node itself provides the runtime environment using Chrome’s Javascript runtime engine to execute JS code directly.

Support and Maintenance

From a code maintenance perspective, static languages like C# and Java are far less pain than dynamic languages like Javascript for the following reasons.

  • Javascript code is not exactly “modular” by design. The language has to be worked upon for the code to look modular, readable, and maintainable.
  • Function scoping in Javascript is a tricky thing to master and can lead to bugs which can miss the eye of a not so experienced developer.
  • For very large teams, code maintenance and bug fixing is relatively easier for Java because of its static typing features and rich IDE based debugging support which can quickly help identify impacted code areas because of the way its compilation and build process works.
  • Javascript syntax and features like promises, closures, callback, and event binding etc make it difficult to debug. For smaller teams (of say 4-5 members), the code is maintainable but for very large teams, Javascript code becomes difficult to debug and maintain because of the language nuances. It can sometimes become difficult to understand the full impact of even small code changes for very large codebases.
  • Binary compatibility and package versioning issues are more prevalent in Javascript because of the active development happening in different frameworks. Java packages are relatively more stable and platforms like Spring make sure the binary dependencies are taken care of at project configuration time itself. Any package upgrade has higher chances of unpredictable code breakages in Javascript than on the Java platform.
  • Upgrading packages can be troublesome in Javascript / NodeJS in case they use C-style bindings. In the Java world, replacing binaries (jars) should work and no external/native builds need to be triggered. But when using C-style bindings in Node, you have to ‘recompile’ the bindings for the upgrade to work. This means an extra step in the build process if you do not forget that is, in which case your upgrade can actually fail!
  • To troubleshoot many topics, Java community seems to have more “researched” and available solutions compared to the Javascript community. When searching on Google, it is easier to find answers for problems in Java than on Javascript.

Security

Compiled and even interpreted languages create bytecode at runtime. While interpreted languages like even Python create compiled bytecode (.pyc files), Node being Javascript based does not generate any such files at runtime. The code being executed is the code “as is” on the file system. This is sometimes seen by many as a potential for code to get compromised. The code can be “read” as is and there is no additional challenge on part of the hacker to go “reverse engineer” the code. The best you can do is obfuscate the code before execution which makes it “unreadable” at the best. However, there are tools in the market which can reverse beautify the code and make it readable again.

The same can be said of bytecode files which can be reverse engineered using disassemblers.

Summary and Afterthoughts

It sometimes depends on which language you picked up first (whether Java or Javascript) and how you see the second language that you pick up which determines how comfortable you are switching or adopting the second language. Familiarity makes one more productive and even though every language has some nuances, if you can figure out the way to be productive, you can make most languages work. There is no “one” way to strictly determine which language is the best. However, with the slew of companies adopting the Javascript frameworks on the server side, it seems like more companies are betting on this stack evolving over time as they feel that the time for Java is behind us - or at least that is how it seems!