6

So here is the existing code snippet written to build Humans ( as in matrix movie :) )

if (gender.equals("male")){
    return Human.builder()
        .gender('male')
        .name('abc')
        .speaks("english")
        .alive(true)
        .build();
}else{
    return Human.builder()
        .gender('female')
        .name('abcd')
        .speaks("english")
        .alive(true)
        .build();    
}

If you look, this code has lot of redundancy in attribute assignment which can be minimised. Now imagine 10 conditions like it (here, its just 2!), no matter what you try, it would eventually lead to ugly looking redundant code.

I tried searching lot of resources online and couldn't find any way to build object as per builder design. What i would like to achive here ( to reduce code redundancy) is something like below :

Human human = Human.builder()
            .speaks("english")
            .alive(true);

if (gender.equals("male")){
        human = human    // or just human.gender('male').name('abc'); no assignment
        .gender('male')
        .name('abc');
}else{
        human = human // or just human.gender('female').name('abcd'); no assignment
        .gender('female')
        .name('abcd');
}            
return human.build();

Is this possible via lombok or anyone knows a better way to build objects here?
If its worth it, i am on drop-wizard

NoobEditor
  • 15,563
  • 19
  • 81
  • 112

2 Answers2

7

Use Lombok's Builder:

import lombok.Builder;
import lombok.ToString;

@Builder
@ToString
public class Human {
    private String name;
    private String gender;
    private String speaks;
    private boolean alive;


    public static void main(String[] args) {
        HumanBuilder humanBuilder = Human.builder();

        String gender = "female";


        humanBuilder
                .speaks("english")
                .alive(true);

        if("male".equals(gender)){
            humanBuilder
                    .gender("male")
                    .name("abc");
        }else{
            humanBuilder
                    .gender("female")
                    .name("abcd");
        }

        Human human = humanBuilder.build();
        System.out.println(human);
    }
}

Result:

Human(name=abcd, gender=female, speaks=english, alive=true)
Dmitry Gorkovets
  • 2,208
  • 1
  • 10
  • 19
  • 1
    `Human` class will have a `lombok.Builder` annotation and doing `Human.builder();` initially will raise error (*have tried it already*) . Is there anything i am not understanding?? – NoobEditor Jan 30 '18 at 11:49
  • I tried it too. No initial errors. If you see doc: https://projectlombok.org/features/Builder you sill see that `Human.builder();` is just public static method. – Dmitry Gorkovets Jan 30 '18 at 12:00
  • @DmitryGorkovets : yes i see that. My mistake.I wasn't using `Builder` method of the class, seems to be working.will work out and accept in due time if all goes well. +1 meanwhile! :) – NoobEditor Jan 30 '18 at 12:12
  • Yes, my bad, realized that. – Dmitry Gorkovets Jan 30 '18 at 12:15
3

You can use any of the following ways for removing code redundancy and giving clarity:

OPTION 1:

Human human = Human.builder()
        .gender(gender.equals("M")?"male":(gender.equals("F")?"female":"transgender"))
        .name("abc")
        .speaks("english")
        .alive(true)
        .address(Optional.ofNullable(address).orElse(defaultAddress))
        .build();

OPTION 2:

Human human = Human.builder()
            .gender(getGender(gender))
            .name("abc")
            .speaks("english")
            .alive(true)
            .address(Optional.ofNullable(address).orElse(defaultAddress))
            .build();

public static String getGender(String gender){
   return gender.equals("M")?"male":(gender.equals("F")?"female":"transgender");
}

OPTION 3:

Human.HumanBuilder humanBuilder = Human.builder();
humanBuilder.name("abc").speaks("english").alive(true);
if(gender.equals("M")){
   humanBuilder.gender("male");
}else {
  humanBuilder.gender("female");
}

Human human = humanBuilder.build();

My personal preference is Option 2 as it makes the code more cleaner.

Hope this helps.

Sahil Chhabra
  • 10,621
  • 4
  • 63
  • 62
  • agreed on this one but downside is it would limit me to only 2 condition match. What if there is a 3rd gender - say `transgender` ? – NoobEditor Jan 30 '18 at 11:51
  • You can put N number of conditions, it doesn't matter. Please refer the updated answer. – Sahil Chhabra Jan 30 '18 at 11:56
  • i see what you did there but question is, *is it a solution or a hack* ? :) – NoobEditor Jan 30 '18 at 11:56
  • According to me its a solution. Its not a hack. I am not doing anything wrong , just making the code shorter and cleaner. – Sahil Chhabra Jan 30 '18 at 11:59
  • 2
    These are good solutions but not as elegant as it would be if support for this was built into Lombok, more specifically in the case where an attribute should only be set if the condition is true the code becomes a bit bulky (see Option 3 above). Would REALLY like if the Lombok team would add this feature. – Casper Kjær Aug 23 '18 at 07:58