Domanda

getEmployeeNameByBatchId(int batchID)
getEmployeeNameBySSN(SSN oggetto)
getEmployeeNameByEmailId(String emailID)
getEmployeeNameBySalaryAccount(SalaryAccount stipendioAccount)

O

getEmployeeName(int typeOfIdentifier, byte[] identifier) ​​-> In questo metodo typeOfIdentifier indica se l'identificatore è batchID/SSN/emailID/salaryAccount

Quale dei precedenti è il modo migliore per implementare un metodo get?

Questi metodi sarebbero in un Servlet e le chiamate verrebbero effettuate da un'API che verrebbe fornita ai clienti.

È stato utile?

Soluzione

Perché non sovraccaricare il metodo getEmployeeName(??)?

getEmployeeName(int BatchID)
getEmployeeName(oggetto SSN)(cattiva idea)
getEmployeeName(Stringa email)
eccetera.

Mi sembra un buon approccio "molti".

Altri suggerimenti

Potresti usare qualcosa del genere:

interface Employee{
    public String getName();
    int getBatchId();
}
interface Filter{
    boolean matches(Employee e);
}
public Filter byName(final String name){
    return new Filter(){
        public boolean matches(Employee e) {
            return e.getName().equals(name);
        }
    };
}
public Filter byBatchId(final int id){
    return new Filter(){
        public boolean matches(Employee e) {
            return e.getBatchId() == id;
        }
    };
}
public Employee findEmployee(Filter sel){
    List<Employee> allEmployees = null;
    for (Employee e:allEmployees)
        if (sel.matches(e))
            return e;
    return null;
}
public void usage(){
    findEmployee(byName("Gustav"));
    findEmployee(byBatchId(5));
}

Se esegui il filtraggio tramite una query SQL, utilizzeresti il ​​file Filter interfaccia per comporre una clausola WHERE.

L'aspetto positivo di questo approccio è che puoi combinare facilmente due filtri con:

public Filter and(final Filter f1,final Filter f2){
    return new Filter(){
        public boolean matches(Employee e) {
            return f1.matches(e) && f2.matches(e);
        }
    };
}

e usarlo in questo modo:

findEmployee(and(byName("Gustav"),byBatchId(5)));

Ciò che ottieni è simile a Criteria API in ibernazione.

Io opterei per l'approccio "molti".Mi sembra più intuitivo e meno soggetto a errori.

Non mi piace getXByY() - potrebbe essere interessante in PHP, ma semplicemente non mi piace in Java (ymmv).

Andrei con l'overload, a meno che tu non abbia proprietà dello stesso tipo di dati.In tal caso, farei qualcosa di simile alla tua seconda opzione, ma invece di utilizzare int, utilizzerei un Enum per la sicurezza e la chiarezza del tipo.E invece di byte[], utilizzerei Object (a causa dell'autoboxing, funziona anche per le primitive).

I metodi sono un esempio perfetto dell'utilizzo del sovraccarico.

getEmployeeName(int batchID)
getEmployeeName(Object SSN)
getEmployeeName(String emailID)
getEmployeeName(SalaryAccount salaryAccount)

Se i metodi hanno un'elaborazione comune all'interno, basta scrivere un altro getEmplyeeNameImpl(...) ed estrarre lì il codice comune per evitare duplicazioni

Prima opzione, nessuna domanda.Sii esplicito.Sarà di grande aiuto nella manutenibilità e non c'è davvero alcun aspetto negativo.

@Stefano:è difficile sovraccaricare un caso come questo (in generale) perché i tipi di parametri potrebbero non essere discriminativi, ad esempio,

  • getEmployeeNameByBatchId(int batchId)
  • getEmployeeNameByRoomNumber(int roomNumber)

Vedi anche i due metodi getEmployeeNameBySSN, getEmployeeNameByEmailId nel messaggio originale.

Utilizzerò nomi di metodo espliciti.Tutti coloro che mantengono quel codice e io in seguito capiremo cosa sta facendo quel metodo senza dover scrivere commenti xml.

A volte può essere più conveniente utilizzare il file modello di specifica.

Per esempio:GetEmployee(Specifica ISpecification<Dipendente>)

E poi inizia a definire le tue specifiche...

Specifica del nome:Specificazione<Dipendente>
{
nome della stringa privata;
public NameSpecification(string nome) { this.name = nome;}
public bool IsSatisFiedBy(Dipendente dipendente) { return dipendente.Nome == this.nome;}
}

Specifica NomeSpecifica = nuova SpecificaNome("Tim");
Tim dipendente = MyService.GetEmployee(spec);

Vorrei utilizzare la prima opzione o sovraccaricarla in questo caso, visto che hai 4 diverse firme dei parametri.Tuttavia, essere specifici aiuta a comprendere il codice tra 3 mesi.

La logica all’interno di ciascuno di questi metodi è sostanzialmente la stessa?

In tal caso, il metodo singolo con parametro identificatore potrebbe avere più senso (semplice e riducendo il codice ripetuto).

Se la logica/procedure varia notevolmente tra i tipi, è preferibile un metodo per tipo.

Come altri hanno suggerito, la prima opzione sembra essere quella buona.Il secondo potrebbe avere senso quando si scrive un codice, ma quando arriva qualcun altro in seguito, è più difficile capire come utilizzare il codice.(Lo so, hai commenti e puoi sempre approfondire il codice, ma GetemployeeNameById è più autoesplicativo)

Nota:A proposito, in alcuni casi l'uso di Enum potrebbe essere qualcosa da considerare.

In un caso banale come questo, opterei per il sovraccarico.Questo è:

getEmployeeName( int batchID );
getEmployeeName( Object SSN );

etc.

Solo in casi speciali specificherei il tipo di argomento nel nome del metodo, ad es.se il tipo di argomento è difficile da determinare, se esistono diversi tipi di argomenti con lo stesso tipo di dati (batchId e EmployeeId, entrambi int) o se i metodi per recuperare l'impiegato sono radicalmente diversi per ciascun tipo di argomento.

Non riesco a capire perché dovrei usarlo

getEmployeeName(int typeOfIdentifier, byte[] identifier)

poiché richiede sia al chiamato che al chiamante di trasmettere il valore in base a typeOfIdentifier.Cattivo design.

Se riscrivi la domanda potresti finire per chiedere:

"SELEZIONA nome DA..."
"SELEZIONA SSN DA..."
"SELEZIONA email DA..."
contro
"SCELTO DA ..."

E immagino che la risposta sia semplice e lo sanno tutti.

Cosa succede se cambi la classe Employee?Per esempio.:Devi rimuovere l'e-mail e aggiungere un nuovo filtro come dipartimento.Con la seconda soluzione corri il rischio enorme di non notare alcun errore se cambi semplicemente l'ordine delle "costanti" dell'identificatore int.Con la prima soluzione noterai sempre se stai utilizzando il metodo in alcune classi dimenticate da tempo che altrimenti ti dimenticheresti di modificare il nuovo identificatore.

Personalmente preferisco avere la denominazione esplicita "...ByRoomNumber" perché se ti ritrovi con molti "sovraccarico" alla fine introdurrai errori indesiderati.Essere espliciti è, secondo me, il modo migliore.

Sono d'accordo con Stephan:Un'attività, un nome di metodo, anche se puoi farlo in più modi.La funzionalità di sovraccarico del metodo è stata fornita esattamente per il tuo caso.

  • getEmployeeName(int BatchID)
  • getEmployeeName(Stringa email)
  • eccetera.

E Evitare la tua seconda soluzione a tutti i costi.Ha l'odore del "tuo vecchio vuoto * di C".Allo stesso modo, passare un "Oggetto" Java è uno stile scadente quasi quanto un "void *" in C.

Se hai una buona progettazione dovresti essere in grado di determinare se puoi utilizzare l'approccio di sovraccarico o se ti imbatterai in un problema in cui, se sovraccarichi, finirai per avere due metodi con lo stesso tipo di parametro.

Il sovraccarico sembra inizialmente il modo migliore, ma se in futuro non sarai in grado di aggiungere un metodo e incasinerai le cose con la denominazione, sarà una seccatura.

Personalmente preferirei l'approccio di un nome univoco per metodo, in questo modo non si incontreranno problemi in seguito nel tentativo di sovraccaricare gli stessi metodi Object con parametro.Inoltre, se qualcuno estendesse la tua classe in futuro e implementasse un altro void getEmployeeName(String name), non sovrascriverebbe il tuo.

Per riassumere, scegli un nome di metodo univoco per ciascun metodo, il sovraccarico può solo causare problemi a lungo termine.

Il disaccoppiamento tra il processo di ricerca e i criteri di ricerca che jrudolf propone nel suo esempio è eccellente.Mi chiedo perché non sia la soluzione più votata.Mi manca qualcosa?

Vorrei andare con Oggetti di query.Funzionano bene per accedere direttamente alle tabelle.Se sei limitato alle procedure memorizzate, queste perdono parte della loro potenza, ma puoi comunque farle funzionare.

Il primo è probabilmente il migliore in Java, considerando che è typesafe (a differenza dell'altro).Inoltre, per i tipi "normali", la seconda soluzione sembra fornire solo un utilizzo ingombrante per l'utente.Tuttavia, poiché stai utilizzando Object come tipo per SSN (che ha un significato semantico oltre Object), probabilmente non riuscirai a farla franca con quel tipo di API.

Tutto sommato, in questo caso particolare avrei utilizzato l'approccio con molti getter.Se tutti gli identificatori avessero il proprio tipo di classe, avrei potuto seguire la seconda strada, ma passando internamente alla classe invece che a un identificatore di tipo fornito/definito dall'applicazione.

inserisci tutte le tue opzioni in un'enumerazione, avrai qualcosa di simile al seguente

GetEmployeeName(Enum identifier)
{
    switch (identifier)
    case eBatchID:
    {
        // Do stuff
    }
    case eSSN:
    {
    }
    case eEmailId:
    {
    }
    case eSalary:
    {
    }
    default:
    {
        // No match
        return 0;
    }
}

enum Identifier
{
    eBatchID,
    eSSN,
    eEmailID,
    eSalary
}

Stai pensando C/C++.

Utilizza oggetti invece di un byte identificativo (o int).

Colpa mia, l'approccio di sovraccarico è migliore e usare il SSN come chiave primaria non è così buono

public ??? getEmployeeName(Object obj){

if (obj instanceof Integer){

  ...

} else if (obj instanceof String){

...

} else if .... // and so on


} else throw SomeMeaningFullRuntimeException()

return employeeName
}

Penso che sia meglio usare le eccezioni non controllate per segnalare input errati.

Documentalo in modo che il cliente sappia quali oggetti aspettarsi.Oppure crea i tuoi involucri.Preferisco la prima opzione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top