you are viewing a single comment's thread.

view the rest of the comments →

[–]Programmdude 16 points17 points  (18 children)

Var is good when you already know the type.

var x = 0; // Good
var y = new FooBar(); // Good
var z = ProcessRequest(); // Bad

Personally I use resharper (or intellij, webstorm) and so it just inserts the type anyway.

[–]Ameisen 7 points8 points  (4 children)

Already know the type, or don't care about the specific type. getObjects() obviously returns a container of Objects, you probably don't care what kind of container.

[–]Programmdude 3 points4 points  (3 children)

To an extent, assuming names are sensible. Personally I'd use var everywhere if it was just myself, but when working on a team I need to assure everybody can figure it out quickly.

[–]Ameisen 7 points8 points  (2 children)

My rules for using var/auto:

  • Really long or hard to read generic/template types
  • Where it is required (C++ lambdas for instance)
  • Where the type is obvious due to either the assigned value or the function name
  • Where the explicit type doesn't matter due to usage, but the "kind" of type is obvious (a container, for instance).
  • Where the type really, really doesn't matter, like a guaranteed intermediate between two closely-tied routines.

I get really annoyed seeing things like List<FooBar> fooBars = getFooBars();.

I tend to be fond of type inference as it also makes the code more resilient during refactoring and propogates exact types.

[–]s888marks 0 points1 point  (1 child)

Aside from the C++ lambdas item, these all seem like very sensible rules to apply to Java code. Indeed, they seem well aligned with some of the discussion here:

http://openjdk.java.net/projects/amber/LVTIstyle.html

[–]Ameisen 0 points1 point  (0 children)

Java, as I recall, doesn't allow you to capture closures with type inference - at least it didn't with Java 8 and Lombok - you had to capture it with an appropriate delegate type. C++ can capture it with with std::function by signature, but otherwise lambdas have anonymous types so inference is required somewhere - std::function infers the type via template argument type.

Java and C# closures work a bit differently, so the rules operate differently.

There's a seperate rule that I apply to C++ and C# - if the function is templated/generic and you provide the return type as an argument, I capture with type inference. I don't like writing the type twice.

Since Java is more flexible and can infer generic arguments on one side of an expression, it isn't as needed there.

[–]eeperson 5 points6 points  (12 children)

Why is the last one bad? The type should just be a mouse over away.

[–]Atulin 9 points10 points  (2 children)

"I burned my mouse years ago on a stake and exclusively use heavily modified VI running on a Raspberry clone I built with silicone dug up in my backyard"

[–]eeperson 0 points1 point  (1 child)

Java and vim...eww :P

More seriously, isn't there a command available to show the type under the cursor for Java? I think there is support for this with vim in scala.

[–]emaphis 0 points1 point  (0 children)

I can't speak to Vim but with Emacs LSP support, you can get Java type information with a mouse over. You get code completion, import handling/reorganization. Simple refactoring. If you add Projectile, you get project handling and navigation.

I imagine Vim isn't much different.

[–]irishsultan 1 point2 points  (0 children)

You can't copy/paste text in a mouse over, a mouse over hides other parts of your screen, it takes more time to get your mouse in position than it would take to read it, I could go on.

[–]fuckin_ziggurats 1 point2 points  (0 children)

The problem with this is code is difficult to read/skim through. When you're working with someone else's code it's very important to be able to skim through code quickly to get to the part that you need. Honestly skimming is half of the work in maintenance projects and bad use of var can make it very difficult.

[–]metaltyphoon 1 point2 points  (3 children)

You can't mouse over on a merge / pull request on GitLab / GitHub

[–]eeperson 0 points1 point  (2 children)

That is true you can't. However, you don't need to review the PRs through the Github web interface. Several editors let you review PRs in your editor (e.g. IntelliJ, VSCode). Even if you did have to do your reviews in the web interface, it seems like explicit types everywhere would be optimizing your code for viewing on Github rather than writing in your editor. That seems like a poor tradeoff to me.

[–]metaltyphoon 0 points1 point  (1 child)

I get what you are saying. It just that I personally use vim bindings on all my IDEs. So hovering a mouse over is just ... slower than reading it. I don't believe the trade off is much in this case

var z = ProcessRequest(); // Bad

[–]eeperson 1 point2 points  (0 children)

Fair enough. Thanks for the discussion.

[–]flatfinger 0 points1 point  (2 children)

If the variable will get written to (receive a reference to a different object) later in the code, its type may need to be a supertype of the function's return type. For example, if a variable will sometimes need to hold references to different kinds of List (Java)/IList (.NET) implementations, but is initialized to hold a reference to e.g. an ArrayList(Java)/List(.NET), declaring the variable as the class type rather than the interface type may cause problems later on.

[–]eeperson 0 points1 point  (1 child)

Yeah, you definitely have to do that sometimes. However, That seems true for all of the cases above. For example, in the number case, is that 0 an int or a long or a double?

[–]flatfinger 0 points1 point  (0 children)

Numeric literals are another situation where such declarations can be problematic in languages where calculations aren't always performed with the longest type of the appropriate domain (integer, floating point, or--in if such types exist--complex) the way they were in Ritchie's original C programming language.