2015-01-09 21 views
8

Ho un sacco di oggetti di valore nel mio progetto.Java BuilderTestPattern - come evitare il boilerplate?

sto usando progetto Lombok per eliminare alcuni boilerplate, quindi i miei oggetti di valore apparire come la seguente:

@Value 
@Accessors(fluent = true) 
public class ValueObject { 

    private final String firstProp; 
    private final int secondProp; 

} 

Non male, quasi nessun boilerplate.

E ora, sto usando il costruttore di all-args abbastanza spesso nei miei test. Sembra piuttosto confusa, così ho pensato che vi presenterò Builder variante del modello invece:

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 
     ); 
    } 
} 

e il codice sembra abbastanza bello ora:

ValueObjectBuilder 
.newValueObject() 
.withFirstProp("prop") 
.withSecondProp(15) 
.build(); 

Ora, il problema è - come ho già detto, ho scrivere un sacco di classi simili ... Sono già stanco di copiarle.

Quello che sto cercando è uno strumento black-magic-smart, che in qualche modo genererà questo codice per me.

Lo so, c'è un'annotazione @Builder in Lombok, ma non soddisfa i miei requisiti. Ecco perché:

1) Non riesco a fornire valori predefiniti in lombok's Builder. Beh, in realtà, è possibile - implementando il modello di classe builder me stesso come

@Builder 
public class Foo { 
    private String prop; 

    public static class FooBuilder() { 
     private String prop = "def value"; 
     ... 
    } 

} 

che genera anche qualche piastra di riscaldamento.

2) Non riesco a trovare alcun modo per inserire il prefisso su ciascun campo di accesso nel builder di lombok. Forse @Wither potrebbe aiutare qui? Ma non lo so, come usarlo correttamente.

3) La ragione più importante: non sto creando un costruttore "naturale". Per quanto ho capito, lombok è progettato per creare Builder per una determinata classe annotata - Non so se c'è un modo per restituire qualsiasi altro oggetto dal metodo build().

Quindi, per riassumere: Conoscete qualche strumento che potrebbe aiutarmi? O forse tutte quelle cose che ho menzionato sono in effetti possibili da raggiungere usando Lombok?

EDIT

Ok, quindi probabilmente trovato una soluzione a questo caso particolare. Con Lombok possiamo usare:

@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

risposta

1

Prova Bob-the-builder per Eclipse. Hmm .. Immagino che funzioni meglio se ti capita di usare eclipse! Se non stai usando eclipse, ci sono alcuni progetti correlati menzionati nella parte inferiore della pagina collegata qui che potrebbe essere utile.

+0

Grazie, in primo luogo, sto usando IDEA - ci hai provato con loro? In secondo luogo, in realtà sto cercando qualcosa che potrei generare il mio codice come fa il lombok - senza tutti quei pasticci – slnowak

+0

Non ho, purtroppo, ho sentito che IDEA è eccellente e ci credo perché hanno usato RubyMine prima e questo è fantastico per il lavoro di Ruby! So che questi generatori non sono piuttosto s o lucido come Lombok ... (cancellato e sostituito per correggere l'ortografia di Lombok!) – unigeek

5

So che questo è vecchio ma se qualcun altro si imbatte in questo, ho trovato una soluzione alternativa per fornire valori predefiniti per un costruttore.

Sostituire il metodo builder e fornire i valori predefiniti prima di restituire un builder. Quindi, nel caso di cui sopra:

@Builder 
public class Foo { 
    private String prop; 

    public static FooBuilder builder() { 
     return new FooBuilder().prop("def value"); 
    } 
} 

Non è una soluzione ideale, ma batte dover sostituire l'intero costruttore stesso o avere un costruttore personalizzato (che è secondo me doloroso se ci sono un sacco di variabili Sarebbe comunque bello. per avere qualcosa sulla falsariga di un'annotazione @With o @Default per gestirlo.

+0

Grazie, lo controllerò più tardi! – slnowak

+1

@mikea Quale versione usi? Sto cercando ma ricevo un errore di compilazione 'FooBuilder non è pubblico e non è possibile accedere dal pacchetto esterno ' – nKognito

+0

@nKognito 1.16.4 – mikea