Annotations for method overloading.

96 views
Skip to first unread message

h1Suggester

unread,
Oct 28, 2024, 7:46:21 AM10/28/24
to Project Lombok
### Feature Proposal: `@Default` and `@Jumbled` Annotations

#### 1. `@Default` Parameter Annotation

**Objective**: Introduce an annotation that enables default values for method parameters, automatically generating overloaded methods that exclude these parameters and provide default values.

**Proposal**:  
When the `@Default` annotation is applied to a method parameter, Lombok would generate variants of the method that exclude the annotated parameters. The excluded parameter values would default to the specified values in their native types, reducing the need for repetitive method overloading.

**Example**:
```java
public class Example {
    // Annotate parameters with `@Default` to specify default values in the correct types
    public void display(
        String message,
        @Default(10) Integer number,
        @Default(true) Boolean isVisible
    ) {
        System.out.println("Message: " + message + ", Number: " + number + ", Visible: " + isVisible);
    }
}
```

**Generated Code**:
```java
public class Example {
    public void display(String message) {
        display(message, 10, true);
    }

    public void display(String message, Integer number) {
        display(message, number, true);
    }

    public void display(String message, Boolean isVisible) {
        display(message, 10, isVisible);
    }

    public void display(String message, Integer number, Boolean isVisible) {
        System.out.println("Message: " + message + ", Number: " + number + ", Visible: " + isVisible);
    }
}
```

**Benefits**:
- Reduces boilerplate by automating the creation of overloaded methods.
- Simplifies method invocation when optional parameters are frequently set to default values.
- **Enables New Design Patterns**: This pattern provides a simplified alternative to traditional builder patterns by allowing methods with flexible parameters, helping developers achieve fluent and configurable method calls without implementing a separate builder class.

---

#### 2. `@Jumbled` Method Annotation

**Objective**: Enable the generation of all valid permutations of method parameter orders, accommodating flexible calling structures where parameter order might vary.

**Proposal**:  
When the `@Jumbled` annotation is applied to a method, Lombok would generate methods for all possible parameter order combinations. This is especially useful in testing, reflection, and dynamic invocations, where parameter order flexibility is beneficial.

**Example**:
```java
public class Example {
    @Jumbled
    public void display(String text, Integer number, Boolean flag) {
        System.out.println("Text: " + text + ", Number: " + number + ", Flag: " + flag);
    }
}
```

**Generated Code**:
```java
public class Example {
    public void display(String text, Integer number, Boolean flag) {
        System.out.println("Text: " + text + ", Number: " + number + ", Flag: " + flag);
    }

    public void display(Integer number, String text, Boolean flag) {
        display(text, number, flag);
    }

    public void display(Boolean flag, String text, Integer number) {
        display(text, number, flag);
    }

    // Other permutations would also be generated here
}
```

**Benefits**:
- Allows for flexible method invocation regardless of parameter order.
- Useful in dynamic programming contexts where parameter order is not guaranteed.
- **Supports Alternative Patterns**: This capability adds versatility to method overloading, achieving pattern flexibility similar to builder-like structures, where developers can pass parameters in various orders without affecting method behavior.

---

#### Summary

These annotations, `@Default` and `@Jumbled`, offer significant boilerplate reduction, method flexibility, and support for fluent, pattern-driven design. This aligns well with Lombok’s goal of minimizing repetitive code, providing developers with flexible configurations similar to builder patterns, all without requiring separate classes.

Reinier Zwitserloot

unread,
Oct 28, 2024, 9:15:16 AM10/28/24
to Project Lombok
The itch "I have a method and I want certain parameters to be optional, to be filled with a default value if not provided" comes up _a lot_.

However, addressing it is incredibly complicated; There are a million and one ways to deliver on this request, and they differ _wildly_. Many of these ways have separate power v. cost tradeoff (i.e. some takes are really, _really_ powerful but also require multiple person-months of work to e.g. improve resolution, or add IDE plugins).

I'm gonna come across as 'cynical old man yells at clouds', but, the proposal you have provided is where we were at 15 years ago. It doesn't work. Specifically, in java annotations have a parameter structure that is entirely predefined and not type-abstractable in any way. In other words, have one annotation that you can use both as `@Default(10)` as well as `@Default("Hello")` __is not possible in java__. We have sent in proposals to make that possible, and they were rejected. You can attempt to dance around it (instead you'd have `@IntDefault` which is ugly as your parameter is _already_ `int` typed, so now we are repeating ourselves), but you've now restricted yourself to allowing only defaults of inherently known java concepts that we (lombok) provide for you (numbers, strings, maaaybe lists, null, true, false, that's it probably). 

A second problem you haven't tackled is ambiguity. Using your exact proposal but changing the  `display` method's signature to `String message, String number, String isVisible` instead - do that exercise, apply the same transformation you are. The end result wouldn't compile (multiple methods with identical signatures).

A third: The problem of combinatory explosions (lets say a method with 8 parameters, all of which have a `@Default` annotation, and let's say there are no type conflicts. Do we generate 256 methods? If the answer is 'no', why not? What part of your proposal guides how to deal with such a situation?)

This is a little rude of me, but, you're 10+ years behind the discussion and it's hard to just 'catch you up'; there are, literally, about 40 more items on this list of 'this is a problem you are going to run into', and you need to know them all in order to get a discussion going on the edge of possibility where we've been for a few years now.

You can go and write some of these as plain jane Annotation Processors that create the explosion of methods as static utility methods. Something like this:

```
// you write exactly what you wrote in your example. An AP produces as entirely new file:

public class ExampleDM { // DM = DefaultMethods
  public static void display(Example ex, String text) {
    ex.display(text, 10, true);
  }

  public static void display(Example ex, String text, Integer number) {
    ex.display(text, number, true);
  }

  // and so on
}
```

If you had done that, and took it through its paces, you'd have run into all 3 problems. Hence, doing that is probably table stakes if you want to join in the discussion and provide meaningful ideas as to how we solve the general problem of 'how do we make default parameters easy in java with lombok'.

@Jumbled has fewer issues but also seems mostly useless to me. I don't think that's worth the maintenance burden to add, and more generally having multiple ways to do the same thing in an API is _a bad thing_ - it leads to style fights. Maybe there's an exception here, but I don't think so. Providing arguments to a method invocation such that multiple overloads each could possibly apply is notorious for being confusing, and `@Jumbled` makes it very, _very_ easy to step into that trap unwittingly. In other words, I'm pretty sure it's a foot-gun: A tool that looks nice and is highly likely to ruin your codebase. That's the kind of feature lombok goes out of its way __not__ to add.

A few more important points:

* Don't handcuff yourself to either your idea or how java coders solve this today. If the best answer is an IDE plugin, then that should be on the table.
* `@Builder` already solves all these problems but in a bit of an overwrought way. Still, it's there and it's a big reason why we aren't investing more time in it. Got a method with tons of parameters? Stick `@Builder` on it; much better than going ham on adding overloads for it.

> These annotations, `@Default` and `@Jumbled`, offer significant boilerplate reduction, method flexibility, and support for fluent, pattern-driven design.

General tip - don't do this. I hate weaselwords and that sentence is filled with em. "Significant"? You can say it but that doesn't make it true. I'm not disagreeing with you, merely pointing out that this sentence feels like you're a second hand car salesman trying to sell me something. None of it is stated in falsifiable or objective ways.

How does this support 'fluent design'? What does 'fluent design' even mean? Because none of these words are locked down there's no debate we can hold.

I'm not saying you should link those terms to their definitions. I'm saying you shouldn't include such sentences at all; you do not need to make the case for `@Default`, it's made. We need to come up with a feature that solves the problem which so far we haven't been able to design (and your design is insufficient; see above).

You do need to make the case for jumbled, but a one-liner with weasel words is the exact opposite: It makes me feel more strongly its a bad idea. Such a case would likely comprise many tens of pages, include analyses of java code bases (github is right there, a good font of java code you can search), and even then likely will be shot down. You're fighting against the grain here - it's a problem that you _can_ solve with boilerplate (by making overloads) and that no API I'm aware of has chosen to do. That means the level of annoyance API designers have that you can't jumble your arguments is lower than the meagre bar of adding those overloads, i.e. it's really low. So you'd have to make the case that all API designers are wrong. Which is possible, but, an extraordinary claim that will require extraordinary evidence.
Reply all
Reply to author
Forward
0 new messages