There are many value objects in my project.
I am using the lombok project to eliminate some pattern, so my value objects look like this:
@Value @Accessors(fluent = true) public class ValueObject { private final String firstProp; private final int secondProp; }
Not bad, almost no templates.
And now, I use the all-args constructor quite often in my tests. It looks pretty dirty, so I thought that instead we would choose the Builder Pattern option:
public class ValueObjectBuilder { private static final int DEFAULT_VALUE_FOR_SECOND_PROP = 666; private String firstProp = "default value for first prop; private int secondProp = DEFAULT_VALUE_FOR_SECOND_PROP; private ValueObjectBuilder() {} public static ValueObjectBuilder newValueObject() { return new ValueObjectBuilder(); } public ValueObjectBuilder withFirstProp(String firstProp) { this.firstProp = firstProp return this; } public ValueObjectBuilder withFirstProp(int secondProp) { this.secondProp = secondProp; return this; } public ValueObject build() { return new ValueObject( firstProp, secondProp ); } }
and now the code looks pretty good:
ValueObjectBuilder .newValueObject() .withFirstProp("prop") .withSecondProp(15) .build();
Now the problem is that, as I mentioned, I have to write a lot of similar classes ... I'm already tired of copying into them.
I am looking for, this is black magic - a smart tool that will somehow generate this code for me.
I know there is @Builder annotation in Lombok, but it does not meet my requirements. That's why:
1) I cannot provide default values โโin lombok Builder. Well, actually, itโs possible - by implementing a builder class template, for example,
@Builder public class Foo { private String prop; public static class FooBuilder() { private String prop = "def value"; ... } }
which also generates some patterns.
2) I can not find a way to put a prefix on each field accessory in lombok builder. Maybe @Wither can help here? But I do not know how to use it correctly.
3) The most important reason: I do not create a โnaturalโ builder. As far as I understand, lombok is designed to create a Builder for a given annotated class - I don't know if there is a way to return any other object from the build() method.
So to summarize: Do you know any tool that could help me? Or maybe all of the things that I mentioned can actually be achieved with the help of Lombok?
EDIT
Ok, so I probably found a solution for this particular case. With a Lombok we can use:
@Setter @Accessors(chain = true, fluent = true) @NoArgsConstructor(staticName = "newValueObject") public class ValueObjectBuilder { private String firstProp = "default"; private int secondProp = 666; public ValueObject build() { return new ValueObject(firstProp, secondProp); } }
Cheers, Slawek