Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE] Strict builder annotation #3367

Open
3DRaven opened this issue Mar 9, 2023 · 2 comments
Open

[FEATURE] Strict builder annotation #3367

3DRaven opened this issue Mar 9, 2023 · 2 comments

Comments

@3DRaven
Copy link

3DRaven commented Mar 9, 2023

Describe the feature
I think need to create new annotation @StrictBuilder with realization of Builder with checking by compiler of full initialization. And annotation @StrictBuilders for multiple chains of initialization calls. As example it is "lomboked" code.

@StrictBuilder
public class Person {
    private final String username;
    private final int age;
}

//Allowed usage
Person.builder().username("Alice").age(10).build()
//Impossible usage
Person.builder().username("Alice").build()

Code without lombok

public class Person {
    private final String username;
    private final int age;

    Person(PersonBuilder personBuilder) {
        this.username = personBuilder.username;
        this.age = personBuilder.age;
    }


    public static PersonUsernameBuilder builder() {
        return new PersonUsernameBuilder();
    }


    public static class PersonUsernameBuilder {
        public PersonAgeBuilder username(String username) {
            return new PersonAgeBuilder(username);
        }
    }

    public static class PersonAgeBuilder {
        public final String username;

        PersonAgeBuilder(String username) {
            this.username = username;
        }

        public PersonBuilder age(int age) {
            return new PersonBuilder(username, age);
        }
    }

    public static class PersonBuilder {
        public final String username;
        public final int age;

        PersonBuilder(String username, int age) {
            this.username = username;
            this.age = age;
        }

        public Person build() {
            return new Person(this);
        }
    }
}

This annotation generate builder for all final fields in class. But with this approach you can have multiple chains of sub builders, so you can have set of some controlled fields combinations not only all fields. This is second variant of annotation - @StrictBuilders. Example:
annotation with multiple "sub builders chains". All fields builder with this annotation must not generated by default. Order of fields in "fields" annotation parameter it is order of fields in generated sub builder.

@StrictBuilders({
        @StrictBuilders.FieldSet(name = "onlyUserBuilder", fields = {"username"}),
        @StrictBuilders.FieldSet(name = "onlyAgeBuilder", fields = {"age"})
})
public class Person {
......
}

//Usage
Person.onlyUserBuilder().username("username").build()
Person.onlyAgeBuilder().age(10).build()
//Imposible usage
Person.onlyUserBuilder().username("username").age(10).build()

Describe the target audience
Lombok annotation @Builder has some problems with partially initialized classes. So, in some projects and companies this annotation totally restricted. This annotation for this projects.
Additional context
Based on this gist: https://gist.github.com/3DRaven/9a11ef9d0c42df6bf5603628327d88b3

@janrieke
Copy link
Contributor

janrieke commented Mar 9, 2023

@3DRaven
Copy link
Author

3DRaven commented Mar 10, 2023

The described idea is simpler than what is in the wiki. That is why I described it. It does not lead to a combinatorial explosion of code, since it is necessary to explicitly list the order of calls that are allowed, or indicate that all should be called. And all sub builders it is nested classes (for IDE autocomplete). This is a completely different solution to this problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants