Live data from Hacker News

Named Parameters in Java

java.dzone.com

51–60 of 62 posts

Re: Named Parameters in Java

#51
post #30

Earlier quoted context omitted.

There is a small but meaningful distinction: Encapsulating the data in OOP fashion allows you to respond when the need arises . You don't build it until you need it, but when/if you do ever need it you won't have to refactor the interface (and the interfaces of all the classes that use these data). This minimizes changes down the road and leads to maintainability.

But it also means that you are introducing a lot of extra classes that do almost nothing but wrap primitives and provide little or no additional behaviour. If you do need to pass in additional information, refactor and change the primitive to an object when you really need to, not because you might need it at some point in the future (and the chances are you won't).

> If you do need to pass in additional information, refactor and change the primitive to an object when you really need to, not because you might need it at some point in the future (and the chances are you won't).

That's a lot harder than doing it right to begin with, and requires significant API-breaking changes across the code base.

Due to the cost of doing so, it's far more likely that the code will be hacked poorly to incorporate the necessary addition, as the substantial changes now required would be much too costly.

YAGNI is misused to justify being lazy. You're always going to need maintenance (except when you have the rare piece of throw-away code), certain approaches are always going to incur high costs to maintenance and future development. YAGNI doesn't apply when past experience provides sufficient evidence that you do need it, and you need it now, when you're writing the code.

Re: Named Parameters in Java

#52

Earlier quoted context omitted.

But it also means that you are introducing a lot of extra classes that do almost nothing but wrap primitives and provide little or no additional behaviour. If you do need to pass in additional information, refactor and change the primitive to an object when you really need to, not because you might need it at some point in the future (and the chances are you won't).

> If you do need to pass in additional information, refactor and change the primitive to an object when you really need to, not because you might need it at some point in the future (and the chances are you won't). That's a lot harder than doing it right to begin with, and requires significant API-breaking changes across the code base. Due to the cost of doing so, it's far more likely that the code will be hacked poo…

And you are correct that there are cases where this is true - but the best approach is to use an element of judgement and make a call when this is likely to pay off in the long term. Always using primitives for everything or never using primitives because you might need to augment them structurally at some point are both silly extremes that are equally bad.

Re: Named Parameters in Java

#53

Earlier quoted context omitted.

> If you do need to pass in additional information, refactor and change the primitive to an object when you really need to, not because you might need it at some point in the future (and the chances are you won't). That's a lot harder than doing it right to begin with, and requires significant API-breaking changes across the code base. Due to the cost of doing so, it's far more likely that the code will be hacked poo…

And you are correct that there are cases where this is true - but the best approach is to use an element of judgement and make a call when this is likely to pay off in the long term. Always using primitives for everything or never using primitives because you might need to augment them structurally at some point are both silly extremes that are equally bad.

> Always using primitives for everything or never using primitives because you might need to augment them structurally at some point are both silly extremes that are equally bad.

I agree.

Re: Named Parameters in Java

#54
post #6

Whoever wrote the original code is missing a major point in OOP: you should (almost) never be passing in simple types. Create an object that holds the data (class IDObject, for instance), and pass an instance of this class in for the parameter. Then, the parameters are de facto named in the data object. This importance of this method is that it allows the you to update the information passed in via the data object (w…

Never passing in simple types? I don't know about you, but one of the reasons I like languages such as Python and JavaScript is I don't have to create a wrapper object for every type I'm using. The fact I had to, for instance, create URL and IP Address and such objects in C# drove me crazy.

The idea is to write a wrapper that encapsulates all of the (related) data. This is useful in type-checked languages where changing the signature can have repercussions across multiple classes.

I actually do this in javascript, too. I'll pass in object (it's nice in js because you can just write them in json) and refer to the variable by object property

  verifyID({idNum: 1234, surname: 'Himes', firstName: 'Dan'});
{where the signature is

  verifyID(idObect)
}

This has the advantage of not requiring you to remember the order of parameters.

Re: Named Parameters in Java

#55
post #50

Earlier quoted context omitted.

If I understand you correctly about the Law of Demeter, and we were to use an `Id` object to represent an ID, then the following would be verboten: val id: Id = db.findUserBySsNumber(ssNumber) println("id=" + id.toString()) // Violates Demeter! Instead we should do something like val id: Id = db.findUserBySsNumber(ssNumber) println("id=" + db.idToString(id)) // Demeter is happy. Boy, it would be a lot easier if `id`…

If I knew what your code was trying to do I might be able to write to it directly. But these guidelines would suggest that if you are going to call methods on the id object, it's best, if possible, to put the methods in the id object itself.

> But these guidelines would suggest that if you are going to call methods on the id object, it's best, if possible, to put the methods in the id object itself.

But that would violate the Law of Demeter, as I understand it: E.g., you shouldn't fetch an Id object from a Db object, and then call a method on the Id object. I.e., you should only talk directly to the Db object.

Not that the Law of Demeter is necessarily the best way to do everything, but it has its merits in terms of decoupling.

I'm not sure where the code snippet that I provided wasn't clear. It looks up someone by Social Security Number in a database and gets back an ID. It thens prints out the ID.

I'm also not clear on just what you are asserting: That my understanding here of the Law of Demeter is incorrect? Or that I shouldn't be following The Law of Demeter here.

Re: Named Parameters in Java

#56

Earlier quoted context omitted.

> If you do need to pass in additional information, refactor and change the primitive to an object when you really need to, not because you might need it at some point in the future (and the chances are you won't). That's a lot harder than doing it right to begin with, and requires significant API-breaking changes across the code base. Due to the cost of doing so, it's far more likely that the code will be hacked poo…

And you are correct that there are cases where this is true - but the best approach is to use an element of judgement and make a call when this is likely to pay off in the long term. Always using primitives for everything or never using primitives because you might need to augment them structurally at some point are both silly extremes that are equally bad.

True, they are silly extremes. But as guidelines they are not equal. One may lead to a few extra "waste" classes, but the other can fook things up.

They are to be taken in the same vein as "prefer implementation to extension (program to interfaces rather than classes)" and so on. Not gospel, but advice from some of those who have been down both roads and are calling back to us. Advice meant to give you pause as you set about building that subclass.

It should be obvious that design strategies that allow change without breaking signatures are good things. Maybe they are not needed or wanted absolutely everywhere, but certainly, if there is any doubt, they should be used.

Re: Named Parameters in Java

#57
post #56

Earlier quoted context omitted.

And you are correct that there are cases where this is true - but the best approach is to use an element of judgement and make a call when this is likely to pay off in the long term. Always using primitives for everything or never using primitives because you might need to augment them structurally at some point are both silly extremes that are equally bad.

True, they are silly extremes. But as guidelines they are not equal. One may lead to a few extra "waste" classes, but the other can fook things up. They are to be taken in the same vein as "prefer implementation to extension (program to interfaces rather than classes)" and so on. Not gospel, but advice from some of those who have been down both roads and are calling back to us. Advice meant to give you pause as you s…

Well, my experience redesigning large-scale enterprise applications built to be "generic" is that almost nobody gets the balance right but by far the worst applications to work with are the over-architected over-generic solutions.

Re: Named Parameters in Java

#58
post #50

Earlier quoted context omitted.

If I knew what your code was trying to do I might be able to write to it directly. But these guidelines would suggest that if you are going to call methods on the id object, it's best, if possible, to put the methods in the id object itself.

> But these guidelines would suggest that if you are going to call methods on the id object, it's best, if possible, to put the methods in the id object itself. But that would violate the Law of Demeter, as I understand it: E.g., you shouldn't fetch an Id object from a Db object, and then call a method on the Id object. I.e., you should only talk directly to the Db object. Not that the Law of Demeter is necessarily t…

If the code snippet returns a local ID object, then calling a method on the ID object doesn't violate the law of Demeter. It can be, in fact, the preferred method in the case that you don't have control over the db object.

If your snippet doesn't return a local id object, then the violating portion should be

  idstring = db.findUserBySsNumber(ssNumber).toString();
  println("id=" + idstring)
A (perhaps) more clear illustration is when you go the other way with the data. Suppose you want to change the last name of the user. You would want to consider that

  id.setLastName('Himes')
  db.updateUser(id)
  
may be preferable to

   db.findUserBySsNumber(ssNumber).updateLastName('Himes')
   
The first case is more robust (but, of course, not infallibly so) to changes in the api for db when, for example, the api providers decide it's too dangerous to throw SSNs around. It's also more robust against changes in the content of id.

These are the kinds of things that OO guidelines can protect against. The tradeoff is added overhead (data objects)-- which means more testing, debugging, etc.

Re: Named Parameters in Java

#59
post #58

Earlier quoted context omitted.

> But these guidelines would suggest that if you are going to call methods on the id object, it's best, if possible, to put the methods in the id object itself. But that would violate the Law of Demeter, as I understand it: E.g., you shouldn't fetch an Id object from a Db object, and then call a method on the Id object. I.e., you should only talk directly to the Db object. Not that the Law of Demeter is necessarily t…

If the code snippet returns a local ID object, then calling a method on the ID object doesn't violate the law of Demeter. It can be, in fact, the preferred method in the case that you don't have control over the db object. If your snippet doesn't return a local id object, then the violating portion should be idstring = db.findUserBySsNumber(ssNumber).toString(); println("id=" + idstring) A (perhaps) more clear illust…

I'm sorry for not being more clear. `db` is a service and the code snippet is client code.

I'm not sure what you mean by a "local object" (unless you are referring to C++'s stack-allocated objects). `Id` is a class defined by the service. The service doesn't know anything about the client code.

Re: Named Parameters in Java

#60
post #36
post #16

Earlier quoted context omitted.

This is a good observation, people who seem to like named parameters strike me as people who might code in plain text editors a lot. Nothing wrong with that but an IDE makes things so much easier and faster.

I think there's a kernel of truth to that but it's not entirely right. I use Pycharm for my python coding and still like named parameters because it makes clear at a glance what each parameter is in the function call. Otherwise, I'd need to click through to each function definition or use the "show doc" command to figure it out. It's much better to be able to scan through the code and understand it without interventi…

I guess I could see that but it might take me a few thousand lines for it to sink in. Makes sense stated the way you did. If you have to add a parameter though then you have to locate all of the locations and update them. With an object you just add the new field and its accessors if you want and then only the new section of code interested in that new field would be changed; but it's new so.
Post reply on HN