Metodo di servizio, bean come argomento e attributi obbligatori

1

C'è un servizio:

createUser(User user)

dove puoi creare un nuovo utente, con così tanti attributi ( name , address linee ...). Ora alcuni attributi utente sono obbligatori. Altri attributi non sono obbligatori (come nickname o image ).

Il problema è che, dall'esterno, non puoi dire la differenza (in fase di compilazione). Non puoi costringerti a impostare solo campi obbligatori; inoltre, l'elenco dei campi obbligatori può cambiare in futuro e il tuo codice smetterà di funzionare (mentre sta ancora compilando).

Quindi possiamo

  • createUser(int userId, String username...) : esplora le proprietà del bean e non utilizzare bean come argomento. Ora ogni modifica si rifletterà nell'API, ma le firme dei metodi potrebbero diventare enormi. Inoltre, quando si sovraccaricano i metodi per varie combinazioni di campi obbligatori con non obbligatorio, anche questo può essere un disastro.
  • usa più bean e hai metodi come (i nomi forniti sono solo illustrativi) createUser(UserCoreData user) , createUser(UserFull user) ma che comunque non sarebbe di grande aiuto.
  • o dispone di un servizio per la memorizzazione di dati utente obbligatori e di servizi aggiuntivi per la memorizzazione di dati aggiuntivi non obbligatori.
  • (MODIFICATO) o per dividere User in componenti logici (ad es. fagioli più piccoli) Address , DateFrom ... e utilizzare quelli nei metodi di servizio.

Esiste un modo pragmatico per descrivere il metodo di servizio e i suoi argomenti in questo caso? (in Java).

    
posta igor 04.12.2013 - 11:46
fonte

3 risposte

2

Non utilizzare un bean Java se è possibile

Sebbene i Java Beans siano estremamente utili in molte occasioni, direi che sarebbe meglio che User non fosse un bean nel contesto che descrivi. Puoi progettare questa classe in modo che le sue istanze siano sempre in uno stato valido.

Nell'esempio seguente, il nome è obbligatorio e l'indirizzo è facoltativo.

class User {
    private String name;
    private String address;

    User(String name) {
        setName(name);
    }

    void setName(String name) {
        if (name == null)
            throw new IllegalArgumentException("[name] cannot be null");
        this.name = name;
    }
    String getName() {
        return name;
    }

    void setAddress(String address) {
        this.address = address;
    }
    String getAddress() {
        return address;
    }
}

Come puoi vedere, con quel design, non è possibile in alcun momento avere un'istanza User senza un nome. Tuttavia, puoi avere istanze con un indirizzo, oltre a istanze senza.

Si noti inoltre che nell'esempio di codice sopra sto eseguendo alcune convalide di base. Se necessario, è possibile eseguire una convalida più complessa di quella. Ad esempio assicurandoti che il nome non contenga caratteri che non appaiono nel tuo contesto.

Cose da considerare

Ci sono alcune cose da considerare per assicurarsi che una classe soddisfi il suo obiettivo. Solo il suo contenuto immutabile può essere mostrato al mondo esterno, per esempio. Considera un'altra classe simile che contiene un elenco che deve sempre contenere almeno un elemento. Se quell'elenco è mutabile e il codice esterno può accedervi (tramite un getter, ad esempio), nulla gli impedisce di rimuovere oggetti da esso finché non è vuoto, ponendo l'istanza iniziale in uno stato che non dovrebbe essere consentito. Naturalmente, se hai bisogno di esporre quei dati, considera solo di dare una copia dell'elenco o di renderlo immutabile.

Che cosa succede se ci sono molti valori obbligatori?

Se ha senso raggruppare alcuni di questi valori in classi proprie e che così facendo il costruttore diventa maneggevole, provaci. Tali classi dovrebbero essere progettate tenendo conto dei vincoli sopra menzionati.

In alternativa, puoi definire un Builder per aiutarti a costruire gli oggetti.

Che cosa succede se è necessario un bean Java in una parte specifica del mio codice?

Il design potrebbe funzionare bene nella maggior parte dei casi in cui queste classi vengono utilizzate tranne che in luoghi specifici in cui, poiché ad esempio un framework ne ha bisogno, è necessario utilizzare i bean Java. Quando ciò accade, invece di usare i bean ovunque, puoi definire un bean che contiene gli stessi dati con costruttore e metodo aggiunti per occuparsi della conversione dei dati. Ad esempio ...

class UserBean {
    private String name;
    private String address;

    UserBean() {
    }
    UserBean(User user) {
        this.name = user.getName();
        this.address = user.getAddress();
    }

    void setName(String name) {
        this.name = name;
    }
    String getName() {
        return name;
    }

    void setAddress(String address) {
        this.address = address;
    }
    String getAddress() {
        return address;
    }

    User toUser() {
        User ret = new User(name);
        ret.setAddress(address);
        return ret;
    }
}

In questo modo è facile avere un bean dall'istanza non bean e viceversa.

Conclusione

Come puoi vedere il problema che hai può essere risolto mantenendo la sua firma iniziale. È possibile che andando in questo modo si ottenga più codice da scrivere per un risultato simile (anche se non ne garantirei, dal momento che passare un oggetto necessariamente valido attorno significa meno convalida richiesta dal codice che lo utilizza).

Ho cercato di farla breve (ehm ...) e di usare qui un disegno simile a quello iniziale (fagioli). Tuttavia, è più per il gusto della spiegazione che per il fatto che considero il miglior design the . Con tutta la seccatura di forse bisogno di costruttori e classi di bean aggiuntive, tenderei a fare il miglio supplementare e rendere la classe passata immutabile. È così che ho progettato un progetto recente e breve, che si è rivelato particolarmente efficace.

    
risposta data 04.12.2013 - 17:34
fonte
0

Sembra che tu stia creando una libreria che altri possono usare. Se fossi in me, passerei in un oggetto utente parzialmente popolato con i valori noti, e il mio primo passo nella creazione di un utente sarebbe quello di convalidare l'input del metodo. Se mancano campi obbligatori, vorrei lanciare un'eccezione MissingParameter (che inventi) in fase di runtime.

Anche se trovi un modo per verificare in fase di compilazione, l'utente della tua libreria sta trasmettendo i valori, non sai ancora che sono valori non vuoti. Dovrai comunque generare un'eccezione per i parametri obbligatori non validi. Colpisci due piccioni con una fava.

    
risposta data 04.12.2013 - 13:17
fonte
0

Utilizza le annotazioni del tempo di compilazione e quindi usa gli strumenti di elaborazione delle annotazioni per verificare i parametri obbligatori al momento della compilazione stesso. Hai bisogno di 2 annotazioni, obbligatorie e facoltative.

Annota correttamente i campi bean e dovresti riuscire a raggiungerlo.

Link di riferimento: link

    
risposta data 04.12.2013 - 13:27
fonte

Leggi altre domande sui tag