Valore consigliato da passare al posto del parametro String per un metodo in java

5

Abbiamo un metodo chiamato attachDevice (Dispositivo dispositivo) che ha un solo argomento. Abbiamo avuto una situazione per sovraccaricare questo metodo con un parametro in più come attachDevice (Device device, String deviceName) .

con un solo argomento

public void attachDevice(Device device)
{
    ..
    ..        
}

con doppio argomento

public void attachDevice(Device device, String deviceName)
{
    ..
    device.setName(deviceName);
    genericDeviceMap.put(deviceName, device);
    ..
}

In realtà, il mio team leader mi ha chiesto di trasformare questi due metodi in un'unica chiamata generica. Il metodo sovraccarico ha solo due linee aggiuntive rispetto al metodo singolo (che sono mostrate come sopra). Posso passare una stringa vuota invece di passare il deviceName, perché l'invocazione del metodo overload sarà molto inferiore alla chiamata a singolo argomento di invocazione. Ma quanto è male se si passa il valore nullo poiché non imposto il nome se l'argomento sarà nullo. Quale sarebbe la migliore pratica per questo scenario?

Qualsiasi suggerimento è molto apprezzato.

Nota: il vero problema che ho affermato qui è che

i) Ho voluto unire metodi sovraccaricati in un metodo che dovrebbe essere generico per evitare la duplicazione del codice

ii) serve un valore consigliato per passare al metodo (stringa vuota o valore null) per rispettare le migliori pratiche di codifica.

Dalle risposte fornite, ho ottenuto la soluzione migliore per il mio problema. La domanda collegata che è stato riferito a questa domanda duplicata fornisce anche informazioni sulla gestione del valore nullo, ma non copre il primo punto che ho menzionato nella nota. E non ho scritto codice errato passando null come parametro, poiché sono consapevole che a volte NPE viene lanciato.

Grazie.

    
posta S.K. Venkat 11.07.2016 - 13:30
fonte

3 risposte

9

Ti sconsigliamo di usare sempre null poiché può portare a un ulteriore NPE, che è difficile da eseguire il debug (e costano molto se si verificano nel codice di produzione).

Soluzione 1 (metodo di sovraccarico)

Se non viene fornito deviceName , puoi invece fornire uno di default. Il più grande svantaggio di questo approccio è il pericolo in genericDeviceMap.put(deviceName, device) perché può ignorare in modo silenzioso la voce la cui chiave è il nome predefinito (quindi, perdere la traccia del precedente Device ).

public void attachDevice(Device device)
{
    attachDevice(device, "DefaultName");       
}

public void attachDevice(Device device, String deviceName)
{
    ..
    device.setName(deviceName);
    genericDeviceMap.put(deviceName, device);
    ..
}

Soluzione 2 (metodo di estrazione)

Forse con la tua architettura attuale non ha senso aggiungere una voce a genericDeviceMap quando attachDevice viene chiamato senza un nome. Se è così, un buon approccio è solo estrarre il comportamento comune tra il due attachDevice in metodi privati. Personalmente non mi piace questo approccio per 2 motivi:

  • Il comportamento tra i due attachDevice non è lo stesso, uno ha un effetto collaterale ( device.setName(deviceName) ) e l'altro no
  • L'effetto collaterale di per sé che spesso porta a bug sottili perché modifichi un oggetto proveniente da un ambito esterno

Codice:

public void attachDevice(Device device)
{
    preAttachDevice();
    postAttachDevice();      
}

public void attachDevice(Device device, String deviceName)
{
    preAttachDevice();
    device.setName(deviceName);
    genericDeviceMap.put(deviceName, device);
    postAttachDevice();
}

private void preAttachDevice()
{
    ...
}

private void postAttachDevice()
{
    ...
}

Soluzione 3 (metodo di rimozione)

Il mio preferito, ma il più difficile. Chiediti se hai davvero bisogno di questi due metodi? Ha davvero senso poter chiamare attachDevice con un nome o no? Non dovresti essere in grado di dire che attachDevice deve essere chiamato con un nome?

In questo caso il codice è semplificato con un solo metodo

public void attachDevice(Device device, String deviceName)
{
    ..
    device.setName(deviceName);
    genericDeviceMap.put(deviceName, device);
    ..
}

O d'altra parte, hai davvero bisogno di mantenere un Map di nomi di dispositivi e dispositivi e di impostare il nome del dispositivo? In caso contrario, puoi sbarazzarti del secondo metodo e mantenere solo il primo.

public void attachDevice(Device device)
{
    ...
    ...     
}
    
risposta data 11.07.2016 - 14:00
fonte
4

Direi che il tuo capo squadra ti sta chiedendo di creare codice errato. Il dover passare un valore arbitrario come parametro name quando non si desidera specificare un nome è disordinato e confuso per tutti gli sviluppatori che desiderano utilizzare il metodo.

Invece, mantieni i tuoi due metodi (anche se rinominerei il tuo ultimo con qualcosa come attachNamedDevice per rendere chiaro che fa qualcosa di diverso da attachDevice , quindi sposta il codice comune in metodi privati:

public void attachDevice(Device device)
{
    preDeviceNameSetup(device);
    postDeviceNameSetup(device);        
}

public void attachNamedDevice(Device device, String deviceName)
{
    preDeviceNameSetup(device);
    device.setName(deviceName);
    genericDeviceMap.put(deviceName, device);
    postDeviceNameSetup(device);        
}

private void preDeviceNameSetup(Device device)
{
    ...
}

private void postDeviceNameSetup(Device device)
{
    ...
}

In tal modo, mantieni l'API pulita, ma evita la duplicazione del codice nell'implementazione.

    
risposta data 11.07.2016 - 13:50
fonte
1

Farei quanto segue:

  1. Rimuovi la seconda funzione con String come secondo parametro.
  2. Chiama device.setName(deviceName) prima di chiamare attachDevice(device) . Non è responsabilità del metodo attachDevice impostare il nome del dispositivo.
  3. Modifica il metodo attachDevice per aggiungere il dispositivo a genericDeviceMap se ha un nome, come mostrato nello snippet di codice seguente.

Se hai anche bisogno di aggiungere il dispositivo a genericDeviceMap quando non ha un nome, probabilmente stai meglio impostando un valore predefinito nel costruttore della classe Device o qualcosa del genere.

public void attachDevice(Device device)
{
    // ...
    if (device.getName())
    {
        genericDeviceMap.put(deviceName, device);
    }
    // ...
}

Ciò mantiene le tue preoccupazioni separate e ti aiuta a stare lontano dalle funzioni con effetti collaterali.

    
risposta data 13.07.2016 - 23:28
fonte

Leggi altre domande sui tag