Angenommen, eine Schnittstelle enthält die folgenden Methoden:
Car find(long id);
List<Car> find(String model);
Ist es besser, sie so umzubenennen?
Car findById(long id);
List findByModel(String model);
In der Tat muss jeder Entwickler, der diese API verwendet, nicht in der Benutzeroberfläche nach möglichen Argumenten für anfängliche find()
Methoden suchen .
Meine Frage ist also allgemeiner: Welchen Vorteil hat die Verwendung überladener Methoden im Code, da sie die Lesbarkeit beeinträchtigen?
Antworten:
Dies ist ein relativ kleines Problem im Vergleich zu vielen anderen schlechten Lesbarkeitspraktiken, für die Sie anfällig sein könnten. Ich würde daher sagen, es ist hauptsächlich eine Frage des Geschmacks, wie Sie Ihre Methoden benennen.
Vor diesem Hintergrund würde ich, wenn Sie etwas dagegen unternehmen wollen, wie folgt vorgehen:
Überlastung wenn ...
Die Methoden entsprechen nahezu demselben Vertrag, funktionieren jedoch nur mit unterschiedlichen Eingaben (stellen Sie sich einen Telefonanbieter vor, der Ihr Konto anhand Ihrer persönlichen Steuer-ID-Nummer, Ihrer Kontonummer oder Ihres Namens und Ihres Geburtstages nachschlagen kann). Dies schließt die Rückgabe des gleichen Ausgabetyps ein .
Verwenden Sie einen anderen Namen, wenn ...
Die Methoden führen erheblich unterschiedliche Aktionen aus oder geben unterschiedliche Ausgaben zurück (wie in Ihrem Fall). Sie können einen anderen Namen verwenden, wenn einer auf die Datenbank zugreift und einer nicht.
Wenn der zurückgegebene Typ anders ist, würde ich außerdem das Verb so ändern, dass Folgendes angezeigt wird:
quelle
Ich würde auf jeden Fall empfehlen, einen anderen Namen zu verwenden. Es ist möglich, dass Sie zu einem späteren Zeitpunkt eine andere Methode hinzufügen möchten
List<Car> findByMake(String make)
, beispielsweise im Gegensatz zuList<Car> findByModel(String model)
. So plötzlichfind
macht es keinen Sinn mehr , alles anzurufen. Es ist auch weniger wahrscheinlich, dass Ihre Methoden versehentlich falsch verwendet werden, wenn ihre Namen weitere Informationen darüber enthalten, wie sie verwendet werden sollen.quelle
find(Make val)
undfind(Model val)
. DannfindByMake(String val)
wären Convenience-Methoden wie viel klarer, was sie tatsächlich tun. Schließlich ist aString
weder ein Fabrikat noch ein Modell, daher sollte die Methode erklären, was sie wirklich tut.Wenn Sie eine Methode umbenennen, wird sie nicht mehr überladen. An und für sich macht das Überladen den Code nicht unbedingt weniger lesbar, es kann jedoch schwieriger sein, der Implementierung zu folgen, wenn die Syntax nicht klar ist.
Viele Sprachen verwenden Methodenüberladung als Mittel, um eine Schnittstelle für Funktionen bereitzustellen, bei denen die Parameter optional sein können und Standardeinstellungen für die optionalen Parameter impliziert sind. Dies gilt insbesondere für Sprachen, die keine Standardparametersyntax in der Methodendeklaration unterstützen.
Also mach das:
erspart Ihnen dies:
Was lesbarer ist, hängt wirklich von Ihnen ab. Persönlich bevorzuge ich die zweite Option, insbesondere wenn die Parameterliste etwas lang wird, aber ich nehme an, dass es nicht wirklich wichtig ist, solange Sie in Ihrer API konsistent sind.
Die Schwierigkeit beim Überladen entsteht, wenn Sie Funktionen wünschen, die im Wesentlichen dasselbe tun, und wenn Sie möchten, dass die Parameterlisten gleich sind, die Rückgabetypen jedoch unterschiedlich sind. Die meisten Sprachen können nicht zwischen zwei gleichnamigen Methoden mit unterschiedlichen Rückgabetypen unterscheiden. An diesem Punkt müssen Sie überlegen, ob Sie entweder Generika verwenden, die Parameterschnittstelle ändern oder eine Ihrer Methoden umbenennen möchten, um den Unterschied im Rückgabetyp anzuzeigen. Hier kann die Lesbarkeit zu einem großen Problem werden, wenn Sie sich nicht für ein einfaches und klares Benennungsschema entscheiden, um mit solchen Situationen fertig zu werden.
Nennen Sie Ihre überladenen Methoden
GetSomething()
undGetSomethingEx()
sagen Sie nicht viel darüber aus, was die Unterschiede zwischen Ihren Methoden sind, besonders wenn es die Rückgabetypen sind, die die einzigen Unterschiede zwischen ihnen sind. Auf der anderen Seite,GetSomethingAsInt()
undGetSomethingAsString()
erzählen Sie ein wenig mehr über das, was die Methoden tun, und zwar nicht unbedingt eine Überlastung zu tun zeigen , dass die beiden Methoden tun ähnliche Dinge, aber unterschiedliche Werttypen zurück. Ich weiß, dass es andere Möglichkeiten gibt, Methoden zu nennen, aber zum Zwecke der Veranschaulichung sollten diese groben Beispiele dies tun.Im OPs-Beispiel ist das Umbenennen nicht unbedingt erforderlich, da die Methodenparameter unterschiedlich sind. Es macht jedoch die Benennung einer Methode etwas klarer. Am Ende kommt es wirklich auf die Art der Benutzeroberfläche an, die Sie Ihren Benutzern präsentieren möchten. Eine Entscheidung darüber, ob Sie nicht überladen möchten, sollte nicht ausschließlich auf Ihrer eigenen Wahrnehmung der Lesbarkeit beruhen. Das Überladen von Methoden kann beispielsweise eine API-Schnittstelle vereinfachen und die Anzahl der Methoden verringern, an die sich ein Entwickler erinnern muss. Andererseits kann es die Schnittstelle in einem Maße verschleiern, dass ein Entwickler die Methodendokumentation lesen muss, um zu verstehen, welches Formular verwendet wird der zu verwendenden Methode, wohingegen eine Reihe von Methoden mit ähnlichem und dennoch beschreibendem Namen es offensichtlicher machen kann, nur einen Methodennamen hinsichtlich seines Zwecks zu lesen.
quelle
Bevorzugen Sie das Überladen, solange die Methoden dasselbe zurückgeben und denselben Vertrag befolgen. Durch das Überladen wird der aufrufende Code nicht unnötig an den Parametertyp gebunden.
Angenommen, die aufrufende Funktion empfängt eine Suchabfrage als Parameter und führt vor und / oder nach dem Aufruf von eine andere Verarbeitung durch
find
.Wenn Sie den Typ dieser Abfrage aus irgendeinem Grund später ändern möchten (z. B. von einer einfachen ID-Zeichenfolge zu einem Abfrageobjekt mit vollem Funktionsumfang), können Sie diese Änderung in der aufrufenden Funktion vornehmen, indem Sie einfach die Funktionssignatur ändern Akzeptieren Sie den neuen Parametertyp, ohne sich Gedanken über die Änderung der Methode zu machen, die er für Ihre Klasse aufruft.
Wenn Sie implementieren
findById
undfindByQueryObject
separat, müssten Sie jeden Anruf nachholen, um diese Änderung vorzunehmen. Im Beispiel habe ich nur ein Wort geändert und war fertig.quelle
findByFoo
, um Typenkonflikte früher zu erkennen.