The Java 9 named parameter pitch

  • Post category:Java

In the previous post Daan van Berkel again made clear that a fluent API is so much more readable than the “regular” API’s. Unfortunately a lot of projects do not have the luxury of being able to convert their code to the fluent paradigm. But there are some easy improvements possible, one of them would be the introduction of named parameters.

Let me first start with a simple example:

    component.show(false, true);

Well, there is nothing wrong with that code, except as an outsider you have no clue what it is doing exactly. What do the two booleans indicate? This can only be solved by a round trip to the documentation. A fluent API would fix this:

    component.modal(false).centered(true).show();

But a lot of codebases cannot simply be converted to a fluent API, and fluent API’s are not easy to get right in the first place. Some developers improve bad readability by adding inline comments like so:

    show(false /*modal*/, true /*center*/);

That surely improves readability, but it also is very dangerous, because there is no validation that the comments actually match the meaning of the parameters. (Did I just now make an argument against comments, in contrast to my previous blog? Yes I did.) So what actually is needed is something like compiler checked comments; named parameters.

    show(modal:=false, center:=true);

This looks a lot more readable than the first example. What would happen here is that, given that the called method has parameter information available, the compiler would match that against the specified names. If they do not match, or no parameter information is available, named parameters would cause a compiler error. So there cannot be ‘incorrect comments’.

But if the compiler knows what parameters are expected and which are provided, then it can be smart about their sequence: it can rearrange the provided parameters to match the expected. So the compiler can rearrange this call to make it work correctly:

    show(center:=true, modal:=false);

The compiler knows the order of the parameters and at compile time can rearrange them to the correct order, in the end the resulting byte code should still be ‘just’ the old style call:

    component.show(false, true);

This approach is a compiler-only enhancement and perfectly backwards compatible. It improves readability, and allows for minor changes in the parameter sequence to not cause problems. And the minute the compiler is not sure what to do, it should throw a compiler error.

This Post Has 13 Comments

  1. Marcus Aurelius

    That’s a nice feature to have. You don’t need to create sophisticated builders, you only need to choose apropriate parameter names.

    However tome the killer feature for Java 9 would be Lombok integration. No more boilerplate! I can dream, right?

  2. adiguba

    This is not what i want to say…

    By introducing named’s parameters on all method, it also blocks the renaming parameters of all methods of all existing libraries in the Java world, because renamming a parameters will be a “source-incompatible” change.

    I think it is best to limit it to a few methods (that was the purpose of the annotation).

    1. tbeernot

      Your objections have been noted, I do not see them as big issues, or as the actual cause of the problem.

    2. Morad

      When you change a function or class name you’d go through the same amount of trouble, why should parameter names be any different?

      The example you mentioned with 1 letter parameters, that is usually common for functions with 1 arguments, in which case the role of the argument is known and there is no need for named parameters, named parameters are for functions with many parameters and if you look at those in common API’s you’d see they usually have nice and descriptive names.

      The only thing I fear from making parameter names part of the function signature is if they used that for overloading too, if that ever happens then god have mercy on us all…

      1. adiguba

        1. Trouble is different for parameter names, because after that you cannot rename any parameter names without potential “source incompatibility”.
        With method names you can use @Deprecated to “rename” the method…

        2. The problem if you add named parameter à-la-C# (by a compile-time syntaxic sugar like said in this article), it will be possible to use it on any method, even with 1 argument.
        So the simple fact of renaming a parameter will be a source of potential source incompatibility.

  3. tbeernot

    If you publish methods with bad parameter names, then no amount of annotations will make any difference.

  4. adiguba

    I am talking about changed like “centered”->”centering”, or most commons with bad-named parameters like simple letters one (“c”->”centered”).

    For example, if I want to change this method :
    public void setName(String s)
    into this:
    public void setName(String newName)

    It could introduce source-incompatibility with methods that used it with named parameters : setName(s:=”text”);
    Especially that EDI could generate such code automatically (and unreasonably).

    It could be a problem in large and massively used librairy (like Jakarta Commons…).

    1. tbeernot

      Yes, and I still consider it only a minor drawback. Publishing a method with a parameter named “s” or “c” is not something that should be done anyhow. So to me that is not a strong argument.
      But there is nothing preventing the coder to call the method the old style, without named parameters. That will still work of course, otherwise it would not have been backwards compatible. If you don’t like it, don’t use it.

      1. adiguba

        Yes but there are a lot of API with “one-letter” parameters, event in the standard API like String.contains(CharSequence s).
        The simple fact of having named’s parameter will stop developers to “correct” naming their parameters because it will be “source-incompatible”…

        It is not a question of liking or not this notation.
        When you publish an API you have no idea how it will be used by others developers.
        Event if yours methods are not intended to be used with named’s parameters, you can not prevent other developers to do so.

        I think this can be critical in some ways, and it must be considered…

        Perhaps by allowing API designers specify whether their methods can be used like that or not, for example via an annotation :

        @NamedParameters public void show(boolean modal, boolean center)

  5. adiguba

    Hello, (and sorry for my poor english)

    There is a big problem with this: the parameter name becomes as important as the method signature.

    The simple act of changing the name of a parameter can cause source incompatibility, without any possibility to do otherwise (with classes / methods can always use the deprecation to do this).

    1. tbeernot

      I don’t consider that a big problem, but a possible drawback. The question is if the drawback outweighs the gain, to me it does. Changing the name of a parameter could be quite a thing; say you change the one in the example from “centered” to “leftAligned”; that is quite a semantic difference but the original code and the inline comment example will still compile. Wouldn’t it be good that the compiler would detect such a major change? You are right that if you change it from “centered” to “centering”, in that case the change would be a nuisance.

      I think parameter names should be part of the signature; it denotes the meaning of the passed value.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.