For a rational choice, we need to consider other more important elements.
I often happen to stumble into posts comparing Java and Go. Almost always, at the center of the comparison is either the speed of execution or the presence/lack of specific features (usually absent in Go and well established in Java).
So if one writes that Go is awesome, there are tens of replies stating that Java is much better because “there is this benchmark that proves Java is much faster” (plus it has Generics and also try-catch). Then you read the “benchmark “that states that Java is faster than Go, and you find another flock of comments sustaining the opposite.
The tone tends to quickly drift towards that of a religious war.
But, wait a minute. Is it possible to approach it from a different standpoint? Is it possible to evaluate which of the two languages is likely to bring more benefits to a specific organisation, product or project?
Ease of development and maintenance of standard enterprise business applications is the most important aspect to consider when comparing different programming languages
This means to compare programming languages on what really matters, which in most cases, specifically in the enterprise world, is how efficient it is to develop and maintain standard business application code. Development and maintenance of standard business application code is where most of the cost usually lays. So ease of development and maintenance of such code should be at the center of any evaluation.
Yes, there are some facts, things that are just true and do not depend on opinions, at least in the vast majority of cases. Here I list those that come to my mind, with no specific order.
Fact: Go produces smaller executables and uses less memory
Docker images containing Go executables are usually smaller than Java equivalent. This is important if optimisation of infrastructure resources or minimisation of warm-up time are important, the latter being relevant for “Function as a service” models.
Fact: Go can sustain an higher level of concurrency
Go can fire easily hundred thousands of goroutines. Java threads are much more limited. Again, this is important if we want to squeeze the most out of our CPUs, specifically in the context of I/O bound workloads.
Fact: Java has libraries to connect to everything
This can be a critical decision factor in some cases. If you need to connect with transaction managers such as CICS or TxSeries or other older technologies, then Java is the only option. There are just no packages for this in Go.
Fact: there are more Java programmers out there
As simple as that.
Fact: Go has a simpler syntax
The Go specifications are 86 pages, examples included. The year 2000 Java specs were already 250 pages and since then things did not get simpler. Quite the contrary.
Fact: the “write once run everywhere” is much less relevant
With the ever increasing popularity of containers, you can write in almost any language and run on top of Docker everywhere
Fact: Go is faster when it comes to build
Have you ever seen the spinning wheel on the screen of a Java developer who has launched the execution of a test suite? Well, this is much less likely to happen with Go.
Unfortunately, or fortunately, life is not all black-or-white. There are shades of grey. Here some of such shades which are relevant in our case.
Questionable: Go is too limited for serious application development
Go does not have Generics. Go does not have try-catch. Some say you can not develop serious enterprise-level code without such basic features. You easily end up repeating over and over again the same code.
Questionable: Java has grown too complex
The opposite argument. With Java you have Object Orientation, Aspect Oriented programming via annotations, Functional Programming even if it tastes a bit clumsy, magic frameworks such as Spring. Some say that, depending on the mood you get up in the morning, you can develop the same logic in many ways, with many different styles, potentially confusing the code and making applications more difficult to be maintained.
Questionable: Go is for system programming
While it is true that it has been heavily used to build things like Docker and Kubernetes, there is no clear reason why it is not fit for standard enterprise application development, unless we use as argument other questionable elements, e.g. the “generics & try/catch” argument listed above.
As you have seen there are pros and cons with both choices. But when it comes to a decision, we need to look at the specific context.
Let’s consider a standard scenario, a software shop that develops enterprise solutions like banking applications or order management systems.
In such cases, the two elements that contribute most to the overall costs are development effort and maintenance effort. In some cases also the cost of the infrastructure required by a certain solution can be relevant. So these are the elements we need to consider in order to make a rational choice around the technologies to use.
This is the most important factor to evaluate in most cases. Does it cost less to develop and maintain an application written in Go or written in Java?
Limited initial investment
Let’s start from the beginning. If we are a Java shop, which most are, we may tend to think there is just one answer: “you know Java -> you will be more efficient with Java”.
On the other side Go simplicity comes very handy here. Being simple means it is easy to learn. If we know how to code, it takes really few days to be able to write production code in Go. Not the most complex one, but certainly a good one. At the same time, if we do not know how to code well we have a basic problem, regardless the language. Summary is that, given its simplicity, you can still evaluate Go, even if what you currently know is just Java.
Is it simple or is it poor?
Go is simple. But may be seen also as poor. We mentioned already that it doesn’t have Generics and error management may be considered verbose. There are no Classes per se and no Inheritance. So one can say that the lack of such features decreases productivity.
On the other hand, with Go usually there is just one way to do one thing. Go creators call this “orthogonality”.
If there is just one way, we do not have to think about which style to adopt when solving a problem. If there is just one way, it is going to be easier to read and understand someone’s else code.
Some studies have measured that we spend ten times more time reading code, either ours or of somebody else, than writing new code. If this is true, simplicity and straightforwardness are crucial to optime efficiency.
So, if Go is easy to learn, we do not have to invest a lot to start using it.
If Go is so simple and lean, it can make development and maintenance of enterprise-class application code easier and more efficient.
If build and test cycles and are much faster, developers end up wasting less time staring at the spinning wheel.
If support for concurrency in Go is so good, then we can exploit much better our infrastructure specifically in I/O bound scenarios.
Adding up all these points, there is a concrete possibility that developing enterprise applications with Go can bring substantial improvements in terms overall efficiency of the IT function.
Of course it all depends on the context, but the possibility to reap serious benefits moving to Go seems concrete. So probably it is worth considering to start experimenting with it. We just need to select the right project candidate, create a team, get a bit of training and see if the outcomes are positive.
It is an investment. As any investment, it entails some risks but also promises some gains. Based on the results, you may then decide to extend it or stop it.
Is it worth to try Go in the enterprise world? We can summarise the entire content of this article in one decision process algorithm, written in Go obviously
func DecideIfTryGo() Outcomes {
// check for showstoppers (g.g. CICS integration) in my environment
showstopper := os.Getenv("SHOWSTOPPERS")
// if there are showstoppers there is no point to try Go
if showstopper != "" {
return errors.New(showstopper)
}
// find a good candidate project considering Go characteristics
project := FindProject("concurrent", "IOBound", "InfraEfficiency")
// create a team
team := NewTeam(project)
// do a bit of training
TrainTeam(team)
// launch the project with a timeout
ctx, cancel = context.WithTimeout(context.Background(), timeout)
outcomes := Launch(ctx, project)
// return the outcomes
return outcomes
}
The article is centred around Go and Java, but the core idea of comparing things around what really matters can be applied to any set of technologies.
So feel free to substitute Java and Go with anything else, as long as you compare them along what really matters. And let’s be cognisant that the context matters a lot.