Comment et pourquoi choisir entre les méthodes de nommage avec les préfixes "get" et "find"

48

J'ai toujours du mal à déterminer si je devrais nommer une méthode en commençant par getSomethingversus findSomething.

Le problème réside dans la création d’ aides pour des API mal conçues. Cela se produit généralement lors de l'obtention de données à partir d'un objet, qui requiert l'objet en tant que paramètre. Voici un exemple simple:

public String getRevision(Item item) {
    service.load(item, "revision");
    // there is usually more work to do before getting the data..
    try {
        return item.get_revision();
    }
    catch(NotLoadedException exception) {
        log.error("Property named 'property_name' was not loaded", exception);
    }
    return null;
}

Comment et pourquoi choisir entre nommer cette méthode getRevision()ou findRevision()?

Connu Asilya
la source
2
Pour une API mal conçue, la meilleure aide est de ne pas embrouiller les noms, mais d'établir une couche anticorruption : "Si votre application doit traiter une base de données ou une autre application dont le modèle est indésirable ou inapplicable au modèle souhaité dans votre propre application, utilisez un AnticorruptionLayer pour traduire vers / à partir de ce modèle et du vôtre. "
moucher le
1
Je n'ai jamais entendu parler de ce concept auparavant. Avez-vous de meilleurs liens avec des exemples?
knownasilya
1
Rechercher sur le Web, il y a beaucoup d'informations à ce sujet. Par exemple, Anatomie d'une couche anti-corruption, partie 1 "il est probable que ... vous êtes inévitablement confronté à la tâche d'interaction avec les spaghettis qui sont déjà présents. Entrez dans la couche anti-corruption ..."
gnat

Réponses:

83

J'utilise Getquand je sais que le temps de récupération sera très court (comme dans une recherche à partir d'une table de hachage ou btree).

Findimplique un processus de recherche ou un algorithme de calcul qui nécessite une période d'exécution "plus longue" (pour une valeur arbitraire plus longue).

Robert Harvey
la source
3
+1 J'utilise get lors de la récupération et trouve le moment où le travail doit être effectué pour obtenir un get.
Jim
5
Tenant compte des changements de code (certaines parties sont optimisées et des modifications d’algorithmes), il est souvent impossible de changer d’API, ce n’est pas un bon critère. Que feriez-vous si vous findremplaciez plus tard par un algorithme de table de hachage?
Meze
2
Je suppose également que, lors de la lecture d’un appel, il est possible d’appeler "find" lorsque la recherche n’aboutit pas car le critère de recherche échoue, alors que "get" doit réussir sauf s’il existe un problème inhabituel.
gnasher729
Que se passe-t-il si la fonction accepte un paramètre facultatif pour filtrer les résultats en fonction de certaines conditions? Les deux getet finds'appliqueraient en fonction de l'utilisation qui en est faite.
ESR
62

Je dirais que cela findpeut échouer mais getne devrait pas.

coredump
la source
25
Si vous voulez dire que findNULL peut être retourné alors que NULL getne le sera jamais, mais que jette (ou affirme), je suis d’accord.
Sjoerd
1
Je suis totalement d'accord avec @Sjoerd à ce sujet.
Mhr
Et si les find()retours Optional<>? Dans ce cas, findc'est aussi nullsans danger.
TheCoder
42

Pour citer une conversation que j'ai souvent avec mes enfants:

moi: Hey gamin! Va me chercher des piles

kid: Mais où sont-ils?

moi: C'est pour ça que je t'ai dit d'aller les chercher . Si je savais où ils étaient, je vous aurais dit d'aller les chercher . Ou vous pouvez demander à votre mère.

La même idée tient:

  • Utilisez "get" pour une méthode qui renvoie une information disponible à un prix avantageux (et peut probablement être insérée ou optimisée), ou pour une information détenue de manière unique par cet objet.

  • utilisez "find" pour une méthode qui fonctionne pour obtenir une information ou utilise d'autres objets pour la trouver.

jimwise
la source
16
Seul un programmeur aurait cette conversation avec leurs enfants. "Voulez-vous sortir les poubelles?" "Non." "Voulez-vous sortir la poubelle?" "Oui."
Robert Harvey
@ RobertHarvey Je pense avoir ce problème avec les gens. Chaque fois que quelqu'un essaie d'expliquer quelque chose ou pose une question, je lui pose généralement des questions et je lui dis d'être explicite à ce sujet. Sinon, nous nous retrouvons généralement avec un problème XY. Si je ne le fais pas, je me sens comme une fonctionnalité de complétude automatique. Vous ne savez pas ce que vous pensez, vous ne pouvez pas le mettre en mots, vous babillez quelques mots et vous attendez de moi que je fasse toute la "réflexion" pour vous et que je vous aide à cela? Non,
ça
3

Rechercher implique de ne pas avoir le résultat, comme lors de l'exécution d'une requête de base de données avec certains paramètres susceptibles de changer entre les appels. Get, d'autre part, implique que les résultats sont connus de la méthode à l'avance ou ne changeront pas une fois connus, qu'il n'y a pas de paramètres dans l'appel.
Donc, j'utiliserais par exemple Client findCustomerById (long customerId) et Customer getCustomer ()

jwenting
la source
3

J'applique le motif suivant:

  • Foo GetFoo() ne peut pas retourner null et sa complexité est O (log (n)) ou moins
  • bool TryGetFoo(out Foo) peut retourner null et sa complexité est O (log (n)) ou moins
  • Foo FindFoo() ne peut pas retourner null et sa complexité est supérieure à O (log (n))
  • bool TryFindFoo(out Foo) peut renvoyer null et sa complexité dépasse O (log (n))

De cette façon, le code est assez clair sur l'intention et la complexité auxquelles vous pouvez vous attendre.

En règle générale, les accesseurs sont destinés à un accès direct à une liste ou à un dictionnaire / jeu.
Les Finders sont une recherche en profondeur, une analyse complète de la liste, etc ...

Dans ton cas:

public bool TryGetRevision( Item item, out String revision ) 
{
    service.load( item, "revision" );
    // there is usually more work to do before getting the data..
    try 
    {
        revision = item.get_revision();
        return true;
    }
    catch( NotLoadedException exception )
    {
        log.error( "Property named 'property_name' was not loaded", exception );
        revision = "";
        return false;
    }
}
Cyril Gandon
la source
+1 pour le trycourt et précis
SpaceTrucker
2

getest approprié dans tous les cas _ en fait, on suppose souvent que pour obtenir quelque chose, il faut d'abord le trouver. Donc, si vous n'êtes pas sûr, utilisez get.

J'utiliserais finddes méthodes telles que findMinimum()ou findOptimal(), c'est-à-dire qu'il existe un algorithme spécial qui calcule la valeur de retour et ne demande pas simplement à la base de données, au système de fichiers, au serveur distant, etc. de recevoir certaines données.

SuperM
la source
1
Bons points. Personnellement, je n’utiliserais probablement pas findde préfixe dans les exemples que vous avez fournis. Pour les tâches de calcul, comme celles de votre exemple, j’utiliserais calculateou compute.
connusasilya
2

N'utilisez pas find ou obtenir des préfixes. Ceci est une violation du principe UniformAccess inventé par bertrand meyer. Pourquoi ne pas créer une méthode comme celle-ci:

public String revision(Item item)
Giorgi Dvalishvili
la source
Je suis complètement d'accord avec toi, génial !!!!
Irakli Gabisonia
1

Je vais généralement utiliser Getpour récupérer un objet / valeur, et Findpour récupérer son emplacement (dans un tableau, par exemple).

pour ex:

object o = obj.GetItem( 'name');

integer i = somearray.Find( 'name');
Grand maître b
la source
0

Pour moi, findimplique qu'il peut éventuellement y avoir plus d'un résultat présent. getimplique un seul.

Karl Bielefeldt
la source
8
On dirait que ça a cette sensation, mais je ne suis pas sûr d’être complètement d’accord. Pensez-y de cette façon: getCatvs findCatvs getCatsvs findCats. La find..représente encore des objets singuliers retournés. Le pluriel devrait être ajouté au nom, à mon avis.
connusasilya