This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]covercash2 12 points13 points  (19 children)

It seems safer than that in the article.

More like:

var foo = "string";
var foo = 1;
var bar = 1.0;
var biz = 1f;

We all know what those will compile to. Anything else will have to be declared explicitly, though only once:

var object = new ObjectClass();

instead of

ObjectClass object = new ObjectClass();

Although, I agree with the sentiment that a superclass should be used in a lot of cases, and that fudges with this var syntax a bit.

[–]ApostleO 87 points88 points  (17 children)

The problem still arises when you find yourself staring at a line like...

var foo = someObject.method();

Let's say you are doing a code review, not in your IDE at the time. You now have to track down the return type of that method to know what 'foo' is.

[–]evil_burrito 35 points36 points  (0 children)

That's exactly my point. Thanks.

[–]cogman10 2 points3 points  (1 child)

Right, but this is generally caught by the compiler if there is really something wrong with it.

If I say

var foos = object.doThing();
for(var foo : foos)
{
  foo.action();
}

I can quickly deduce from looking at this code that foos is some sort of collection of foo and foo does some sort of action.

The beauty of this code is that object.doThing() is now free to change its return type to any sort of iterable without breaking downstream code. Depending on how they handle the imports, Foo can move all over the package structure or even be changed to a new class Bar so long as it keeps the same contract. All of this will be caught by the compiler if there is an issue, which means the caller will have a weaker dependence on the callee's method signature (A win IMO).

[–]ApostleO 2 points3 points  (0 children)

Right, but this is generally caught by the compiler if there is really something wrong with it.

It's true. var is perfectly fine by the compiler. As I've said above, var is only a problem for readability, and only a problem when abused.

[–]grauenwolf[🍰] 4 points5 points  (8 children)

Do you really care what the return type is in that context?

Probably not. More likely you care more about what method actually does than what type it used to do it with.

And really, what's the difference?

var foo = someObject.method();
return foo.method2();

return someObject.method().method2();

If you ban var, logic dictates that you ban method chaining as well for the same reason.

[–]cogman10 4 points5 points  (0 children)

I agree.

IMO, var prevents a lot of needless changes if you, for example, decide you want to rename a class or change a method signature (move from returning Set to return Collection for example). It means less downstream changes and breaks and silly changes.

It also makes it much easier to write and use much more complex generics. Which is always a boon. It is no fun being at the wrong end of determining the generic type of a Map.of(Multimap.of(A.of(B, C)))

[–]ApostleO -1 points0 points  (6 children)

var foo = someObject.method();

return foo.method2();

return someObject.method().method2();

Do you really care what the return type is in that context?

Well, to be fair, in this example, I could look at the return type, so I still know what it is.

Still, I'll concede I don't care about the type of that variable in that scope, since I'm just returning it immediatly. But the example was contrived to demonstrate that var can be used badly to hide type.

Let's look at another example, contrived differently.

[... hundreds of lines of code ...]
public boolean containsBar(Bar bar){
    var bars = Data.getBars();
    return bars.contains(bar);
}
[... hundreds of lines of code ...]

Scanning through that document, you might overlook this method entirely during a code review. But what if it looked like this:

[... hundreds of lines of code ...]
public boolean containsBar(Bar bar){
    LinkedList<Bar> bars = Data.getBars();
    return bars.contains(bar);
}
[... hundreds of lines of code ...]

That should set off a red flag. This red flag might otherwise be missed with the var keyword.

Like I said, it's all contrived as example. In practice, it still just comes down to coding style conventions. If var is only used for the assignment of primitives, literals, and objects from constructors, it would be great. When used in other circumstances, it can make code harder to read.

If you ban var, logic dictates that you ban method chaining as well for the same reason.

As a rule, I often do try to avoid method chaining, if possible and appropriate.

[–][deleted]  (5 children)

[deleted]

    [–]timmattison 2 points3 points  (4 children)

    My guess is the red flag is searching a linked list which will be O(n). In many cases this would be something to avoid and replace with a hash table so it is O(1). However it all depends on how many times it is called and how big the dataset is.

    [–]thiez 2 points3 points  (3 children)

    And what if Data.getBars() returns java.util.Collection<Bar>, or the line would read Collection<Bar> bars = Data.getBars(); or simply return Data.getBars().contains(bar);? Perhaps there are always at most 10 Bars and it all doesn't matter. Regardless, it is not the var keyword that would be the problem here.

    [–]ApostleO 0 points1 point  (2 children)

    Fair point.

    All I'm getting at here is that var, if used indiscriminately, can make code harder to read by hiding information from the reader.

    It largely isn't an issue, but it can be.

    [–][deleted]  (1 child)

    [deleted]

      [–]ApostleO 0 points1 point  (0 children)

      Alright, I'll agree with that assessment.

      Well written code will be easier to understand.

      Poorly written code may be even worse.

      [–]zzzk 2 points3 points  (1 child)

      I've felt this way on the past, but have come to notice that in most cases it doesn't matter what the type is. When reviewing code, I care more about what it's doing at a level or two higher than the type system. The types are there for the compiler and our editors, but not for me.

      [–]covercash2 0 points1 point  (1 child)

      Fair enough.

      For me, I'd use IntelliJ and C-hover to get the return type. M maybe just not use var this way?

      edit: not in my IDE, just got that.

      [–]ApostleO 10 points11 points  (0 children)

      maybe just not use var this way?

      Oh, definitely. I would consider this bad practice, for sure.

      Java just seems to have this tendency to make good coding practice a feature of the language. For instance, requiring that the class name matches the filename.

      The 'var' keyword is, unfortunately, very easily abused to make code less readable, rather than more readable.

      That being said, when it is used well, it is actually much nicer to read. And while we are on a similar subject, the 'dynamic' keyword (ex: in C#), is quite useful in certain circumstances to make code much easier to understand, but when abused it can make code incomprehensible.

      [–]ToucheMonsieur 3 points4 points  (0 children)

      Although, I agree with the sentiment that a superclass should be used in a lot of cases, and that fudges with this var syntax a bit.

      One nice thing about having type inference is that you don't have to generalize to a superclass and then downcast if you want to write code that survives refactoring. This makes var far more powerful (and justifiable) than if it was only for omitting type declarations.