Ho incontrato diverse situazioni in cui un POJO in cui il valore di un campo è significativo dipende dal valore di un altro campo. Un esempio, usando Lombok (che cerchiamo di usare per evitare il boilerplate):
@Data
@Builder
public class SomePojo {
// an enum whose values are DEFAULT_LOCATION, STANDARD_INPUT, FILE
private final SourceType sourceType;
// meaningful only if sourceType == FILE
private final String path;
private final String attributes;
}
(Questo è solo un esempio, il caso che sto guardando non ha nulla a che fare con i file. Se fa la differenza, lo scopo della classe è quello di restituire un metodo che deve restituire diversi pezzi di informazioni al chiamante.)
Sebbene la classe possa essere utilizzata così com'è, quali sono le migliori pratiche per affrontare questa situazione? In particolare:
-
Devo scrivere un metodo getter personalizzato per
path
che genera un'eccezione sesourceType != FILE
? -
Devo scrivere un builder personalizzato che genera un'eccezione se il builder prova a impostare
path
quando impostasourceType
su qualcosa di diverso daFILE
? -
Devo scrivere
equals()
personalizzato ehashCode()
che non guardanopath
sesourceType != FILE
? -
Il mio costruttore o costruttore ha impostato
path
su un valore fisso sesourceType != FILE
? Così facendo eliminerebbero la necessità di% specialeequals()
ehashCode()
. -
Devo rendere il percorso un
Optional<String>
? Basterebbe fare questo senza fare nulla di # 1-4? -
È preferibile definire una nuova gerarchia di classi per incapsulare i campi
sourceType
epath
(quindi ci sarebbero tre sottoclassi di qualche classe base e solo una di esse avrebbe unpath
)? Supponiamo che non ci siano metodi polimorfici in questa gerarchia.
MORE: Sono d'accordo con il commento che se un metodo restituisce un record variante, ci sono buone possibilità che il metodo stia facendo troppo e che sia necessario controllarlo. Ma questo non è sempre il caso. Un esempio molto semplice sarebbe un metodo che cerca una stringa per vedere se contiene una sottostringa e restituisce la posizione della sottostringa se presente. (Il metodo Java per fare ciò restituisce un valore speciale come "posizione" se la sottostringa non è presente, che sarebbe una cattiva pratica perché può introdurre errori se un chiamante non riesce a controllare questo caso e tratta la posizione risultante come numero. Optional
sarebbe di aiuto in questo caso, ma non nel caso in cui ci siano più di due stati da restituire.) Questo sembra essere un caso di uso naturale per il ritorno (FOUND, position
) o (NOT_FOUND ) che non avrebbe una posizione. Il caso con cui sto lavorando non è così semplice, ma è stato esaminato a fondo ed è già stato strappato un paio di volte dai colleghi nelle revisioni del design, quindi sono abbastanza sicuro che non è un metodo che fa troppo .