Question

getEmployeeNameByBatchId (int ID de lot)

getEmployeeNameBySSN (Object SSN)
getEmployeeNameByEmailId (String emailID)
getEmployeeNameBySalaryAccount (SalaryAccount salaireAccount)

ou

getEmployeeName (int typeOfIdentifier, identificateur d'octet []) - > Dans cette méthode, typeOfIdentifier indique si l’identifiant est batchID / SSN / emailID / salaireCompte

.

Laquelle de ces solutions est la meilleure pour implémenter une méthode get?

Ces méthodes seraient dans un servlet et les appels seraient passés à partir d'une API qui serait fournie aux clients.

Était-ce utile?

La solution

Pourquoi ne pas surcharger la méthode getEmployeeName (??)?

getEmployeeName (int BatchID)
getEmployeeName (objet SSN) (mauvaise idée)

getEmployeeName (String Email)
etc.

Cela me semble être une bonne approche "beaucoup".

Autres conseils

Vous pouvez utiliser quelque chose comme ça:

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));
}

Si vous effectuez le filtrage à l'aide d'une requête SQL, vous utiliserez l'interface Filter pour composer une clause WHERE.

La bonne chose avec cette approche est que vous pouvez combiner facilement deux filtres avec:

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

et utilisez-le comme ça:

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

Ce que vous obtenez est similaire à l'API Criteria d'Hibernate.

J'irais avec le " nombreux " approche. Cela me semble plus intuitif et moins sujet aux erreurs.

Je n'aime pas getXByY () - cela pourrait être cool en PHP, mais je ne l'aime pas en Java (ymmv).

J'accepterais la surcharge, sauf si vous avez des propriétés du même type de données. Dans ce cas, je ferais quelque chose de similaire à votre deuxième option, mais au lieu d'utiliser ints, j'utiliserais un Enum pour plus de sécurité et de clarté. Et au lieu d'octet [], j'utiliserais Object (en raison de la sélection automatique, cela fonctionne également pour les primitives).

Les méthodes sont un exemple parfait d’utilisation de la surcharge.

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

Si les méthodes comportent un traitement commun, écrivez simplement un autre getEmplyeeNameImpl (...) et extrayez-y le code commun pour éviter les doublons

Première option, pas de question. Soyez explicite. Cela facilitera grandement la maintenabilité et il n’y aura vraiment aucun inconvénient.

@Stephan: il est difficile de surcharger un cas comme celui-ci (en général) car les types de paramètre ne sont peut-être pas discriminants, par exemple,

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

Voir aussi les deux méthodes getEmployeeNameBySSN, getEmployeeNameByEmailId dans la publication d'origine.

Je vais utiliser des noms de méthodes explicites. Tous ceux qui gèrent ce code et moi-même comprendrons plus tard ce que fait cette méthode sans avoir à écrire de commentaires XML.

Parfois, il est plus pratique d'utiliser le modèle de spécification .

Exemple: GetEmployee (spécification IS < Employé > spécification)

Et commencez ensuite à définir vos spécifications ...

NameSpecification: ISpecification < employé >
{
 nom de chaîne privée;
 public NameSpecification (nom de chaîne) {this.name = name; }
 public bool IsSatisFiedBy (employé employé) {retourne employé.nom == ceci.nom; }
}

NameSpecification spec = new NameSpecification (& Quot; Tim & Quot;);

Employé tim = MyService.GetEmployee (spec);

J'utiliserais la première option ou la surchargerais dans ce cas, vu que vous avez 4 signatures de paramètres différentes. Cependant, être spécifique aide à comprendre le code dans 3 mois.

La logique à l'intérieur de chacune de ces méthodes est-elle en grande partie la même?

Si tel est le cas, la méthode unique avec le paramètre identificateur peut avoir plus de sens (code répété simple et réducteur).

Si la logique / les procédures varient considérablement entre les types, une méthode par type peut être préférable.

Comme d'autres l'ont suggéré, la première option semble être la bonne. La seconde peut avoir un sens quand vous écrivez un code, mais quand quelqu'un d'autre vient plus tard, il est plus difficile de comprendre comment utiliser le code. (Je sais, vous avez des commentaires et vous pouvez toujours fouiller dans le code, mais GetemployeeNameById est plus explicite.)

Remarque: Au fait, l'utilisation de Enums peut être un élément à prendre en compte dans certains cas.

Dans un cas aussi trivial que celui-ci, je préférerais la surcharge. C'est-à-dire:

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

etc.

Ce n'est que dans des cas particuliers que je spécifierais le type d'argument dans le nom de la méthode, c'est-à-dire si le type d'argument est difficile à déterminer, s'il existe plusieurs types d'arguments ayant le même type de données (batchId et employeeId, les deux int). , ou si les méthodes de récupération de l'employé sont radicalement différentes pour chaque type d'argument.

Je ne vois pas pourquoi je l'aurais jamais utilisé

getEmployeeName(int typeOfIdentifier, byte[] identifier)

car il exige que l'appelé et l'appelant transmettent la valeur en fonction de typeOfIdentifier. Mauvais design.

Si vous réécrivez la question, vous pouvez vous demander:

" SELECT le nom de ... "

" SELECTIONNER LE SSN DE ... "

" SELECTIONNER LE COURRIEL DE ... "

vs.
" SELECT * FROM ... "

Et je suppose que la réponse à cette question est facile et que tout le monde le sait.

Que se passe-t-il si vous changez la classe Employee? Exemple: vous devez supprimer l'e-mail et ajouter un nouveau filtre tel que department. Avec la deuxième solution, vous courez un risque énorme de ne pas remarquer d’erreurs si vous ne modifiez que l’ordre de l’identifiant int & "; Constantes &"; Avec la première solution, vous remarquerez toujours que si vous utilisez la méthode dans des classes longtemps oubliées, vous oublieriez sinon de modifier le nouvel identifiant.

Personnellement, je préfère avoir le nom explicite " ... ByRoomNumber " parce que si vous vous retrouvez avec beaucoup de " surcharges " vous allez éventuellement introduire des erreurs indésirables. Être explicite est à mon sens la meilleure solution.

Je suis d'accord avec Stephan: une tâche, un nom de méthode , même si vous pouvez le faire de plusieurs manières. La fonctionnalité de surcharge de méthode a été fournie exactement pour votre cas.

  • getEmployeeName (ID de lot int)
  • getEmployeeName (Chaîne E-mail)
  • etc.

Et évitez votre deuxième solution à tout prix. Ça sent & "Ton vieux vide * de C &". De même, en passant un objet Java & Quot; & Quot; est presque aussi pauvre qu'un style C & "; void * &";.

Si votre conception est bonne, vous devriez pouvoir déterminer si vous pouvez utiliser l'approche de la surcharge ou si vous rencontrez un problème qui vous oblige à utiliser deux méthodes avec la même méthode. type de paramètre.

La surcharge semble être la meilleure solution au départ, mais si vous ne pouvez pas ajouter de méthode à l'avenir et que vous vous trompez en nommant, ce sera un problème.

Personnellement, je préférerais l’approche d’un nom unique par méthode. Ainsi, vous ne rencontrerez pas de problèmes plus tard en essayant de surcharger le même paramètre Méthodes d’objet. De plus, si quelqu'un étendait votre classe à l'avenir et implémentait un autre void getEmployeeName (nom de chaîne), il ne remplacerait pas le vôtre.

Pour résumer, attribuez un nom de méthode unique à chaque méthode. La surcharge ne peut que causer des problèmes à long terme.

Le découplage entre le processus de recherche et les critères de recherche proposés par jrudolf dans son exemple est excellent. Je me demande pourquoi ce n’est pas la solution la plus votée. Est-ce que je manque quelque chose?

Je choisirais les objets de requête . Ils fonctionnent bien pour accéder directement aux tables. Si vous êtes limité aux procédures stockées, ils perdent une partie de leur pouvoir, mais vous pouvez quand même le faire fonctionner.

Le premier est probablement le meilleur de Java, étant donné qu’il est typé (contrairement à l’autre). De plus, pour & Quot; normal & Quot; types, la deuxième solution semble ne fournir qu’une utilisation lourde pour l’utilisateur. Cependant, puisque vous utilisez Object comme type pour SSN (qui a une signification sémantique au-delà de Object), vous ne réussirez probablement pas avec ce type d'API.

Au total, dans ce cas particulier, j'aurais utilisé l'approche avec beaucoup de getters. Si tous les identificateurs ont leur propre type de classe, j'aurais peut-être choisi la deuxième route, mais en passant en interne sur la classe au lieu d'un identificateur de type fourni / défini par l'application.

coller toutes vos options dans une énumération, avoir quelque chose comme ce qui suit

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
}

Vous pensez en C / C ++.

Utilisez des objets au lieu d'un octet d'identifiant (ou int).

My Bad, l'approche de la surcharge est meilleure et utiliser le SSN comme clé primaire n'est pas si bon

public ??? getEmployeeName(Object obj){

if (obj instanceof Integer){

  ...

} else if (obj instanceof String){

...

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


} else throw SomeMeaningFullRuntimeException()

return employeeName
}

Je pense qu'il est préférable d'utiliser des exceptions non contrôlées pour signaler une entrée incorrecte.

Documentez-le pour que le client sache à quels objets s'attendre. Ou créez vos propres wrappers. Je préfère la première option.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top