PROPOSAL: Named method parameters

rssh at gradsoft.com.ua rssh at gradsoft.com.ua
Sat Mar 21 09:47:24 PDT 2009


Great,

One small note: I see requirements to programmer:
- pass parameters at same order
- write @PublicParameterNames in all places, where can be parameter names:
too restrictive.

1. Are really ordering parameters by names in call is difficult task ? In
worse case it is one extra loop.
2. For choosing policy to apply: parameter names by default if this is
possible, looks for me, much cleaner.

Also note, that exists implementation of embedding parameter names into
classfile and accessing ones via extensions of reflection API
  http://paranamer.codehaus.org/
Which (I think) can be mention here.


> I'd like to propose the implementation of optionally named method
> parameters, and suggest that they are particularly useful when creating
> immutable objects (which are important in our increasingly concurrent
> world).
>
> Note that this is a topic that seems to have been considered before (see
> the
> note in http://paulhammant.com/blog/announcing_paranamer.html which
> suggests
> that it was even considered for Java 6), but I can't see it in the current
> list of Java 7 changes or in the Project Coin mailing list archives
> (though
> others have also discussed it in relation to Java 7, such as Alex Miller
> in
> http://tech.puredanger.com/2007/08/15/dr-java7/ and
> http://tech.puredanger.com/2007/10/11/java7-roundup-32/).  Therefore I am
> proposing it here - I think that it is an important change (unless anyone
> can suggest how I can reasonably create an immutable object with four or
> more properties without using a Builder or a list of unnamed parameters).
>
> Also note that other relevant references include:
> http://blogs.sun.com/abuckley/entry/named_parameters (which discusses why
> parameter reordering might be difficult),
> http://beust.com/weblog/archives/000096.html (which suggests that we do
> not
> need named parameters, but really just shows the use of the Builder
> pattern
> which has limitations).
>
>
> Named method parameters
>
> AUTHOR(S):
>
> Paul Martin
>
> OVERVIEW
>
> FEATURE SUMMARY:
>
> Named parameters allow a method or constructor caller to explicitly state
> the parameter name of each parameter value passed to the method or
> constructor.  Without named parameters, only the order of the parameter
> values is significant (and it may not be clear what each value
> represents).
>
> MAJOR ADVANTAGE:
>
> This is a relatively simple way of introducing named parameters to the
> Java
> platform.
>
> MAJOR BENEFIT:
>
> Named parameters allow method calls with relatively long lists of
> parameters
> (greater than 3) to be understood by developers.  This can also facilitate
> the direct use of constructors and factory methods to create immutable
> objects, where otherwise Builders or mutable JavaBeans would be required.
>
> MAJOR DISADVANTAGE:
>
> The syntax for method calls would change to allow both named and unnamed
> parameters to be used.
>
> Named parameters might be used too often, which could unnecessarily
> clutter
> source files.
>
> Metadata to store the names of the parameters must be added to classfiles
> (for example as annotations).
>
> The use of annotations to describe named parameters would mean that no
> metadata would be stored about the parameter names used by the method
> caller, and so no runtime checks to match the parameter names being used
> could be made (only compile-time).  If the parameter names change (but
> otherwise the method signature does not), then the method caller would not
> be aware of the changes until it was recompiled.  Note that this is
> existing
> behaviour for unnamed parameters, and would only be a problem if the
> meaning
> of the parameters also changes (which should indicate that the caller
> would
> need to change anyway, but this would not be detected automatically at
> runtime).
>
> ALTERNATIVES:
>
> Unnamed parameters can make the same method calls as named parameters, but
> if there are many parameters they are harder to understand and prone to
> ordering-related bugs (particularly for primitive types or Strings).
>
> The Builder pattern can be used to simulate named parameters in
> constructors/factory methods.  For example the following class uses a
> Builder to initialise itself (note that only two properties are used to
> simplify the example):
>
>     public final class MyClass {
>
>         private final String name;
>         private final int age;
>
>         private MyClass(Builder b) {
>             this.name = b.name;
>             this.age = b.age;
>         }
>
>         public static class Builder {
>
>             private String name;
>             private int age;
>
>             /**
>              * Name to set.
>              */
>             public Builder setName(String name) {
>                this.name = name;
>                return this;
>             }
>
>             /**
>              * Age to set
>             */
>             public Builder setAge(int age) {
>                 this.age = age;
>                 return this;
>             }
>
>             public MyClass build() {
>                return new MyClass(this);
>             }
>         }
>     }
>
> Objects can then be constructed in the following manner:
>
>     MyClass obj = new
> MyClass.Builder().setName("Fred").setAge(53).build();
>
> However, the use of a builder requires additional code, and all parameters
> are effectively optional from the perspective of the compiler (it cannot
> easily check that all of the required setter methods have been called), so
> bugs may occur where parameter values are not set.  Note that runtime
> checks
> can be made to ensure that all property values are set, but they involve
> additional work and cannot be used by the compiler (though static analysis
> of the code in conjunction with annotations might be able to repeat many
> of
> these checks).
>
> There are also many ways to implement named parameters that are different
> to
> the solution proposed here.  These include:
>
> Implement optional named parameters on all methods:  This avoids the need
> for the @PublicParameterNames annotation, but may mean inconsistent usage
> of
> named parameters - the annotation is also a suggestion for the use of
> named
> parameters by the caller (which IDEs can also make use of).  This will
> also
> highlight the difference to classfiles compiled with earlier versions of
> Java, where named parameters cannot be used at all (since it will then not
> be obvious when named parameters can and cannot be used).
>
> Add parameter names to the classfile as 'fundamental' method metadata
> rather
> than as annotations: This may allow closer integration of the named
> parameters with the rest of the language, but its impact on the rest of
> the
> language (and JVM) is much greater.  The same inconsistencies and
> incompatibilities described in the previous alternative would also apply.
> In addition, the use of annotations should not preclude the subsequent
> modification of classfiles in a later release - the annotations could
> still
> remain (at a potential cost of some duplication).
>
> EXAMPLES
>
> SIMPLE EXAMPLE:
>
> Constructor declaration:
>
>     @PublicParameterNames
>     public MyClass(String name, int age) { ....
>
> Constructor use:
>
>     MyClass obj = new MyClass(name: "Fred", age: 53);
>
> ADVANCED EXAMPLE: Show advanced usage(s) of the feature.
>
> The full class definition from the simple example is shown below, as a
> contrast to that provided in the Builder example.
>
>     public final class MyClass {
>
>         private final String name;
>         private final int age;
>
>         /**
>          * @param name Name to set
>          * @param age Age to set
>          */
>
>         @PublicParameterNames
>         public MyClass(String name, int age) {
>             this.name = name;
>             this.age = age;
>         }
>     }
>
> DETAILS
>
> SPECIFICATION:
>
> The @PublicParameterNames annotation is used on a constructor or method to
> allow named parameters to be used when calling it.  It can also be applied
> to a class or package to apply to all methods within.  Similarly, a
> @NoParameterNames annotation can be used on a constructor, method, or
> class
> to override the use of @PublicParameterNames at a higher level.
>
> The compiler can then automatically generate a
> @PublicParameterName(value="parameter-name") annotation for each affected
> method.  These can then be used by the compiler (and IDE) to validate the
> parameter names used by callers of the method or constructor.
>
> The use of parameter names by callers is always optional (primarily for
> backwards compatibility).  However, parameter names cannot be used for
> some
> parameters and not others (this would make the code harder to read).
>
> Parameters must always be specified in the same order regardless of
> whether
> parameter names are used - parameter reordering by callers is not allowed
> (reordering would make overloading difficult, and is not really
> necessary).
>
> Inheritance: Neither the @PublicParameterNames annotation (and
> @NoParameterNames annotation), or the names of the parameters themselves,
> need to be inherited.  This is because only static evaluation of a
> caller's
> parameter names will be applied (rather than at runtime), so the callers
> parameter names only need to match those of the declared type of the
> target.  However, it would still be advisable to reuse the same parameter
> names and annotations when overriding a method (IDEs could help with
> this).
>
> COMPILATION:
>
> The compiler must automatically generate a
> @PublicParameterName(value="parameter-name") annotation for each method
> and
> constructor annotated with @PublicParameterNames (or whose the parent
> class
> or package is annotated with @PublicParameterNames and the child class or
> method does not override it with @NoParameterNames).
>
> For example:
>
>     int myMethod(int param1, String param2)
>
> Would effectively become:
>
>     int myMethod(@PublicParameterName("param1") int param1,
> @PublicParameterName("param2") String param2)
>
> Method-calling syntax would need to change, using a colon to separate the
> parameter name and value where the are used.  For example:
>
>    MyClass obj = new MyClass(name: "Fred", age: 53);
>
> When a method caller uses parameter names, the compiler must check that
> those parameter names exactly match the value of generated
> @PublicParameterName annotations of the target method or constructor.  It
> is
> a compilation error if they do not match or the target method or
> constructor
> does not have named parameters.
>
> IDEs can use the @PublicParameterNames and @NoParameterNames annotations
> (or
> @PublicParameterName directly) to automatically insert the relevant
> parameter names as part of code-completion.  Additional refactoring
> support
> would also be required to enable parameter names to be renamed, or added
> and
> removed completely.
>
> Frameworks such as Spring can use the same annotations to allow objects to
> be created from their configuration files using named parameters to
> constructors and factory methods.  Currently they only allow objects to be
> created from configuration files as JavaBeans (with setter methods) or
> with
> ordered (and unnamed) parameters.
>
> TESTING:
>
> The feature can be tested by compiling and running programs that exercise
> the feature.
>
> LIBRARY SUPPORT:
>
> No.
>
> REFLECTIVE APIS:
>
> java.lang.reflect.Method and java.lang.reflect.Constructor could be
> enhanced
> with new methods that return parameter names.  However, that is not
> required
> to successfully implement the proposal.
>
> OTHER CHANGES:
>
> No.  The use of named parameters is always optional.  The javadoc tool
> already documents parameter names.  Other tools/libraries might benefit
> from
> these changes, but their use is not required.
>
> MIGRATION:
>
> The @PublicParameterNames annotation (and @NoParameterNames annotation)
> simply needs to be added to the appropriate methods.  IDEs could then
> suggest the use of parameter names for the method's callers, and apply the
> changes automatically.
>
> COMPATIBILITY
>
> BREAKING CHANGES:
>
> No.
>
> EXISTING PROGRAMS:
>
> The changes required by this feature should be transparent to existing
> source and class files if annotations are used internally to describe the
> named parameters.  I am not sure what the impact would be otherwise.
>
> REFERENCES
>
> EXISTING BUGS:
>
> 4124331 (though it is set to 11-Closed, Will Not Fix, request for
> enhancement, and from 1998)
>
>





More information about the coin-dev mailing list