Hacker News new | ask | show | jobs
by zelphirkalt 1069 days ago
While Java's compiler or JIT is probably one of the most optimized softwares in existence, how do we measure, what overhead the language nudges the programmers to build? I am thinking of AbstractProviderFactoryProxy and similar. Or that for a very long time it forced you (or still does to a degree) to put everything into classes, breeding 1 or 2 generations of programmers, who see a noun and jump to making a class and then subsequently initializing the class to be able to call a method, which actually would only need to be a standalone function.

It probably does not balance the 38x, and probably the JIT optimizes parts of it away, but surely the cost is far from zero.

Also what about the computational resources it takes to just run a JVM, compared to running a Python program?

3 comments

Please explain how "AbstractProviderFactoryProxy" is related to the language.

I have taken over as lead for a Python project and what I see all the Java problems people used to make fun of (none have worked in Java before) and worse. On top, everything has an interface starting with "I", C# style. Methods in entities, service classes are instantiated with state etc. And side-effects are all over the place.

If you are writing modern Java syntax, there is little that is more stable and readable than good modern Java syntax.

> Please explain how "AbstractProviderFactoryProxy" is related to the language.

The language Java did, until some time ago, not allow you to pass functions as arguments. You had to make an anonymous inner class for example, satisfying some interface. Many design patterns are very much oriented towards a language like Java, which does/did not allow for higher order functions.

Take the visitor pattern for example. It will get you a "Visitor" in your class name implementing a visitor. How would it work in other languages, which provide higher order functions or always did so? Well, you would simply write a function and depending on whether your language has static types, annotate its types for arguments and return value. You would then pass this function in as an argument, whose name can be "visitor".

Take a factory pattern as an example. How would it work? Well, a factory can be expressed using a function, that returns another function. It takes the arguments, that specify/narrow down how the returned function works. In Java it would become a Factory class instead. Instead of using a simple function, one needs (needed?) to build a whole class around that, because one could not return a function. So one would build that class and then make it return an object instead, which of course again must be derived from some class ...

Just 2 examples that quickly come to mind.

> I have taken over as lead for a Python project and what I see all the Java problems people used to make fun of (none have worked in Java before) and worse.

It is certainly true, that people also write shit code in Python. I have seen very popular libraries, which wrap REST APIs in objects. It is silly, because objects are meant to have some lifetime in which they communicate with each other and possibly change their state. There is no changing state though. Everything is a response from the REST API, which by the definition of REST should transfer the representative state in its responses. I don't want any in between stored state. I want the state that the API gives me. It is very much a more functional view on things. But Python programmers will go "make classes!" nevertheless. Because noun. Because not thinking about whether they really need a class. Because thinking that one approach fits it all and the only approaches they learned were procedural at the beginning of their learning and then OOP, which is complex enough to take years to learn properly, so that is where they stopped.

However, Python always (for a very long time?) has allowed you to pass procedures as arguments and as such does not encourage "AbstractProviderFactoryProxy" as much as Java does. Still, sometimes former Java developers try their hand at some Python code ...

> If you are writing modern Java syntax, there is little that is more stable and readable than good modern Java syntax.

Modern Java certainly has improved. But there is a lot of relearning to be done for those generations of Java programmers, to get rid of the "every noun a class" mentality.

You are misunderstanding the Visitor design pattern. It is not replaced by higher order functions — the point of it is to emulate multiple dispatch (over the usual single dispatch most languages have), that is, to change method implementation based not only on the receiver, but the argument as well.

(It is replaced/has an exact analog with pattern matching though. Thankfully, Java has that available nowadays as well).

Well, according to the wikipedia quote (https://en.wikipedia.org/wiki/Visitor_pattern#Definition) of GoF:

> Represent[ing] an operation to be performed on elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.

And that is exactly what you can do with higher order functions (or maybe procedures, if your visitor involves a side-effect). Instead of passing a "Visitor" object/instance, you pass in a "visitor" function/procedure. It too can achieve the goal of enabling to implement "a new operation" outside of "the class" (or whatever one uses instead of a class). "Operation" probably also being conceptually closer to function than object, since an operation is about "doing something", while an object is not necessarily actively doing something other than live.

By writing a function that accepts a function as an argument, you leave open the possibility for some other part of the code to define that function (a new operation). If you need to add another operation, you just define a new function. That you can pass in as an argument.

How is a class that holds a static method/function any different to simply namespacing? Never understood people’s problem with that. For example, what’s the problem with Java’s Math “class”? It only has stateless math functions like any other language, nothing is forced on you.
It does not have to be a problem in terms of it working or not.

The problem is rather, that a class comes with loads of conceptual baggage. It is conceptually not fit for the purpose of merely namespacing.

A good language will have a concept fit for the purpose of namespacing. Either something directly called "namespace" or something that is meant to namespace things, like modules. A class is rather for grouping methods that interact with the state of the objects.

Of course, if you don't have anything else available, you gotta take what you have. It will not serve making the code more readable though, as a potentially new reader of the code will expect a class to be instanced somewhere, as is typical for classes. It can lead to confusion. If there was however a concept "namespace", they will immediately know that it is for grouping a category of things.

> see a noun and jump to making a class

Even when what you Utils.see Utils.is a verb, you Utils.must still Utils.jump to Utils.make a class.

Java 5's static imports at least allow cleaning up the call site, although the documentation advises (in bold) using this feature "very sparingly".