Account account = customer.GetAccount();
List<Transaction> transactions = account.GetTransactions();
Have I saved you any extra-effort here by specifying the types? You have no idea where these types came from or how they are defined. So why is this useful? 'Go to definition' works just as well on var.
var customerOrderGroups =
from(customerList)
.select(c -> tuple(
c.companyName(),
from(c.orders())
.groupBy(o -> o.orderDate().year())
.select(into((year, orders) -> tuple(
year,
from(orders)
.groupBy(o -> o.orderDate().month())
)))
));
Yuck! I need to read that entire thing to have any clue as to what that produces or how I should go about using it. It is compact but it is not understandable. The "Magic" of Java is clean abstractions with no voodoo. PHP/Ruby programmers like their frameworks who hide code from the developer, which layer on complexity, and which "just work" (until they stop). In a proper Java project anyone can visually see, in any part of the program, what is attempting to be done and what is being linked up to what. A big portion of this is types. Account account = ...;
List<Transaction> transactions = ...;
Is all you need to read from your example. If we were to expand your ideal to a function it would look like this: void someFunction(var customer) {
var account = customer.GetAccount();
var transactions = account.GetTransactions()
}
I can honestly tell you that it is impossible for me to know what will happen in this program unless I go through and look at every single code path that reaches this function. Once you have entire functions, or units of code, that are using `var` it becomes entirely unmanageable. Is a string getting into `someFunction`? What about a `Trader` or a `Banker` making it's way into there rather than a `Customer`? Would you know this was happening as both Trader and Banker implement .GetAccount()?It's no surprise though that in the world of null-propagation haven that the language maintainers would decide to expand this class of problem to all object types! Why should the null primitive be the only thing that gets to ruin our day?
If I replaced the types above with var, you would still be in the dark as to what an Account and/or Transaction is without going to the type definition.
I can see that the thing returned from getAccount() is an Account object! It's not an accountId, or the name of the account, or an AccountDTO, or an Optional<Account>, or any of the dozen other things I've seen people return from methods named getAccount().
Depending on how methods are named, the implicit documentation can be very helpful:
Account from = transfer.getFrom();
I don't think that var is particularly evil, but I think it has a poor case for existence. Meh.var transactions = account.getTransactions();
...tells you nothing. Is transactions iterable? Is it an enum? Is it ordered? Are duplicates allowed? Maybe you're returning a basic type? Maybe it's another pojo?