Manchmal erstelle ich 'Util'-Klassen, die hauptsächlich dazu dienen, Methoden und Werte zu speichern, die anscheinend nicht wirklich woanders hingehören. Aber jedes Mal, wenn ich eine dieser Klassen erstelle, denke ich: "Oh, ich werde es später bereuen ...", weil ich irgendwo gelesen habe, dass es schlecht ist.
Auf der anderen Seite scheint es für sie zwei zwingende (zumindest für mich) Fälle zu geben:
- Implementierungsgeheimnisse, die in mehreren Klassen innerhalb eines Pakets verwendet werden
- Bereitstellung nützlicher Funktionen zur Erweiterung einer Klasse, ohne deren Schnittstelle zu überladen
Bin ich auf dem Weg zur Zerstörung? Was du sagst !! Soll ich umgestalten?
Util
in den Namen Ihrer Klassen. Problem gelöst.SomethingUtil
ist etwas faul und verschleiert nur den wahren Zweck der Klasse - genau wie bei Klassen mit dem NamenSomethingManager
oderSomethingService
. Wenn diese Klasse eine einzige Verantwortung hat, sollte es einfach sein, ihr einen aussagekräftigen Namen zu geben. Wenn nicht, ist das das eigentliche Problem ...Util
, obwohl ich offensichtlich nicht erwartet hatte, dass das fixiert und der Rest der Frage ignoriert wird ...Antworten:
Modernes OO-Design akzeptiert, dass nicht alles ein Objekt ist. Manche Dinge sind Verhaltensweisen oder Formeln, andere haben keinen Zustand. Es ist gut, diese Dinge als reine Funktionen zu modellieren, um die Vorteile dieses Designs zu nutzen.
Java und C # (und andere) erfordern, dass Sie eine Util-Klasse erstellen und durch diesen Rahmen springen, um dies zu tun. Ärgerlich, aber nicht das Ende der Welt; und aus gestalterischer Sicht nicht wirklich störend.
quelle
Sag niemals nie"
Ich denke nicht, dass es notwendigerweise schlecht ist, es ist nur schlecht, wenn man es schlecht macht und es missbraucht.
Wir alle brauchen Werkzeuge und Hilfsprogramme
Für den Anfang benutzen wir alle einige Bibliotheken, die manchmal als fast allgegenwärtig und unverzichtbar angesehen werden. Zum Beispiel in der Java-Welt Google Guava oder einige von Apache Commons ( Apache Commons Lang , Apache Commons Collections , etc ...).
Es besteht also eindeutig ein Bedarf für diese.
Vermeiden Sie Hard-Word, Vervielfältigung und das Einführen von Fehlern
Wenn Sie über diese denken , sind ziemlich einfach ein sehr großer Haufen dieser
Util
Klassen , die Sie beschreiben, außer jemand durch den großen Längen ging sie (relativ) Recht zu bekommen, und sie haben schon Zeit - getestet und stark ins Auge geballt durch andere.Ich würde also sagen, die erste Faustregel beim Schreiben einer
Util
Klasse ist, zu überprüfen, ob dieUtil
Klasse tatsächlich noch nicht existiert.Das einzige Gegenargument, das ich dafür gesehen habe, ist, wenn Sie Ihre Abhängigkeiten begrenzen möchten, weil:
Beides kann jedoch gelöst werden , indem Sie die Bibliothek mit ProGuard oder einem gleichwertigen Programm neu packen oder selbst zerlegen (für Maven- Benutzer bietet das Maven-Shade-Plugin einige Filtermuster , um diese in Ihren Build zu integrieren).
Wenn es sich also in einer Bibliothek befindet und mit Ihrem Anwendungsfall übereinstimmt und kein Benchmark etwas anderes angibt, verwenden Sie es. Wenn es ein bisschen von dem abweicht, was Sie tun, erweitern Sie es (wenn möglich) oder erweitern Sie es, oder schreiben Sie es in letzter Instanz neu.
Regeln der Namensgebung
Bisher habe ich sie jedoch so genannt
Util
wie Sie. Nennen Sie sie nicht so.Geben Sie ihnen aussagekräftige Namen. Nehmen Sie Google Guava als (sehr, sehr) gutes Beispiel, und stellen Sie sich vor, dass der
com.google.guava
Namespace tatsächlich Ihreutil
Wurzel ist.Nennen Sie Ihr Paket
util
im schlimmsten Fall, aber nicht die Klassen. Wenn es umString
Objekte und die Manipulation von String-Konstrukten geht, nennen Sie esStrings
nichtStringUtils
(Entschuldigung, Apache Commons Lang - ich mag und benutze Sie immer noch!). Wenn es etwas Bestimmtes tut, wähle einen bestimmten Klassennamen (wieSplitter
oderJoiner
).Gerätetest
Wenn Sie auf das Schreiben dieser Dienstprogramme zurückgreifen müssen, stellen Sie sicher, dass Sie diese Unit-Tests durchführen. Das Gute an Dienstprogrammen ist, dass es sich in der Regel um eigenständige Komponenten handelt, die bestimmte Eingaben annehmen und bestimmte Ausgaben zurückgeben. Das ist das Konzept. Es gibt also keine Entschuldigung, sie nicht einmal zu testen.
Durch Unit-Tests können Sie auch den API-Vertrag definieren und dokumentieren. Wenn die Tests abbrechen, haben Sie entweder etwas falsch geändert, oder Sie versuchen, den API-Vertrag zu ändern (oder Ihre ursprünglichen Tests waren Mist - lernen Sie daraus und wiederholen Sie sie nicht) .
API-Design
Die Designentscheidungen, die Sie für diese APIs treffen, werden Ihnen möglicherweise noch lange folgen.
Splitter
Seien Sie also vorsichtig , wenn Sie sich nicht stundenlang mit dem Schreiben eines Klons beschäftigen.Stellen Sie sich einige Fragen:
Sie möchten, dass diese Tools eine große Bandbreite von Anwendungsfällen abdecken, robust, stabil, gut dokumentiert und nach dem Prinzip der geringsten Überraschung in sich geschlossen sind. Im Idealfall kann jedes Unterpaket Ihrer Utils oder zumindest Ihr gesamtes Util-Paket zur einfachen Wiederverwendung in ein Bundle exportiert werden.
Lernen Sie hier wie gewohnt von Riesen:
util
Paket (das die Collections-Bibliothek enthält) und sein .Net-Äquivalent ,Ja, viele davon konzentrieren sich auf Sammlungen und Datenstrukturen, aber sagen Sie mir nicht, dass dies nicht der Ort oder das Ziel ist, an dem Sie die meisten Ihrer Utils normalerweise direkt oder indirekt implementieren.
quelle
If deals with String objects and manipulation of string constructs, call it Strings, not StringUtils
StringsCollectionTypeHere
wenn du eine konkrete umsetzung willst. Oder einen genaueren Namen, wenn diese Zeichenfolgen im Kontext Ihrer App eine bestimmte Bedeutung haben. Für diesen speziellen Fall verwendet GuavaStrings
im Gegensatz zuStringUtils
Commons Lang seine stringbezogenen Helfer . Ich finde es vollkommen akzeptabel, es bedeutet für mich nur, dass die KlassenString
Objekte verarbeiten oder eine Allzweckklasse zum Verwalten von Strings sind.NameUtils
mich Sachen, denn wenn es unter einem klar gekennzeichneten Paketnamen steht, würde ich bereits wissen, dass es sich um eine Utility-Klasse handelt (und wenn nicht, würde ich es schnell herausfinden, wenn ich mir die API anschaue). Es ist so ärgerlich für mich als Menschen Sachen wie erklärtSomethingInterface
,ISomething
oderSomethingImpl
. Ich war mit solchen Artefakten einigermaßen einverstanden, als ich in C codierte und keine IDEs verwendete. Heute würde ich solche Dinge im Allgemeinen nicht brauchen.Util-Klassen sind nicht zusammenhängend und im Allgemeinen schlecht gestaltet, da eine Klasse einen einzigen Änderungsgrund haben muss (Prinzip der einheitlichen Verantwortung).
Doch habe ich „util“ Klassen in dem sehr Java API gesehen, wie:
Math
,Collections
undArrays
.Dies sind in der Tat Dienstprogrammklassen, aber alle ihre Methoden beziehen sich auf ein einziges Thema, eine hat mathematische Operationen, eine Methoden zum Bearbeiten von Sammlungen und die andere zum Bearbeiten von Arrays.
Versuchen Sie nicht, völlig unabhängige Methoden in einer Utility-Klasse zu haben. Wenn dies der Fall ist, können Sie sie wahrscheinlich auch woanders hinstellen, wo sie wirklich hingehören.
Wenn Sie util-Klassen haben müssen, versuchen Sie, diese nach Themen wie Java's
Math
,Collections
and zu trennenArrays
. Zumindest zeigt es eine Absicht des Designs, auch wenn es sich nur um Namespaces handelt.Ich jedenfalls vermeide immer Gebrauchsklassen und hatte nie das Bedürfnis , eine zu erstellen.
quelle
Math
oderArrays
zeigt zumindest eine Absicht des Designs.Es ist durchaus akzeptabel, Util- Klassen zu haben , obwohl ich den Begriff bevorzuge
ClassNameHelper
. Die .NET BCL enthält sogar Hilfsklassen. Das Wichtigste, an das Sie sich erinnern sollten, ist, den Zweck der Klassen sowie jede einzelne Hilfsmethode gründlich zu dokumentieren und sie zu einem wartbaren Code von hoher Qualität zu machen.Und lassen Sie sich nicht von Helferklassen mitreißen.
quelle
Ich benutze einen zweistufigen Ansatz. Eine "Globals" -Klasse in einem "util" -Paket (Ordner). Damit etwas in eine "Globals" -Klasse oder ein "util" -Paket aufgenommen werden kann, muss es sein:
Beispiele, die diese Tests bestehen:
Hier ist ein Beispiel für eine sehr kleine Hilfsmethode, die vom Rest der Anwendung völlig unabhängig ist:
Wenn ich mir das ansehe, sehe ich einen Fehler, der besagt, dass 21 "21st", 22 "22nd" usw. sein sollte, aber das ist nicht der springende Punkt.
Wenn eine dieser Hilfsmethoden wächst oder kompliziert wird, sollte sie in eine eigene Klasse im util-Paket verschoben werden. Wenn zwei oder mehr Hilfsklassen im util-Paket miteinander verknüpft sind, sollten sie in ein eigenes Paket verschoben werden. Wenn sich herausstellt, dass eine Konstanten- oder Hilfsmethode mit einem bestimmten Teil Ihrer Anwendung zusammenhängt, sollte sie dorthin verschoben werden.
Sie sollten in der Lage sein zu rechtfertigen, warum es keinen besseren Ort für alles gibt, was Sie in einer Globals-Klasse oder einem Util-Paket festhalten, und Sie sollten es regelmäßig mit den oben genannten Tests reinigen. Ansonsten schaffen Sie nur ein Durcheinander.
quelle