Che cosa è meglio passare un'istanza di classe al metodo o solo alle primitive? [duplicare]

6

Diciamo che ho un modello di alcuni dati:

public class User {

    public String name;
    public String password;

}

E qualche altra classe per lavorare con questo utente:

public class ClassB {

    public static void saveUser(User user) {
        // Something 
    }

    public static void saveUser(String username, String password) {
        // Something
    }

}

Qual è il modo migliore per andare? Faresti meglio a scegliere il secondo metodo in modo da non accoppiare queste due classi o scegliere il primo modo solo passando un'istanza User ?

    
posta Eugene 30.09.2013 - 12:52
fonte

4 risposte

6

Considera quanto segue (parte dell'eccellente codice Clean di Uncle Bob):

Se ci sono connessioni dirette tra i parametri, dovresti incapsularlo in una classe. (qualcosa del genere dal libro)

Esempio: se hai una classe UserCredential , puoi facilmente aggiungere SSO o autenticazione basata su un biglietto singolo. Se avessi un metodo o una proprietà chiamata AreValid , non avrai mai bisogno di modificare il tuo codice, anche se stai aggiungendo queste due nuove funzionalità.

Vedi?

public static void saveUser(UserCredentials credentials) 
{
    if (credentials.AreValid)
    {
        // Something - won't ever change
    }
}

Nota: non è nemmeno una classe User , solo le credenziali.

L'ulteriore vantaggio di creare classi più piccole ( UserCredentials invece di User ) è: puoi aggiungere logica in quella piccola classe - quindi scoprire se l'utente ha credenziali valide non inquinerà il tuo codice dove ti stai concentrando per salvare qualcosa: stai separando le responsabilità (controlla: Principio di responsabilità singola ).

    
risposta data 30.09.2013 - 13:59
fonte
13

Come hai identificato, saveUser(User user) accoppia le due classi. Questo non è sempre male. Se l'unico scopo della classe B è quello di salvare un utente, è giusto che si aspetti che un oggetto utente salvi. Tuttavia, può portare a problemi di estensibilità, se il modello è abbastanza complesso.

Fornisce inoltre al metodo saveUser l'accesso a qualsiasi logica aggiunta alla classe dell'utente. Un rischio basso, ma comunque un rischio.

D'altra parte, saveUser(String username, String password) porta i suoi problemi. è molto facile, soprattutto quando hai 10 o più parametri, per farli confondere. Se qualcuno digita accidentalmente saveUser(user.Password, user.Username) , non otterrai un errore in fase di compilazione, o persino un errore di runtime, salverà felicemente quelle stringhe nei campi sbagliati.

Inoltre, un lungo elenco di parametri può rendere il tuo codice illeggibile.

Un'opzione migliore è probabilmente quella di utilizzare un'interfaccia saveUser(IUserDetails user) che non accoppia le classi l'una all'altra, ma piuttosto accoppia il metodo saveUser a qualsiasi classe che contenga i dati necessari per eseguire l'attività che è stata assegnata a fai - salva un nome utente e una password.

    
risposta data 30.09.2013 - 13:20
fonte
5

Vorrei andare per un oggetto. Prima di tutto, orientato agli oggetti ma anche alla leggibilità:

User user = new User("aString", "anotherString")
saveUser(user);

è più leggibile di:

saveUser("aString", "anotherString");

ed è più sicuro, ad esempio:

saveUser(password, username) //oops
    
risposta data 30.09.2013 - 13:16
fonte
4

Raramente è una buona idea usare più parametri per rappresentare un singolo "oggetto" (qui usato come un insieme di variabili logicamente coesivo) in una funzione, quando è possibile è consigliabile passare solo un singolo parametro per ognuno di questi "oggetto".

Considera che quando si modifica il framework delle autorizzazioni per utilizzare un token di autenticazione, è necessario modificare le chiamate tutte che utilizzano username / password più l'implementazione di tali funzioni, rispetto a solo l'utente che passa dove hai solo bisogno di cambiare l'implementazione.

O prendi una terza opzione e crea un sub-oggetto come un token di autenticazione (per continuare l'analogia) che puoi trasmettere, questo è un livello superiore rispetto a username / password stringhe, ma disaccoppia ancora utente da ClassB .

    
risposta data 30.09.2013 - 13:15
fonte

Leggi altre domande sui tag