8 ms·
Named Parameters in Java
- PaulHoule 14y agoIt might be crazy but I like this kind of DSLization of Java a lot
- bartonfink 14y agoI think it would really shine with IDE support. It probably wouldn't even be that hard to do (famous last words). I think I'll take a stab at it. I like it as well, and have done similar things by creating input/output classes to use as "structs" when the list of parameters gets unweildy or when I want multiple returns.
- tkellogg 14y agoWhen "the list of parameters gets unweildy" and "I want multiple returns" are to major indicators that you got some anti-patterns going on. I think the refactoring that you need might a new class with a single responsibility.
- gizmo686 14y agoOr they are indicators that you have experience in languages that allow such designs, and would like java to introduce them. My biggest problem with java is that it tried to be a single paradigm langues: object oriented. While it was doing that, people worked on developing other methods. Concepts from these other systems are beggining to creep into java. For example, generics are a functional concept, as are lambdas which will be introduced in the next version.
- kd0amg 14y agoIt doesn't seem all that crazy to me. I wouldn't be surprised to see an ML programmer write something like datatype name = Name of string and this is just the way to express that in Java.
- peeters 14y agoI've seen a pretty big move in popular libraries to fluent interfaces. It does a pretty good job of getting over the verbosity in Java (at least where the verbosity hurts readability). Examples like Guava: Cache<String, User> userCache = CacheBuilder.newBuilder() .initialCapacity(7) .expireAfterWrite(20, TimeUnit.MINUTES) .build(); Or Hamcrest: assertThat(result, containsString("OK")); Or Rest-Assured: expect().statusCode(200).when().get("/user/1");
- josemando 14y agoComing back to Java after learning Objective-C made realize how named parameters are awesome
- SeanLuke 14y agoObjective-C doesn't have named parameters (that is, Lisp-like "keyword" parameters). It has a hack which allows a method to be so named that it has to be used in a named way. Named parameters can be in any order and may or may not exist in the function call. Obj-C can't do this because its "names" are actually just part of the method signature. It's fake.
- sbmassey 14y agoIt may be "fake", but it still has the property that this article was looking for, in that it is obvious to the reader what each of the arguments being passed to the method are for.
- dhimes 14y agoWhoever 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 (when ID needs change, and they will over the course of a project) without breaking the interface. And that's the point of it all.
- TazeTSchnitzel 14y agoNever 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.
- jebblue 14y agoWhen I program in Python I would do it the same way, create a class that represents the types. The class can be made into a persistence class easily, this approach is clear, readable and maintainable. Oh and I try to avoid JavaScript, too much clever coding makes it a hard language to maintain.
- nessus42 14y agoNamed tuples are nice in Python. I wonder how easy it is, though, to modify a namedtuple constructor to do argument validation and to allow for default field values.
- TazeTSchnitzel 14y agoIf you see how namedtuple is implemented, you'd realise it's extremely easy. namedtuple uses eval(). It really shouldn't, since there are far better ways to do what it does, but it does.
- dhimes 14y ago
- jasonkolb 14y agoWow 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.
- tsewlliw 14y agoThis. I'd do my best to make sure the authors contributions stopped. Type safety obviously doesn't protect you the worst possibilities in software.
- flatline3 14y ago> 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.
- columbo 14y agoInteresting. 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 like these SAME values being used all over the place" then use DEFAULTS. o.doSomething1(); //defaults to "Alfred","c:\\temp",42,"shadurhaft.de",23 That or pass in an object. o.doSomething1(mySomethingObject); If the values are genuinely different then the only way to solve this problem is to validate the options (paths should be a valid file location and not a website, websites should be a valid website etc) and then (possibly) pass in an object instead of primitives. I don't see encapsulation doing anything really, aside from increasing the number of "junk" classed by about a hundred fold. Why throw standard convention out the window?
- peeters 14y agoI'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.
- jlgreco 14y agoThe other problem is that int zip = zip.zip; is just silly, even by Java's standards.
- cpt1138 14y agoWouldn't the Builder pattern address this issue? So you can do: object.setName("Alfred E. Neumann") .setLink("http://blog.schauderhaft.de http://blog.schauderhaft.de) .setUltimateAnswer(42) .setTempFile("c:\\temp\\x.txt") .setZip(23);
- Aykroyd 14y agoThat would definitely be a nicer way to do it. Although, using the builder pattern to create parameters for every single method in your API would be a gigantic pain. Javascript APIs hack this in by taking Objects as params so that you can do {name='Alfred E. Neuman'...}. Unfortunately, Java's syntax isn't nice for creating Maps either, but maybe you could do something with that. In the end, this seems like a problem with the language syntax and any fix other than one at the language level is going to be a hack.
- moondowner 14y agoor ObjectName.getBuilder("Alfred E. Neumann", "http://blog.schauderhaft.de http://blog.schauderhaft.de, 42, "c:\\temp\\x.txt", 23).build(); maybe? It's not addressing named parameters issue, but I find it better like this.
- devgutt 14y agoI 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});
- javinpaul 14y agoanother example of Builder pattern http://goo.gl/NkAhE http://goo.gl/NkAhE
- x3eme 14y agoor you know, use an IDE!
- jebblue 14y agoThis 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.
- Aykroyd 14y agoI 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 intervention from IDE features.
- jebblue 14y agoI 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.
- jebblue 14y agoI would not use a separate class per parameter though that is a clever solution. It might hurt performance and it just feels a bit heavy. For performance, clarity and reusability I would simply create a class that holds the values needed. Add an @Entity tag and now it can be used as a Hibernate persistence class too.
- pathdependent 14y agoAlthough the solution produces too many problems, I agree that named parameters are highly desirable for readability and the prevention of bugs. Have there been any proposals for Java 8 to included named parameters? Edit: * http://openjdk.java.net/jeps/118 http://openjdk.java.net/jeps/118 proposes run-time storing of parameter names -- not what is desired, but in the same ballpark. * http://web.archiveorange.com/archive/v/bobySzLnuDWgr47zqwU9 http://web.archiveorange.com/archive/v/bobySzLnuDWgr47zqwU9 proposes named arguments for making clean code.
- bad_user 14y agoThe problem with named parameters is that suddenly method parameters become part of your exposed API. The other problem is that the compiler currently discards the parameter names, so older binaries are not going to be compatible.
- erode 14y agoI use named parameters in csharp, and they are nice, but they're not worth all that extra effort. The code is now much more confusing.
- bchen 14y agoSince long parameter list is considered a code smell, people should be discouraged from writing this kind of code anyways. Namely, this example from the article is in fact a bad practice: > o.doSomething1("Alfred E. Neumann", "http://blog.schauderhaft.de http://blog.schauderhaft.de, 42, "c:\\temp\\x.txt", 23); As other commenters have pointed out, I think the builder pattern is one of the two solutions I would use. The other solution is to simply create an object that represents the values to be passed in to the method. Consider: User user = new User("Alfred E. Neumann"); user.setLink("http://blog.schauderhaft.de); user.setUltimateAnswer(42); user.setTempFile("c:\\temp\\x.txt"); user.setZip(23); o.doSomething(user); Even with named parameters, I would say the latter approach is still superior than having a long parameter list.
- yarrel 14y agoNamed parameters would result in more readable, compact, and efficient code compared to the latter approach. But yes, long parameter lists (whether represented as argument structs or not) generally indicate a problem.
- hnriot 14y agoThis, like many of the proposed solutions here exposes the issue that putting the (not particularly) long list of parameters into the ctor, that of not every being able to call doSomething without all the required values. What is the caller of your builder doesn't remember to set the zip and the doSomething method then uses it? You've only really added syntactic sugar and sacrificed functionality.