Supposons une interface contenant ces méthodes:
Car find(long id);
List<Car> find(String model);
Est-il préférable de les renommer comme ça?
Car findById(long id);
List findByModel(String model);
En effet, tout développeur qui utilise cette API n'aura pas besoin de regarder l'interface pour connaître les arguments possibles des find()
méthodes initiales .
Ma question est donc plus générale: quel est l'avantage d'utiliser des méthodes surchargées dans le code car cela réduit la lisibilité?
Réponses:
Il s'agit d'un problème relativement mineur par rapport à de nombreuses autres mauvaises pratiques de lisibilité auxquelles vous pourriez être sensible, donc je dirais que c'est principalement une question de goût comment vous nommez vos méthodes.
Cela dit, si vous voulez faire quelque chose, je suivrais cette pratique:
Surcharge si ...
Les méthodes obéissent à peu près au même contrat mais fonctionnent simplement sur des entrées différentes (imaginez un opérateur téléphonique qui peut rechercher votre compte par votre numéro d'identification fiscale, votre numéro de compte ou votre nom et votre anniversaire). Cela inclut le retour du même type de sortie .
Utilisez un nom différent si ...
Les méthodes font des choses sensiblement différentes ou retournent des sorties différentes (comme votre cas). Vous pourriez envisager d'utiliser un nom différent si l'un accède à la base de données et l'autre pas.
De plus, si le type retourné est différent, je changerais également le verbe pour indiquer que:
la source
Je recommanderais d'utiliser un nom différent, dans tous les cas. Il est possible qu'à un moment donné dans le futur, vous souhaitiez ajouter une autre méthode, disons
List<Car> findByMake(String make)
, contrairement àList<Car> findByModel(String model)
. Alors tout à coup, tout appelerfind
cesse de faire sens. Vos méthodes sont également moins susceptibles d'être mal utilisées par inadvertance, si leurs noms donnent plus d'informations sur la façon dont elles doivent être utilisées.la source
find(Make val)
etfind(Model val)
. Ensuite, des méthodes pratiques telles que celles-findByMake(String val)
ci seraient beaucoup plus claires sur ce qu'elles font réellement. Après tout, aString
n'est pas une marque ou un modèle, donc la méthode doit expliquer ce qu'elle fait vraiment.Si vous renommez une méthode, elle ne sera plus surchargée. En soi, la surcharge ne rend pas nécessairement le code moins lisible, mais elle peut rendre l'implémentation plus difficile à suivre si la syntaxe n'est pas claire.
De nombreux langages utilisent la surcharge de méthode comme moyen de présenter une interface vers des fonctionnalités où les paramètres peuvent être facultatifs et les valeurs par défaut des paramètres facultatifs sont implicites. Cela est particulièrement vrai pour les langues qui ne prennent pas en charge une syntaxe de paramètre par défaut dans la déclaration de méthode.
Ce faisant:
vous évite de le faire:
Quant à ce qui est plus lisible, cela dépend vraiment de vous. Personnellement, je préfère la deuxième option, en particulier lorsque la liste des paramètres devient un peu longue, mais je suppose que cela n'a pas vraiment d'importance tant que vous êtes cohérent tout au long de votre API.
La difficulté de surcharge survient lorsque vous voulez des fonctions qui font essentiellement la même chose et où vous voulez que les listes de paramètres soient les mêmes, mais que les types de retour soient différents. La plupart des langues ne savent pas différencier deux méthodes nommées de la même manière, mais avec des types de retour différents. À ce stade, vous devez penser à utiliser des génériques, à modifier l'interface des paramètres ou à renommer l'une de vos méthodes pour indiquer la différence de type de retour. C'est là que la lisibilité peut devenir un gros problème, si vous ne vous contentez pas d'un schéma de nommage simple et clair pour faire face à des situations comme celle-ci.
Nommer vos méthodes surchargées
GetSomething()
etGetSomethingEx()
ne va pas en dire long sur les différences entre vos méthodes, en particulier si ce sont les types de retour qui sont les seules différences entre elles. D'un autre côté,GetSomethingAsInt()
etGetSomethingAsString()
vous en dire un peu plus sur ce que font les méthodes, et bien qu'il ne s'agisse pas strictement d'une surcharge, indiquez que les deux méthodes font des choses similaires, mais retournent des types de valeurs différents. Je sais qu'il existe d'autres façons de nommer les méthodes, mais pour illustrer ce point, ces exemples grossiers devraient le faire.Dans l'exemple OPs, le renommage n'est pas strictement nécessaire car les paramètres de méthode sont différents, mais cela rend les choses un peu plus claires pour nommer une méthode plus spécifiquement. En fin de compte, cela se résume vraiment au type d'interface que vous souhaitez présenter à vos utilisateurs. La décision de ne pas surcharger ne doit pas être prise uniquement en fonction de votre propre perception de la lisibilité. La surcharge des méthodes peut par exemple simplifier une interface API et réduire le nombre de méthodes dont un développeur peut avoir besoin de se souvenir, d'autre part, elle peut obscurcir l'interface à un degré qui oblige ensuite un développeur à lire la documentation de la méthode pour comprendre quelle forme de méthode à utiliser, alors que le fait d'avoir un certain nombre de méthodes nommées de manière similaire mais descriptive peut rendre plus évident la simple lecture d'un nom de méthode quant à son objectif.
la source
Privilégiez la surcharge tant que les méthodes retournent la même chose et suivent le même contrat. La surcharge libère le code appelant de la validation inutile du type de paramètre.
Supposons que la fonction appelante reçoive une requête de recherche en tant que paramètre et effectue un autre traitement avant et / ou après l'appel à
find
.Si vous souhaitez modifier le type de cette requête pour une raison quelconque (par exemple, d'une simple chaîne d'ID à un objet de requête complet), vous pouvez effectuer ce changement dans la fonction d'appel simplement en changeant la signature de la fonction pour accepter le nouveau type de paramètre sans vous soucier de changer la méthode qu'il appelle sur votre classe.
Si vous implémentez
findById
etfindByQueryObject
séparément, vous devrez rechercher chaque appel pour effectuer ce changement. Dans l'exemple, je n'ai changé qu'un seul mot et j'avais terminé.la source
findByFoo
pour détecter les incompatibilités de type plus tôt.