Klasse, die nichts repräsentiert - stimmt das?

42

Ich entwerfe gerade meine Anwendung und bin mir nicht sicher, ob ich SOLID und OOP richtig verstehe. Klassen sollten eine Sache tun und es gut machen, aber andererseits sollten sie reale Objekte darstellen, mit denen wir arbeiten.

In meinem Fall mache ich eine Feature-Extraktion für einen Datensatz und dann eine Analyse des maschinellen Lernens. Ich gehe davon aus, dass ich drei Klassen schaffen könnte

  1. FeatureExtractor
  2. DataSet
  3. Analyzer

Aber die FeatureExtractor-Klasse stellt nichts dar, sie tut etwas, was sie eher zu einer Routine als zu einer Klasse macht. Es wird nur eine Funktion verwendet: extract_features ()

Ist es richtig, Klassen zu erstellen, die nicht eine Sache darstellen, sondern eine Sache tun?

EDIT: nicht sicher, ob es wichtig ist, aber ich benutze Python

Und wenn extract_features () so aussehen würde: Lohnt es sich, eine spezielle Klasse für diese Methode zu erstellen?

def extract_features(df):
    extr = PhrasesExtractor()
    extr.build_vocabulary(df["Text"].tolist())

    sent = SentimentAnalyser()
    sent.load()

    df = add_features(df, extr.features)
    df = mark_features(df, extr.extract_features)
    df = drop_infrequent_features(df)
    df = another_processing1(df)
    df = another_processing2(df)
    df = another_processing3(df)
    df = set_sentiment(df, sent.get_sentiment)
    return df
Alicja Głowacka
quelle
13
Das sieht als Funktion ganz gut aus. Wenn Sie die drei von Ihnen als Module aufgelisteten Dinge in Betracht ziehen, ist es in Ordnung, sie in verschiedenen Dateien zu platzieren. Dies bedeutet jedoch nicht, dass es sich um Klassen handeln muss.
Bergi
31
Beachten Sie, dass die Verwendung von Nicht-OO-Ansätzen in Python durchaus üblich und akzeptabel ist.
jpmc26
13
Sie könnten an Domain Driven Design interessiert sein. Die "Klassen sollten Objekte aus der realen Welt darstellen" ist eigentlich falsch ... sie sollten Objekte in der Domäne darstellen . Die Domäne ist oft stark mit der realen Welt verbunden, aber abhängig von der Anwendung können einige Dinge als Objekte betrachtet werden oder nicht, oder einige Dinge, die "in Wirklichkeit" getrennt sind, können innerhalb der Domäne der Anwendung entweder verknüpft oder identisch sein.
Bakuriu
1
Wenn Sie mit OOP vertraut werden, werden Sie wahrscheinlich feststellen, dass Klassen sehr selten eins zu eins mit realen Entitäten korrespondieren. Zum Beispiel ist hier ein Aufsatz, der argumentiert, dass der Versuch, alle mit einer realen Entität in einer einzelnen Klasse verbundenen Funktionen zu blockieren, sehr häufig ein Anti-Pattern ist: programmer.97things.oreilly.com/wiki/index.php/…
Kevin - Setzen Sie Monica am
1
"Sie sollten reale Objekte darstellen, mit denen wir arbeiten." nicht unbedingt. Viele Sprachen haben eine Stream-Klasse, die einen Stream von Bytes darstellt. Dies ist eher ein abstraktes Konzept als ein "reales Objekt". Technisch gesehen ist ein Dateisystem auch kein 'echtes Objekt', sondern nur ein Konzept, aber manchmal gibt es Klassen, die ein Dateisystem oder einen Teil davon darstellen.
Pharap

Antworten:

96

Klassen sollten 1 Sache tun und es gut machen

Ja, das ist im Allgemeinen ein guter Ansatz.

Auf der anderen Seite sollten sie jedoch ein reales Objekt darstellen, mit dem wir arbeiten.

Nein, das ist meiner Meinung nach ein weit verbreitetes Missverständnis. Der Zugang eines guten Anfängers zu OOP besteht oft darin, "mit Objekten zu beginnen, die Dinge aus der realen Welt darstellen" , das ist wahr.

Damit sollten Sie jedoch nicht aufhören !

Klassen können (und sollten) verwendet werden, um Ihr Programm auf verschiedene Arten zu strukturieren. Das Modellieren von Objekten aus der realen Welt ist ein Aspekt, aber nicht der einzige. Das Erstellen von Modulen oder Komponenten für eine bestimmte Aufgabe ist ein weiterer sinnvoller Anwendungsfall für Klassen. Ein "Feature Extractor" ist wahrscheinlich ein solches Modul, und selbst wenn es nur eine öffentliche Methode enthält extract_features(), würde ich mich wundern, wenn es nicht auch viele private Methoden und möglicherweise einen gemeinsamen Status enthält. Wenn Sie also eine Klasse FeatureExtractorhaben, erhalten Sie einen natürlichen Ort für diese privaten Methoden.

Randnotiz: In Sprachen wie Python, die ein separates Modulkonzept unterstützen, kann man auch ein Modul FeatureExtractordafür verwenden, aber im Kontext dieser Frage ist dies meiner Meinung nach ein vernachlässigbarer Unterschied.

Darüber hinaus kann man sich einen "Merkmalsextraktor" als "eine Person oder einen Bot vorstellen, der Merkmale extrahiert". Das ist ein abstraktes "Ding", vielleicht nicht etwas, das man in der realen Welt findet, aber der Name selbst ist eine nützliche Abstraktion, die jedem eine Vorstellung davon gibt, was die Verantwortung dieser Klasse ist. Ich bin also anderer Meinung, dass diese Klasse "nichts darstellt".

Doc Brown
quelle
33
Mir gefällt besonders, dass Sie die Frage des inneren Zustands angesprochen haben. Ich finde oft, dass dies der entscheidende Faktor dafür ist, ob ich etwas in Python zu einer Klasse oder zu einer Funktion mache.
David Z
17
Sie scheinen "Klassitis" zu empfehlen. Machen Sie keine Klasse dafür, es ist ein Java-Antipattern. Wenn es sich um eine Funktion handelt, machen Sie sie zu einer Funktion. Interner Zustand ist irrelevant: Funktionen können das haben (über Verschlüsse).
Konrad Rudolph
25
@KonradRudolph: Du scheinst verpasst zu haben, dass es nicht darum geht, eine Funktion zu machen. Hierbei handelt es sich um einen Code, für den mehrere Funktionen, ein gemeinsamer Name und möglicherweise ein gemeinsamer Status erforderlich sind . Die Verwendung eines Moduls hierfür kann in Sprachen mit einem Modulkonzept sinnvoll sein, das von Klassen getrennt ist.
Doc Brown
8
@ DocBrown Ich muss nicht zustimmen. Es ist eine Klasse mit einer öffentlichen Methode. API weise, das ist nicht von einer Funktion zu unterscheiden. Siehe meine Antwort für Details. Die Verwendung von Klassen mit nur einer Methode kann gerechtfertigt sein, wenn Sie einen bestimmten Typ erstellen müssen, um einen Status darzustellen. Dies ist hier jedoch nicht der Fall (und selbst dann können manchmal Funktionen verwendet werden).
Konrad Rudolph
6
@ DocBrown Ich beginne zu verstehen, was Sie meinen: Sie sprechen über die Funktionen, die von innen aufgerufen werden extract_features? Ich ging einfach davon aus, dass es sich um öffentliche Veranstaltungen von einem anderen Ort aus handelt. Fairerweise bin ich damit einverstanden, dass wenn diese privat sind, sie wahrscheinlich in ein Modul aufgenommen werden sollten (aber immer noch: keine Klasse, es sei denn, sie teilen den Status), zusammen mit extract_features. (Das heißt, Sie können sie natürlich lokal innerhalb dieser Funktion deklarieren.)
Konrad Rudolph
44

Doc Brown ist genau richtig: Klassen müssen keine realen Objekte darstellen. Sie müssen nur nützlich sein . Klassen sind grundsätzlich nur zusätzliche Typen, und was bedeutet intoder stringentspricht das in der realen Welt? Es sind abstrakte Beschreibungen, keine konkreten, greifbaren Dinge.

Das heißt, Ihr Fall ist etwas Besonderes. Nach Ihrer Beschreibung:

Und wenn extract_features () so aussehen würde: Lohnt es sich, eine spezielle Klasse für diese Methode zu erstellen?

Sie haben vollkommen recht: Wenn Ihr Code wie abgebildet ist, hat es keinen Sinn, ihn in eine Klasse zu verwandeln. Es gibt einen berühmten Vortrag , der argumentiert, dass solche Verwendungen von Klassen in Python Code-Geruch sind und dass einfache Funktionen oft ausreichen. Ihr Fall ist ein perfektes Beispiel dafür.

Überbeanspruchung von Klassen ist auf die Tatsache zurückzuführen, dass OOP in den 1990er Jahren mit Java zum Mainstream wurde. Leider fehlten in Java zu dieser Zeit einige moderne Sprachfunktionen (z. B. Closures), was dazu führte, dass viele Konzepte ohne den Einsatz von Klassen nur schwer oder gar nicht auszudrücken waren. Zum Beispiel war es in Java bis vor kurzem unmöglich, Methoden zu haben, die state (dh closures) trugen. Stattdessen mussten Sie eine Klasse schreiben, die den Status enthält und eine einzelne Methode (so etwas wie invoke) verfügbar macht .

Leider wurde dieser Programmierstil weit über Java hinaus populär (teilweise aufgrund eines einflussreichen Softwareentwicklungsbuchs , das ansonsten sehr nützlich ist), auch in Sprachen, die keine derartigen Problemumgehungen erfordern.

In Python sind Klassen offensichtlich ein sehr wichtiges Werkzeug und sollten großzügig eingesetzt werden. Aber sie sind nicht das einzige Werkzeug, und es gibt keinen Grund, sie dort einzusetzen, wo sie keinen Sinn ergeben. Es ist ein weit verbreitetes Missverständnis, dass freie Funktionen in OOP keinen Platz haben.

Konrad Rudolph
quelle
Wenn es sich bei den im Beispiel aufgerufenen Funktionen tatsächlich um private Funktionen handelt, ist es durchaus angebracht, sie in einem Modul oder einer Klasse zu kapseln. Ansonsten stimme ich voll und ganz zu.
Leliel
11
Auch nützlich, um sich daran zu erinnern, dass "OOP" nicht "eine Reihe von Klassen schreiben" bedeutet. Funktionen sind Objekte in Python, daher muss dies nicht als "nicht OOP" betrachtet werden. Vielmehr werden die eingebauten Typen / Klassen einfach wiederverwendet , und "Wiederverwendung" ist einer der heiligen Punkte beim Programmieren. Dies in eine Klasse zu packen, würde die Wiederverwendung verhindern, da nichts mit dieser neuen API kompatibel wäre (es __call__sei denn, es ist definiert, verwenden Sie in diesem Fall einfach eine Funktion!)
Warbo
3
Auch zum Thema "Klassen vs. freistehende Funktionen": eev.ee/blog/2013/03/03/…
Joker_vD
1
Ist es nicht so, dass "freie Funktionen" in Python auch Objekte mit einem Typ sind, der eine Methode verfügbar macht __call__()? Unterscheidet sich das wirklich von einer anonymen Instanz der inneren Klasse? Syntaktisch gesehen, sicher, aber von einem Sprachentwurf abgesehen, scheint es eine weniger bedeutende Unterscheidung zu sein, als Sie hier präsentieren.
JimmyJames
1
@ JimmyJames Richtig. Der springende Punkt ist, dass sie die gleiche Funktionalität für den bestimmten Zweck bieten, aber einfacher zu bedienen sind.
Konrad Rudolph
36

Ich entwerfe gerade meine Anwendung und bin mir nicht sicher, ob ich SOLID und OOP richtig verstehe.

Seit über 20 Jahren dabei und ich bin mir auch nicht sicher.

Klassen sollten 1 Sache tun und es gut machen

Hier kann man kaum etwas falsch machen.

Sie sollten reale Objekte darstellen, mit denen wir arbeiten.

Ja wirklich? Lassen Sie mich Ihnen die Einzel beliebtesten und erfolgreichsten Klasse aller Zeiten: String. Wir verwenden es für Text. Und das Objekt der realen Welt, das es darstellt, ist folgendes:

Der Fischer hält 10 Fische an einer Schnur

Warum nein, nicht alle Programmierer sind vom Fischen besessen. Hier verwenden wir eine sogenannte Metapher. Es ist in Ordnung, Modelle von Dingen zu erstellen, die nicht wirklich existieren. Es ist die Idee, die klar sein muss. Sie erstellen Bilder in den Köpfen Ihrer Leser. Diese Bilder müssen nicht echt sein. Einfach verstanden.

Ein gutes OOP-Design gruppiert Nachrichten (Methoden) um Daten (Status), sodass die Reaktionen auf diese Nachrichten je nach den Daten variieren können. Wenn Sie das tun, dann modellieren Sie eine reale Sache, schick. Wenn nicht, na ja. Solange es für den Leser sinnvoll ist, ist es in Ordnung.

Nun sicher, Sie könnten sich das so vorstellen:

Festliche Briefe, die an einer Schnur aufgehängt sind, lauten "LETS DO THINGS!"

Aber wenn Sie denken, dass dies in der realen Welt existieren muss, bevor Sie die Metapher verwenden können, wird Ihre Programmierkarriere eine Menge Kunst und Handwerk beinhalten.

kandierte_orange
quelle
1
Eine schöne Reihe von Bildern ...
Zev Spitz
Zu diesem Zeitpunkt bin ich mir nicht sicher, ob "string" überhaupt metaphorisch ist. Es hat nur eine bestimmte Bedeutung in der Programmierdomäne, wie Wörter wie classund tableund column...
Kyralessa
@Kyralessa du lehrst den Neuling die Metapher oder du lässt es magisch für sie sein. Bitte rette mich vor Programmierern, die an Magie glauben.
candied_orange
6

In acht nehmen! Nirgendwo sagt SOLID, dass eine Klasse nur "eine Sache tun" sollte. Wenn dies der Fall wäre, hätten Klassen immer nur eine einzige Methode, und es würde keinen wirklichen Unterschied zwischen Klassen und Funktionen geben.

SOLID sagt, dass eine Klasse eine einzelne Verantwortung darstellen sollte . Dies entspricht in etwa der Verantwortung von Personen in einem Team: dem Fahrer, dem Anwalt, dem Taschendieb, dem Grafikdesigner usw. Jede dieser Personen kann mehrere (verwandte) Aufgaben ausführen, die jedoch alle eine einzelne Verantwortung betreffen.

Der springende Punkt dabei ist: Wenn sich die Anforderungen ändern, müssen Sie idealerweise nur eine einzelne Klasse ändern. Dies macht den Code einfacher zu verstehen, einfacher zu ändern und reduziert das Risiko.

Es gibt keine Regel, dass ein Objekt "eine reale Sache" darstellen sollte. Dies ist nur eine Frachtkult-Überlieferung, da OO ursprünglich für die Verwendung in Simulationen erfunden wurde. Da es sich bei Ihrem Programm jedoch nicht um eine Simulation handelt (es gibt nur wenige moderne OO-Anwendungen), gilt diese Regel nicht. Solange jede Klasse eine klar definierte Verantwortung hat, sollte es Ihnen gut gehen.

Wenn eine Klasse wirklich nur eine einzige Methode hat und die Klasse keinen Status hat, können Sie in Betracht ziehen, sie zu einer eigenständigen Funktion zu machen. Dies ist absolut in Ordnung und folgt den KISS- und YAGNI-Prinzipien - Sie müssen keine Klasse erstellen, wenn Sie sie mit einer Funktion lösen können. Wenn Sie jedoch Grund zu der Annahme haben, dass Sie möglicherweise einen internen Status oder mehrere Implementierungen benötigen, können Sie dies auch zu einer Klasse von vornherein machen. Sie müssen hier Ihr bestes Urteilsvermögen anwenden.

JacquesB
quelle
+1 für "keine Notwendigkeit, eine Klasse zu erstellen, wenn Sie sie mit einer Funktion lösen können". Manchmal muss jemand die Wahrheit sagen.
Tchrist
5

Ist es richtig, Klassen zu erstellen, die nicht eine Sache darstellen, sondern eine Sache tun?

Im Allgemeinen ist das in Ordnung.

Ohne ein bisschen genauere Beschreibung, was die FeatureExtractorKlasse genau machen soll, ist es schwer zu sagen.

Wie auch immer, selbst wenn das FeatureExtractornur eine öffentliche extract_features()Funktion verfügbar macht , könnte ich daran denken, sie mit einer StrategyKlasse zu konfigurieren , die bestimmt, wie genau die Extraktion durchgeführt werden soll.

Ein weiteres Beispiel ist eine Klasse mit einer Template-Funktion .

Und es gibt weitere Verhaltensentwurfsmuster , die auf Klassenmodellen basieren.


Wie Sie einige Code zur Verdeutlichung hinzugefügt.

Und wenn extract_features () so aussehen würde: Lohnt es sich, eine spezielle Klasse für diese Methode zu erstellen?

Die Linie

 sent = SentimentAnalyser()

genau das, was ich damit gemeint habe, dass man eine klasse mit einer strategie konfigurieren kann .

Wenn Sie eine Schnittstelle für diese SentimentAnalyserKlasse haben, können Sie sie an die FeatureExtractorKlasse an ihrem Konstruktionspunkt übergeben, anstatt sie direkt an diese spezifische Implementierung in Ihrer Funktion zu koppeln.

πάντα ῥεῥ
quelle
2
Ich sehe keinen Grund, Komplexität (eine FeatureExtractorKlasse) hinzuzufügen, nur um noch mehr Komplexität (eine Schnittstelle für die SentimentAnalyserKlasse) einzuführen . Wenn eine Entkopplung erwünscht ist, extract_featureskann die get_sentimentFunktion als Argument verwendet werden (der loadAufruf scheint von der Funktion unabhängig zu sein und wird nur nach ihren Auswirkungen aufgerufen). Beachten Sie auch, dass Python keine Schnittstellen hat / anregt.
Warbo
1
@warbo - selbst wenn Sie die Funktion als Argument angeben, indem Sie sie zu einer Funktion machen, schränken Sie mögliche Implementierungen ein, die in das Format einer Funktion passen. Wenn jedoch ein dauerhafter Status zwischen einem Aufruf und dem folgenden verwaltet werden muss Als nächstes (zB a CacheingFeatureExtractoroder a TimeSeriesDependentFeatureExtractor) würde ein Objekt viel besser passen. Nur weil es für ein Objekt keine Notwendigkeit zur Zeit bedeutet nicht , wird es nie sein.
Jules
3
@Jules Erstens brauchen Sie es nicht (YAGNI), zweitens können Python-Funktionen auf persistente Zustände (Closures) verweisen, wenn Sie es brauchen (Sie werden es nicht brauchen), drittens schränkt die Verwendung einer Funktion nichts ein, da jedes Objekt mit a __call__Die Methode ist kompatibel, wenn Sie sie benötigen (Sie werden es nicht tun), viertens, indem Sie einen Wrapper hinzufügen, als würden FeatureExtractorSie den Code mit allen anderen jemals geschriebenen Codes inkompatibel machen (es sei denn, Sie geben eine __call__Methode an, in diesem Fall würde eine Funktion deutlich einfacher )
Warbo
0

Abgesehen von Mustern und all den ausgefallenen Sprachen / Konzepten ist das, worüber Sie gestolpert sind, ein Job oder ein Stapelprozess .

Letztendlich muss sogar ein reines OOP-Programm von etwas getrieben werden, um tatsächlich Arbeit zu leisten. Irgendwie muss es einen Einstiegspunkt geben. In dem MVC-Muster beispielsweise empfängt der "C" -Ontroller Click-Ereignisse usw. von der GUI und orchestriert dann die anderen Komponenten. In klassischen Befehlszeilentools würde eine "Haupt" -Funktion dasselbe tun.

Ist es richtig, Klassen zu erstellen, die nicht eine Sache darstellen, sondern eine Sache tun?

Ihre Klasse repräsentiert eine Entität, die etwas tut und alles andere orchestriert. Sie können es Controller , Job , Main oder was auch immer in den Sinn kommt nennen.

Und wenn extract_features () so aussehen würde: Lohnt es sich, eine spezielle Klasse für diese Methode zu erstellen?

Das hängt von den Umständen ab (und ich bin nicht mit der üblichen Vorgehensweise in Python vertraut). Wenn dies nur ein kleines One-Shot-Kommandozeilen-Tool ist, sollte eine Methode anstelle einer Klasse in Ordnung sein. Die erste Version Ihres Programms kann sicher mit einer Methode davonkommen. Wenn Sie später feststellen, dass Sie am Ende Dutzende solcher Methoden haben, vielleicht sogar mit globalen Variablen, dann ist es an der Zeit, die Klassen neu zu faktorisieren.

AnoE
quelle
3
Beachten Sie, dass das Aufrufen von Standalone-Prozeduren in solchen Szenarien verwirrend sein kann. Die meisten Sprachen, einschließlich Python, nennen sie "Funktionen". "Methoden" sind Funktionen / Prozeduren, die an eine bestimmte Instanz einer Klasse gebunden sind.
Dies
Richtig, @Warbo. Oder wir könnten sie Prozedur oder Defun oder Sub oder ... nennen; und sie können Klassenmethoden (sic) sein, die sich nicht auf eine Instanz beziehen. Ich hoffe, dass der sanfte Leser die beabsichtigte Bedeutung abstrahieren kann. :)
AnoE
@Warbo das ist gut zu wissen! Das meiste Lernmaterial, auf das ich gestoßen bin, besagt, dass die Begriffe Funktion und Methode austauschbar sind und dass es lediglich eine sprachabhängige Präferenz ist.
Dom
@Dom Im Allgemeinen ist eine ("reine") "Funktion" eine Zuordnung von Eingabewerten zu Ausgabewerten. Eine "Prozedur" ist eine Funktion, die auch Auswirkungen haben kann (z. B. Löschen einer Datei). beide werden statisch versandt (dh im lexikalischen Bereich nachgeschlagen). Eine "Methode" ist eine Funktion oder (normalerweise) Prozedur, die dynamisch von einem Wert (als "Objekt" bezeichnet) abgesetzt (nachgeschlagen) wird, der automatisch an ein (implizites thisoder explizites self) Argument der Methode gebunden wird. Die Methoden eines Objekts sind gegenseitig "offen" rekursiv, sodass beim Ersetzen fooalle self.fooAufrufe diese Ersetzung verwenden.
Warbo
0

Wir können uns OOP als Modellierung des Verhaltens eines Systems vorstellen . Beachten Sie, dass das System nicht in der "realen Welt" existieren muss, obwohl Metaphern in der realen Welt manchmal nützlich sein können (z. B. "Pipelines", "Fabriken" usw.).

Wenn unser gewünschtes System zu kompliziert ist, um es auf einmal zu modellieren, können wir es in kleinere Teile zerlegen und diese (die "Problemdomäne") modellieren, was eine weitere Zerlegung beinhalten kann, und so weiter, bis wir zu Teilen kommen, deren Verhalten übereinstimmt (mehr oder weniger) das eines eingebauten Sprachobjekts wie einer Zahl, einer Zeichenkette, einer Liste usw.

Sobald wir diese einfachen Teile haben, können wir sie kombinieren, um das Verhalten größerer Teile zu beschreiben, die wir zu noch größeren Teilen kombinieren können, und so weiter, bis wir alle Komponenten des Bereichs beschreiben können, die für ein Ganzes benötigt werden System.

In dieser Phase des "Zusammenfügens" könnten wir einige Klassen schreiben. Wir schreiben Klassen, wenn es kein Objekt gibt, das sich so verhält, wie wir es wollen. Beispielsweise könnte unsere Domain "foos", Sammlungen von foos, die als "bars" bezeichnet werden, und Sammlungen von Bars, die als "bazs" bezeichnet werden, enthalten. Wir bemerken vielleicht, dass Foos einfach genug sind, um mit Strings zu modellieren, also machen wir das. Wir stellen fest, dass Balken erfordern, dass ihr Inhalt einer bestimmten Einschränkung entspricht, die nicht mit den von Python bereitgestellten übereinstimmt. In diesem Fall schreiben wir möglicherweise eine neue Klasse, um diese Einschränkung zu erzwingen. Vielleicht haben Bas keine derartigen Besonderheiten, deshalb können wir sie nur mit einer Liste darstellen.

Beachten Sie, dass wir konnten eine neue Klasse für jede dieser Komponenten (Foos, Bars und bazs) schreiben, aber wir nicht brauchen , um , wenn es schon etwas mit dem richtigen Verhalten. Insbesondere, damit eine Klasse nützlich ist, muss sie etwas "bereitstellen" (Daten, Methoden, Konstanten, Unterklassen usw.). Selbst wenn wir viele Ebenen von benutzerdefinierten Klassen haben, müssen wir schließlich ein eingebautes Feature verwenden. Wenn wir beispielsweise eine neue Klasse für foos schreiben würden, würde sie wahrscheinlich nur einen String enthalten. Warum also nicht die foo-Klasse vergessen und die bar-Klasse stattdessen diese Strings enthalten? Denken Sie daran, dass Klassen auch ein integriertes Objekt sind, sie sind nur ein besonders flexibles Objekt.

Sobald wir unser Domänenmodell haben, können wir einige bestimmte Instanzen dieser Teile nehmen und sie in einer "Simulation" des bestimmten Systems anordnen, das wir modellieren möchten (z. B. "ein maschinelles Lernsystem für ...").

Sobald wir diese Simulation haben, können wir sie ausführen und hey presto, wir haben eine funktionierende (Simulation eines) maschinellen Lernsystems für ... (oder was auch immer wir modellieren).


In Ihrer speziellen Situation versuchen Sie nun, das Verhalten einer "Feature Extractor" -Komponente zu modellieren. Die Frage ist, ob es eingebaute Objekte gibt, die sich wie ein "Feature Extractor" verhalten, oder ob Sie es in einfachere Dinge aufteilen müssen. Es sieht so aus, als würden sich Feature-Extraktoren sehr ähnlich wie Funktionsobjekte verhalten. Ich denke, Sie können diese Objekte als Modell verwenden.


Beachten Sie beim Erlernen solcher Konzepte, dass verschiedene Sprachen unterschiedliche integrierte Funktionen und Objekte bereitstellen können (und einige verwenden natürlich nicht einmal eine Terminologie wie "Objekte"!). Daher sind Lösungen, die in einer Sprache sinnvoll sind, in einer anderen möglicherweise weniger nützlich (dies kann sogar für verschiedene Versionen derselben Sprache gelten!).

Historisch gesehen hat sich ein Großteil der OOP-Literatur (insbesondere "Design Patterns") auf Java konzentriert, was sich von Python stark unterscheidet. Beispielsweise sind Java-Klassen keine Objekte, Java hatte bis vor kurzem keine Funktionsobjekte, Java hat eine strenge Typprüfung (die Interfaces und Unterklassen fördert), während Python das Duck-Typing fördert, Java hat keine Modulobjekte, Java-Ganzzahlen / schwimmt / etc. sind keine Objekte, Meta-Programmierung / Introspektion in Java erfordert "Reflektion" und so weiter.

Ich versuche nicht, Java in Betracht zu ziehen (als weiteres Beispiel dreht sich eine Menge der OOP-Theorie um Smalltalk, das sich wiederum sehr von Python unterscheidet), sondern ich möchte nur darauf hinweisen, dass wir sehr sorgfältig über den Kontext und das Thema nachdenken müssen Einschränkungen, in denen Lösungen entwickelt wurden, und ob dies der Situation entspricht, in der wir uns befinden.

In Ihrem Fall scheint ein Funktionsobjekt eine gute Wahl zu sein. Wenn Sie sich fragen, warum in einer "Best Practice" -Richtlinie Funktionsobjekte nicht als mögliche Lösung erwähnt werden, liegt dies möglicherweise einfach daran, dass diese Richtlinien für ältere Versionen von Java geschrieben wurden!

Warbo
quelle
0

Pragmatisch ausgedrückt, wenn ich ein "Verschiedenes, das etwas Wichtiges tut und getrennt sein sollte", und es keine eindeutige Heimat hat, schreibe ich es in einen UtilitiesAbschnitt und verwende diesen als meine Namenskonvention. dh FeatureExtractionUtility.

Vergessen Sie die Anzahl der Methoden in einer Klasse. Eine einzelne Methode heute muss möglicherweise morgen auf fünf Methoden erweitert werden. Entscheidend ist eine klare und konsistente Organisationsstruktur, beispielsweise ein Versorgungsbereich für verschiedene Funktionssammlungen.

Dom
quelle