Live data from Hacker News

Named Parameters in Java

java.dzone.com

41–50 of 62 posts

Re: Named Parameters in Java

#41
post #22

Earlier quoted context omitted.

Hmm, I've never seen Demeter interpreted to mean that you should favour primitives over rich types. Can you explain your interpretation?

I've heard the Law of Demeter at times stated explicitly as that you should usually return only primitive data types from an API. Rich Hickey certainly claims this too, although he doesn't refer to it as the Law of Demeter. The Law of Demeter is also sometimes summarized by "One dot: good. Two dots: bad." Or from Wikipidia: In particular, an object should avoid invoking methods of a member object returned by another…

That has nothing to do with primitive types. Otherwise in Java it would mean you shouldn't return a String ever because it's not primitive! It has nothing to do with primitive types whatsoever. It's about encapsulation, i.e. you should not depend on the internal structure of an object.

As a simple example, when one wants to walk a dog, one would not command the dog's legs to walk directly; instead one commands the dog which then commands its own legs.

i.e. this is violating the law: dog.getLegs().walk()

and should instead be written: dog.walk()

with this implementation:

  class Dog { 
    void walk() { legs.walk(); }
  }

Re: Named Parameters in Java

#42
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…

I think types are orthogonal to why named parameters are helpful, because parameters don't just indicate a type but a particular usage of a type.

So for example, in a bank transfer method the named parameter would help distinguish the from-account from the to-account. The accounts are already not simple types, but their usages (roles in the sentence underlying the semantics of the method) are different.

You could create a "transfer" class of course for the pair of accounts, but are we going to do this for each combination of usages of our types. Hopefully not - we'd basically be encoding each combination of parameters that our methods accept into an object - not practical or productive in my opinion.

Re: Named Parameters in Java

#43
post #32
post #8

Interesting. But it looks like it is solving a problem with another problem. The receiving class would then look like this: public void doSomething(Name name, Link link, UltimateAnswer ultimateAnswer, TempFile tempFile, Zip zip) { String name = name.name; String link = link.link; int ultimateAnswer = ultimateAnswer.ultimateAnswer; String tempFile = tempFile.tempFile; int zip = zip.zip; } If the problem is "I don't li…

I'm not sure I see the "another problem" you're referring to. Can you describe the problem with the new implementation of doSomething()? Also, I don't think the original problem was the same values being used all over the place. The problem is how to be clear about which parameters you're providing, and accepting static types and giving the type a simple way of constructing it solves that.

The other problem is that

  int zip = zip.zip;
is just silly, even by Java's standards.

Re: Named Parameters in Java

#44
post #22

Earlier quoted context omitted.

Hmm, I've never seen Demeter interpreted to mean that you should favour primitives over rich types. Can you explain your interpretation?

I've heard the Law of Demeter at times stated explicitly as that you should usually return only primitive data types from an API. Rich Hickey certainly claims this too, although he doesn't refer to it as the Law of Demeter. The Law of Demeter is also sometimes summarized by "One dot: good. Two dots: bad." Or from Wikipidia: In particular, an object should avoid invoking methods of a member object returned by another…

The Law of Demeter isn't about data encapsulation. It's trying to solve the problem of tightly-coupled code methods. It is a close cousin of "Don't get data from objects and operate on them- ask the contain object to do the operation for you." The Law of Demeter says, "Don't call a method on an object that was returned by a method of a different object." When you do this you are creating a tightly-woven daisy-chain which will lead to inter-dependency hell should something change in the future. Instead, you should either (1) ask the object you are calling to call the other object for you, or (2) call the third object method directly, without relying on the intermediary to get it.

In other words, with objects X, Y and Z. Assume that X has Y. You want to run method fz on Z. Don't do:

  Y.getZ().fz
Do do:

  Y.runFz()  // calls Z.fz
or instantiate a copy of Z in X and simply

  Z.fz
The data encapsulation principle is also about keeping things loosely coupled. By passing data around as an object, the interested parties need to care far less about the details (that is, their signatures don't change EDIT:TYPO _as_ the code changes).

This is a really good thing to do in the "build early and try it" style of building projects as adding data (parameters) to the signature is relatively painless.

Re: Named Parameters in Java

#45
post #9

Wouldn't the Builder pattern address this issue? So you can do: object.setName("Alfred E. Neumann") .setLink(" http://blog.schauderhaft.de ) .setUltimateAnswer(42) .setTempFile("c:\\temp\\x.txt") .setZip(23);

I think this way is better:

  o.doSomething({
    name : "Alfred E. Neumann",
    link : "http://blog.schauderhaft.de,
    ultimateAnswer: 42,
    tempFile: "c:\\temp\\x.txt",
    zip : 23});

Re: Named Parameters in Java

#46
post #45
post #9

Wouldn't the Builder pattern address this issue? So you can do: object.setName("Alfred E. Neumann") .setLink(" http://blog.schauderhaft.de ) .setUltimateAnswer(42) .setTempFile("c:\\temp\\x.txt") .setZip(23);

I think this way is better: o.doSomething({ name : "Alfred E. Neumann", link : "http://blog.schauderhaft.de, ultimateAnswer: 42, tempFile: "c:\\temp\\x.txt", zip : 23});

another example of Builder pattern http://goo.gl/NkAhE

Re: Named Parameters in Java

#47
post #41

Earlier quoted context omitted.

I've heard the Law of Demeter at times stated explicitly as that you should usually return only primitive data types from an API. Rich Hickey certainly claims this too, although he doesn't refer to it as the Law of Demeter. The Law of Demeter is also sometimes summarized by "One dot: good. Two dots: bad." Or from Wikipidia: In particular, an object should avoid invoking methods of a member object returned by another…

That has nothing to do with primitive types. Otherwise in Java it would mean you shouldn't return a String ever because it's not primitive! It has nothing to do with primitive types whatsoever. It's about encapsulation, i.e. you should not depend on the internal structure of an object. As a simple example, when one wants to walk a dog, one would not command the dog's legs to walk directly; instead one commands the do…

By "primitive data types" I didn't mean to exclude built-in collections of primitive data types. Point taken, though: I probably should have said "built-in data types", or some such. I didn't even mean to exclude algebraic data types, as I explicitly mentioned.

Though I think that the question of whether algebraic datatypes should be allowed is an interesting one. Also, clearly allowed would be any objects provided by the standard library, since returning those would not couple your code to the code of the API.

As Rich Hickey expresses it, I believe, you should only return from an API data that you could send over the wire without sharing any of the API's code. If you stick to this rule, then, for instance, it is much easier to make your application distributed.

(Though I'm not sure to what degree Hickey and The Law of Demeter would agree on everything. E.g., returning some hairy nested dictionary of dictionaries of dictionaries of strings to represent a book, or what have you. I don't know what Rich Hickey would say about that.)

Re: Named Parameters in Java

#48
post #44

Earlier quoted context omitted.

I've heard the Law of Demeter at times stated explicitly as that you should usually return only primitive data types from an API. Rich Hickey certainly claims this too, although he doesn't refer to it as the Law of Demeter. The Law of Demeter is also sometimes summarized by "One dot: good. Two dots: bad." Or from Wikipidia: In particular, an object should avoid invoking methods of a member object returned by another…

The Law of Demeter isn't about data encapsulation. It's trying to solve the problem of tightly-coupled code methods . It is a close cousin of "Don't get data from objects and operate on them- ask the contain object to do the operation for you." The Law of Demeter says, "Don't call a method on an object that was returned by a method of a different object." When you do this you are creating a tightly-woven daisy-chain…

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` were just a string to begin with!

Also, now we're physically dependent on db's data structures (i.e., `Id`). If we were to want to move `db` to be on a server, we would have to share at least some of the server's code. If `id` were just a string, we would be less tightly coupled to `db`.

Re: Named Parameters in Java

#49

Wow this would make for some crazy code to try to read thru. I would be über-pissed to trace thru code like this only to find all of these wrapper classes. This is what Javadocs are for, it's much easier and cleaner just to document your code as you write it.

> I would be über-pissed to trace thru code like this only to find all of these wrapper classes.

Why? I think this code is better; to demonstrate why, I'll deconstruct the first example -- names.

Names aren't strings. Names are multi-component entities comprised of strings with rather complex internationalization rules regarding composition.

To properly represent a name, you need the set of fields that compose the name, along with a 'full name' (historically in x.500 and LDAP this is called the 'commonName') that is pre-composed according to the users preference.

Some of the individual components you'll need if you wish to compose names:

- Surname [may be more than one]

- Middle name [may be more than one]

- Given name [may be more than one]

- Prefix (title, etc) [may be more than one]

- Suffix (IIrd, etc) [may be more than one]

- Nick name

The rules for composition can be complicated, so you'll want to centralize them somewhere. Also, you may not want to build a super-complex name class now, but later you might need to start sending out e-mails with "Mr. Psuedonym" at the top.

So how do you handle this?

CREATE A CLASS.

Names aren't strings. Most things aren't strings, though they may be represented as strings. Create a class now and make it easy to extend types later.

Treating everything as strings and ints throws away more than just the type system -- it throws away much of the code maintenance value of OO!

That's just names. His example also uses file paths, and file paths are actually quite similar to names; they're composed of multiple components, they have very specific rules regarding composition and normalization, and unlike names, you can easily introduce security issues by incorrectly handling file paths (eg, failure to correctly normalize a path before applying security checks).

This is why we create File classes that handle normalization/composition/decomposition of path names. As a side effect, it also helps constrain the types of your method calls.

Personally, I'm "über-pissed" when I trace through code that uses raw "string & int programming" and does not properly leverage types. It makes for messy code that does not properly take advantage of OO encapsulation and is difficult to read, difficult to type-check, is difficult to maintain, and even more difficult to build on.

Re: Named Parameters in Java

#50
post #44

Earlier quoted context omitted.

The Law of Demeter isn't about data encapsulation. It's trying to solve the problem of tightly-coupled code methods . It is a close cousin of "Don't get data from objects and operate on them- ask the contain object to do the operation for you." The Law of Demeter says, "Don't call a method on an object that was returned by a method of a different object." When you do this you are creating a tightly-woven daisy-chain…

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.
Post reply on HN