02

12/11

Java’s Problems Compound on Themselves

13:17 by rleahy. Filed under: Elitism,Technology
Tags:

I just realize that when I posted yesterday I overlooked an instance of one flaw of Java exacerbating another flaw.

Yesterday’s post was about Java’s absence of pass-by-reference, and one Java programmer’s (i.e. “hostage’s“) defense thereof.

Talking about the idea of making a class that encapsulates the return values and returning that instead of having multiple return values via pass-by-reference I said:

Moreover, creating objects is non-trivial, especially creating an object so you can copy reference types into it, push the pointer to it onto the stack, pop it off, and then copy the reference types back out.

On further thought, I realized that this problem would be greatly lessened if Java supported something else that it doesn’t—structs—which are far cheaper to create than objects.

01

12/11

Java is Terrible and Java Programmers Have Stockholm Syndrome

09:47 by rleahy. Filed under: Elitism,Technology
Tags:

I hate Java.

It probably has a lot to do with being a libertarian, since Java is the programmer equivalent of big government—you want to write code, do it our way or not at all.

There are tonnes of dogmatic language decisions made about Java that aren’t made by its competitors—which are syntactically almost identical but much more flexible and useful because of the lack of dogma, e.g. C#—that I could rant about, but the most egregious—the one that I always fall back on—is pass-by-reference.

I was unable to sleep for a bit last night, and bored of watching Criminal Minds (the only non-HBO TV show I watch), so I decided to randomly Bing and see if Java had an equivalent to C#’s ref or out keywords yet.

The answer appears to still be “no“.

It seems, however, that when people use a deficient tool, they become emotionally attached to it and rather than recognizing and admitting its flaws they gloss over or even actively excuse them—a type of programming Stockholm Syndrome it would seem.

Case-in-point.

Let’s go through his workarounds one-by-one.

On a side note, I think it’s interesting that the header for the section I linked to is “[w]ays to avoid needing pass-by-reference“, which suggests that pass-by-reference is undesirable and should be “avoided“, whereas the anchor (if you view source) is “workaround“, which more accurately reflects the state-of-affairs: Something should be there, isn’t, and now you need to hack around it.  A bit of cognitive dissonance/doublethink/denial going on there.

I digress.

If any of your return values are status codes that indicate success or failure of the method, eliminate them immediately. Replace them with exception handling that throws an exception if the method does not complete successfully. The exception is a more standard way of handling error conditions, can be more expressive, and eliminates one of your return values.

Except exception throwing and catching is expensive (it triggers a stack trace, among other things), and it isn’t “a more standard way of handling error conditions“, it’s supposed to handle exceptional conditions (hence the name?). Not all errors are exceptional. If I want to read from a stream, but the stream is at the end of the underlying data, that’s an error, but it’s not exceptional since you reach the end of pretty much every stream (i.e. reaching the end is the rule, not the exception).

Find related groups of return values, and encapsulate them into objects that contain each piece of information as fields. The classes for these objects can be expanded to encapsulate their behavior later, to further improve the design of the code. Each set of related return values that you encapsulate into an object removes return values from the method by increasing the level of abstraction of the method’s interface. For instance, instead of passing co-ordinates X and Y by reference to allow them to be returned, create a mutable Point class, pass an object reference by value, and update the object’s values within the method.

Well sure, except that introducing non-standard classes just because one method had to return two values is idiotic and actually makes the code more confusing and harder to learn (since you have to learn the interface for a new class in addition to the signature/purpose of a new function).

The Point example is obviously hand-picked to make this look like a trivial argument, since the Point class (or struct, depending) is pretty much a given. But what about the case of highly efficient methods like TryParse, which is better than the corresponding Convert method solely because it doesn’t throw exceptions. Should we make a weird Boolean and Int32 encapsulating class just so this method can return without violating sacred Java dogma?

Moreover, creating objects is non-trivial, especially creating an object so you can copy reference types into it, push the pointer to it onto the stack, pop it off, and then copy the reference types back out.

Dumb.

If you find yourself passing in an object and then returning a new version of that object, and the object is mutable, then consider moving the method to be a member of the class of the object that you were passing. This can improve the encapsulation of the design and simplify the interface.

Well sure unless you happen to want both versions.

If, after all steps above, you are still left with multiple returns to a method, split the method into several different methods that each return a part of the answer. Using this set of methods from client code will be much clearer than one mega-method.

Except some functions that return many values are logically one function. Separating them to get around arbitrary dogmatic language restrictions doesn’t make any sense whatsoever and can actually make things less clear because one logical operation now requires more than one function invocation.

Besides, function invocations (unless inlined) represent overhead.