Wie und warum soll man sich zwischen Benennungsmethoden mit den Präfixen "get" und "find" entscheiden?


48

Ich habe immer Probleme herauszufinden, ob ich eine bestimmte Methode benennen soll, die mit getSomethingversus beginnt findSomething.

Das Problem besteht darin, Hilfsprogramme für schlecht gestaltete APIs zu erstellen . Dies tritt normalerweise auf, wenn Daten von einem Objekt abgerufen werden, für das das Objekt als Parameter erforderlich ist. Hier ist ein einfaches Beispiel:

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

Wie und warum sollte man entscheiden, ob diese Methode als getRevision()oder benannt wird findRevision()?


2
Der beste Helfer für eine schlecht gestaltete API ist, sich nicht mit kniffligen Namen herumzuschlagen , sondern eine Antikorruptionsschicht einzurichten : "Wenn Ihre Anwendung mit einer Datenbank oder einer anderen Anwendung umgehen muss, deren Modell für das gewünschte Modell in Ihrer eigenen Anwendung unerwünscht oder nicht anwendbar ist, Verwenden Sie eine Antikorruptions-Ebene, um von / zu diesem und Ihrem Modell zu übersetzen. "
gnat

1
Ich habe noch nie von diesem Konzept gehört. Haben Sie bessere Links zu Beispielen?
knownasilya

1
Suchen Sie im Web, es gibt eine Menge Informationen darüber. ZB Anatomie einer Anti-Korruptions-Schicht, Teil 1 "Es ist wahrscheinlich, dass ... Sie unweigerlich vor der Aufgabe stehen, mit den bereits vorhandenen Spaghetti zu interagieren. Betreten Sie die Anti-Korruptions-Schicht ..."
Mücke

Antworten:


83

Ich benutze, Getwenn ich weiß, dass die Abrufzeit sehr kurz sein wird (wie bei einer Suche von einer Hash-Tabelle oder einem Btree).

Findimpliziert einen Suchprozess oder einen Berechnungsalgorithmus , dessen Ausführung eine "längere" Zeitdauer erfordert (für einen beliebigen Wert von länger).


3
+1 Ich verwende get beim Abrufen und finde heraus, wann Arbeit erledigt werden muss, um einen Abruf durchzuführen.
Jim

5
Wenn man berücksichtigt, dass sich der Code ändert (einige Teile werden optimiert und Algorithmen ändern sich) und die API oft nicht geändert werden kann, sieht es nicht nach einem richtigen Kriterium aus. Was würden Sie tun, wenn Sie später findeinen Hash-Tabellen-Algorithmus verwenden würden?
Mezze

2
Ich würde auch annehmen, dass beim Lesen eines Aufrufs "find" aufgerufen werden kann, wenn der Suchvorgang nicht erfolgreich ist, da das Suchkriterium nicht erfolgreich ist, während "get" voraussichtlich erfolgreich ist, es sei denn, es liegt ein ungewöhnliches Problem vor.
gnasher729

Was ist, wenn die Funktion einen optionalen Parameter akzeptiert, um die Ergebnisse basierend auf einer Bedingung zu filtern? Beides getund findwürde je nach Verwendungszweck zutreffen.
ESR

61

Ich würde sagen, das findkönnte scheitern, getsollte aber nicht.


25
Wenn Sie damit meinen, dass findNULL zurückgegeben getwerden kann, während NULL niemals zurückgegeben wird, aber möglicherweise ausgelöst (oder bestätigt) wird, stimme ich zu.
Sjoerd

1
Da stimme ich @Sjoerd voll und ganz zu.
22.01.13 Uhr

Und wenn der find()zurückkommt Optional<>? In diesem Fall findist auch nullsicher.
TheCoder

42

Um ein Gespräch zu zitieren, das ich oft mit meinen Kindern habe:

Ich: Hey Junge! Such mir ein paar Batterien

Kind: Aber wo sind sie?

Ich: Deshalb habe ich dir gesagt, du sollst sie suchen . Wenn ich gewusst hätte, wo sie sind, hätte ich dir gesagt, dass du sie holen sollst . Oder du könntest deine Mutter fragen.

Die gleiche Idee gilt:

  • Verwenden Sie "get" für eine Methode, die eine billig verfügbare Information zurückgibt (und möglicherweise inline oder anderweitig optimiert werden kann), oder für eine Information, die nur diesem Objekt gehört.

  • Verwenden Sie "find" für eine Methode, mit der Informationen abgerufen werden können, oder verwenden Sie andere Objekte, um sie zu finden.


16
Nur ein Programmierer würde dieses Gespräch mit seinen Kindern führen. "Möchtest du den Müll rausbringen?" "Nein." "Wirst du den Müll rausbringen?" "Ja."
Robert Harvey

@ Robert Harvey Ich glaube, ich habe dieses Problem mit Menschen. Wenn jemand versucht, etwas zu erklären, oder eine Frage stellt, stelle ich normalerweise Fragen zurück und sage ihm, er solle es ausdrücklich erklären. Ansonsten haben wir normalerweise ein XY-Problem. Wenn ich das nicht mache, fühle ich mich wie eine Funktion zum automatischen Vervollständigen beim Gehen. Sie wissen nicht, was Sie denken, Sie können es nicht in Worte fassen, Sie plappern ein paar Worte und erwarten von mir, dass ich das ganze "Denken" für Sie erledige und Ihnen dabei helfe? Nein, passiert nicht :)
akinuri

3

Suchen bedeutet, dass das Ergebnis nicht angezeigt wird, z. B. wenn eine Datenbankabfrage mit einigen Parametern ausgeführt wird, die sich zwischen den Aufrufen ändern können. Get hingegen impliziert, dass die Ergebnisse der Methode im Voraus bekannt sind oder sich nicht ändern, sobald bekannt ist, dass der Aufruf keine Parameter enthält.
Also würde ich zum Beispiel Customer findCustomerById (long customerId) und Customer getCustomer () verwenden.


3

Ich wende folgendes Muster an:

  • Foo GetFoo() kann nicht null zurückgeben und die Komplexität ist O (log (n)) oder weniger
  • bool TryGetFoo(out Foo) kann null zurückgeben und die Komplexität ist 0 (log (n)) oder weniger
  • Foo FindFoo() kann nicht null zurückgeben und die Komplexität ist größer als O (log (n))
  • bool TryFindFoo(out Foo) kann null zurückgeben und die Komplexität ist größer als O (log (n))

Auf diese Weise ist der Code ziemlich klar in Bezug auf die Absicht und die Komplexität, die Sie erwarten können.

In der Regel sind die Getter für den direkten Listen- oder Wörterbuch- / Satzzugriff vorgesehen.
Die Finder sind tiefe Suche, vollständiger Scan der Liste, etc ...

In deinem Fall:

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

+1 für die try, kurz und präzise
SpaceTrucker

2

getist auf jeden Fall angebracht - in der Tat wird oft angenommen, dass man das zuerst finden muss, um etwas zu bekommen. Wenn Sie sich nicht sicher sind, verwenden Sie get.

Ich würde findfür Methoden wie findMinimum()oder verwenden findOptimal(), dh, wenn es einen speziellen Algorithmus gibt, der den Rückgabewert berechnet und nicht einfach eine Anforderung an die Datenbank, das Dateisystem, den Remote-Server usw. sendet, um einige Daten zu empfangen.


1
Gute Argumente. Persönlich würde ich wahrscheinlich nicht findals Präfix in den Beispielen verwenden, die Sie zur Verfügung gestellt haben. Für Rechenaufgaben, wie in Ihrem Beispiel, würde ich calculateoder verwenden compute.
Knownasilya


1

Ich werde im Allgemeinen verwenden Get, um ein Objekt / einen Wert Findabzurufen und um dessen Position abzurufen (z. B. in einem Array).

zum Beispiel:

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

integer i = somearray.Find( 'name');

0

Für mich findbedeutet dies, dass möglicherweise mehr als ein Ergebnis vorliegt. getimpliziert nur eine.


8
Scheint, als hätte es dieses Gefühl, aber ich bin mir nicht sicher, ob ich dem vollkommen zustimme. Denken Sie daran , auf diese Weise: getCatvs findCatvs getCatsvs findCats. Das find..Symbol repräsentiert immer noch einzelne Objekte, die zurückgegeben werden. Meiner Meinung nach sollte der Plural zum Substantiv hinzugefügt werden.
Knownasilya
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.