Sind Klassen mit nur einer (öffentlichen) Methode ein Problem?


51

Ich arbeite derzeit an einem Softwareprojekt, das die Komprimierung und Indizierung von Videoüberwachungsmaterial durchführt. Bei der Komprimierung werden Hintergrund- und Vordergrundobjekte geteilt und der Hintergrund als statisches Bild und der Vordergrund als Sprite gespeichert.

Vor kurzem habe ich begonnen, einige der von mir für das Projekt entworfenen Klassen zu wiederholen.

Mir ist aufgefallen, dass es viele Klassen gibt, die nur eine einzige öffentliche Methode haben. Einige dieser Klassen sind:

  • VideoCompressor (mit einer compressMethode, die ein Eingabevideo vom Typ aufnimmt RawVideound ein Ausgabevideo vom Typ zurückgibt CompressedVideo).
  • VideoSplitter (mit einer splitMethode, die ein Eingabevideo vom Typ aufnimmt RawVideound einen Vektor mit 2 Ausgabevideos vom Typ zurückgibt RawVideo).
  • VideoIndexer (mit einer indexMethode, die ein Eingabevideo vom Typ aufnimmt und einen Videoindex vom Typ RawVideozurückgibt VideoIndex).

Ich finde ich jede Klasse Instanziierung nur zu telefonieren wie VideoCompressor.compress(...), VideoSplitter.split(...), VideoIndexer.index(...).

An der Oberfläche denke ich, dass die Klassennamen ausreichend beschreibend für ihre beabsichtigte Funktion sind und es sich tatsächlich um Substantive handelt. Entsprechend sind ihre Methoden auch Verben.

Ist das eigentlich ein Problem?


14
Das hängt von der Sprache ab. In einer Multi-Paradigma-Sprache wie C ++ oder Python gibt es für diese Klassen kein Geschäft: Ihre "Methoden" sollten freie Funktionen sein.

3
@delnan: Selbst in C ++ verwenden Sie normalerweise Klassen zum Erstellen von Modulen, auch wenn Sie nicht die vollständigen "OO-Funktionen" benötigen. Es gibt zwar die Alternative, Namespaces zu verwenden, um "freie Funktionen" zu einem Modul zusammenzufassen, aber ich sehe darin keine Vorteile.
Doc Brown

5
@DocBrown: C ++ hat dafür Namespaces. Tatsächlich verwenden Sie in modernem C ++ häufig freie Funktionen für Methoden, da diese für alle Argumente (statisch) überladen werden können, während Methoden nur für den Aufrufer überladen werden können.
Jan Hudec

2
@ DocBrown: Es ist ein Kern der Frage. Module, die Namespaces mit nur einer "externen" Methode verwenden, sind in Ordnung, wenn die Funktion ausreichend komplex ist. Denn Namespaces geben nicht vor, etwas darzustellen, und geben nicht vor, objektorientiert zu sein. Klassen tun das, aber Klassen wie diese sind eigentlich nur Namespaces. Natürlich kann man in Java keine Funktion haben, daher ist dies das Ergebnis. Schande über Java.
Jan Hudec

2
Verwandte (fast ein Duplikat): programmers.stackexchange.com/q/175070/33843
Heinzi

Antworten:


87

Nein, das ist kein Problem, ganz im Gegenteil. Es ist ein Zeichen der Modularität und der klaren Verantwortung der Klasse. Die schlanke Oberfläche ist aus Sicht eines Benutzers dieser Klasse leicht zu erfassen und fördert die lose Kopplung. Dies hat viele Vorteile, aber fast keine Nachteile. Ich wünschte, mehr Komponenten würden so entworfen!


6
Dies ist die richtige Antwort, und ich habe sie positiv bewertet, aber Sie können sie verbessern, indem Sie einige der Vorteile erläutern. Ich denke, was der Instinkt des OP ihm sagt, dass es ein Problem ist, ist etwas anderes ... das heißt, dass VideoCompressor wirklich eine Schnittstelle ist. Mp4VideoCompressor ist eine Klasse und sollte mit einem anderen VideoCompressor austauschbar sein, ohne den Code für einen VideoSplitter in eine neue Klasse zu kopieren.
pdr

1
Entschuldigung, aber du liegst falsch. Eine Klasse mit einer einzelnen Methode sollte nur eine eigenständige Funktion sein.
Miles Rout

3
@MilesRout: Ihr Kommentar zeigt, dass Sie die Frage falsch verstanden haben - das OP schrieb über eine Klasse mit einer öffentlichen Methode, nicht mit einer Methode (und er meinte tatsächlich eine Klasse mit mehreren privaten Methoden, wie er uns hier in einem Kommentar sagte).
Doc Brown

2
"Eine Klasse mit einer einzelnen Methode sollte nur eine eigenständige Funktion sein." Eine grobe Annahme darüber, was diese Methode ist. Ich habe eine Klasse mit einer öffentlichen Methode. HINTER ES gibt mehrere Methoden in dieser Klasse plus 5 andere Klassen, die absolut keine Ahnung vom Client haben. Eine ausgezeichnete Anwendung von SRP ergibt eine saubere, einfache Schnittstelle der geschichteten Klassenstruktur, wobei sich diese Einfachheit bis ganz nach oben manifestiert.
Radarbob

2
@Andy: Die Frage lautete "Ist das ein Problem?" Und nicht "Entspricht dies einer bestimmten OO-Definition?". Darüber hinaus gibt es in der Frage, dass das OP Klassen ohne Staat bedeutet, keinerlei Anzeichen.
Doc Brown

26

Es ist nicht mehr objektorientiert. Da diese Klassen nichts darstellen, sind sie nur Gefäße für die Funktionen.

Das heißt nicht, dass es falsch ist. Wenn die Funktionalität ausreichend komplex oder generisch ist (dh die Argumente sind Schnittstellen, keine konkreten Endtypen), ist es sinnvoll, diese Funktionalität in einem separaten Modul abzulegen .

Von dort hängt es von Ihrer Sprache ab. Wenn die Sprache freie Funktionen hat, sollten dies Module sein, die Funktionen exportieren. Warum so tun, als wäre es eine Klasse, wenn dies nicht der Fall ist? Wenn die Sprache keine freien Funktionen wie z. B. Java hat, erstellen Sie Klassen mit einer einzelnen öffentlichen Methode. Nun, das zeigt nur die Grenzen des objektorientierten Designs. Manchmal passt funktional einfach besser zusammen.

Es gibt einen Fall, in dem Sie möglicherweise eine Klasse mit einer einzelnen öffentlichen Methode benötigen, da die Schnittstelle mit einer einzelnen öffentlichen Methode implementiert werden muss. Sei es für Beobachtermuster oder Abhängigkeitsinjektion oder was auch immer. Hier kommt es wieder auf die Sprache an. In Sprachen mit erstklassigen Funktoren (C ++ ( std::functionoder Vorlagenparameter), C # (Delegat), Python, Perl, Ruby ( proc), Lisp, Haskell, ...) verwenden diese Muster Funktionstypen und benötigen keine Klassen. Java hat (noch) keine Funktionstypen, daher verwenden Sie einzelne Methodenschnittstellen und entsprechende einzelne Methodenklassen.

Natürlich befürworte ich nicht das Schreiben einer einzigen großen Funktion. Es sollte über private Subroutinen verfügen, diese können jedoch für die Implementierungsdatei (statischer oder anonymer Namespace auf Dateiebene in C ++) oder für eine private Hilfsklasse privat sein, die nur innerhalb der öffentlichen Funktion instanziiert wird ( Daten speichern oder nicht? ).


12
"Warum so tun, als wäre es eine Klasse, wenn es nicht so ist." Das Vorhandensein eines Objekts anstelle einer freien Funktion ermöglicht Status und Untertypen. Das könnte sich in einer Welt, in der sich die Anforderungen ändern, als wertvoll erweisen. Früher oder später müssen Einstellungen für die Videokomprimierung vorgenommen oder alternative Komprimierungsalgorithmen bereitgestellt werden. Vorher sagt uns das Wort "Klasse" lediglich, dass diese Funktion zu einem leicht erweiterbaren und austauschbaren Softwaremodul mit einer klaren Verantwortung gehört. Ist es nicht das, was OO wirklich anstrebt?
KOMMEN SIE VOM

1
Nun, wenn es nur eine öffentliche Methode gibt (und keine geschützten impliziert), kann sie nicht wirklich erweitert werden. Natürlich können Komprimierungsparameter für das Packen sinnvoll sein. In diesem Fall wird es zum Funktionsobjekt (einige Sprachen unterstützen diese separat, andere nicht).
Jan Hudec

3
Dies ist eine grundlegende Verbindung zwischen Objekten und Funktionen: Eine Funktion ist isomorph zu einem Objekt mit einer einzigen Methode und ohne Felder. Ein Abschluss ist isomorph zu einem Objekt mit einer einzelnen Methode und einigen Feldern. Eine Selektorfunktion, die eine von mehreren Funktionen zurückgibt, die sich alle über denselben Variablensatz schließen, ist isomorph zu einem Objekt. (Auf diese Weise werden Objekte in JavaScript codiert, außer dass Sie eine Wörterbuchdatenstruktur anstelle einer Auswahlfunktion verwenden.)
Jörg W Mittag

4
"Es ist nicht mehr objektorientiert. Da diese Klassen nichts darstellen, sind sie nur Gefäße für die Funktionen." - Das ist falsch. Ich würde argumentieren, dass dieser Ansatz MEHR objektorientiert ist. OO bedeutet nicht, dass es sich um ein reales Objekt handelt. Ein Großteil der Programmierung befasst sich mit abstrakten Konzepten. Bedeutet dies, dass Sie keinen OO-Ansatz anwenden können, um diese zu lösen? Definitiv nicht. Es geht mehr um Modularität und Abstraktion. Jedes Objekt hat eine einzelne Verantwortung. Auf diese Weise können Sie sich ganz einfach mit dem Programm beschäftigen und Änderungen vornehmen. Nicht genügend Speicherplatz, um die zahlreichen Vorteile von OOP aufzulisten.
Despertar

2
@Phoshi: Ja, ich verstehe. Ich habe nie behauptet, dass ein funktionaler Ansatz nicht so gut funktionieren würde. Dies ist jedoch eindeutig nicht das Thema. Ein Videokomprimierer oder ein Videotransmogrifizierer oder was auch immer ist immer noch ein perfekter Kandidat für ein Objekt.
KOMMEN SIE VOM

13

Es kann Gründe geben, eine bestimmte Methode in eine dedizierte Klasse zu extrahieren. Einer dieser Gründe ist das Zulassen der Abhängigkeitsinjektion.

Stellen Sie sich vor, Sie haben eine Klasse, VideoExporterdie ein Video komprimieren kann. Ein sauberer Weg wäre, eine Schnittstelle zu haben:

interface IVideoCompressor
{
    Stream compress(Video video);
}

was so implementiert werden würde:

class MpegVideoCompressor : IVideoCompressor
{
    // ...
}

class FlashVideoCompressor : IVideoCompressor
{
    // ...
}

und so benutzt:

class VideoExporter
{
    // ...
    void export(Destination destination, IVideoCompressor compressor)
    {
        // ...
        destination = compressor(this.source);
        // ...
    }
    // ...
}

Eine schlechte Alternative wäre eine, VideoExporterdie viele öffentliche Methoden hat und alle Aufgaben erledigt, einschließlich des Komprimierens. Es würde schnell zu einem Wartungs-Albtraum werden, was es schwierig macht, Unterstützung für andere Videoformate hinzuzufügen.


2
Ihre Antwort unterscheidet nicht zwischen öffentlichen und privaten Methoden. Es könnte als Empfehlung verstanden werden, den gesamten Code einer Klasse auf eine einzige Methode zu beschränken, aber ich denke, das ist nicht das, was Sie gemeint haben?
Doc Brown

2
@DocBrown: Private Methoden sind für diese Frage nicht relevant. Sie können in die interne Helferklasse oder was auch immer eingewiesen werden.
Jan Hudec

2
@JanHudec: Derzeit lautet der Text "Eine schlechte Alternative wäre ein VideoExporter mit vielen Methoden" - aber es sollte "Eine schlechte Alternative wäre ein VideoExporter mit vielen öffentlichen Methoden" sein.
Doc Brown

@ DocBrown: Hier zustimmen.
Jan Hudec

2
@ DocBrown: Vielen Dank für Ihre Bemerkungen. Ich habe meine Antwort bearbeitet. Ursprünglich dachte ich, dass davon ausgegangen wurde, dass es sich bei der Frage (und damit meiner Antwort) nur um öffentliche Methoden handelt. Es scheint, dass es nicht so offensichtlich ist.
Arseni Mourzenko

6

Dies ist ein Zeichen dafür, dass Sie Funktionen als Argumente an andere Funktionen übergeben möchten. Ich vermute, dass Ihre Sprache (Java?) Dies nicht unterstützt. Wenn dies der Fall ist, liegt dies weniger an Ihrem Design als vielmehr an der Sprache Ihrer Wahl. Dies ist eines der größten Probleme bei Sprachen, die darauf bestehen, dass alles eine Klasse sein muss.

Wenn Sie diese Faux-Funktionen nicht wirklich weitergeben, möchten Sie nur eine freie / statische Funktion.


1
Seit Java 8 haben Sie Lambdas, so dass Sie praktisch Funktionen übergeben können.
Silviu Burcea

Fair point, aber das wird nicht für eine Weile länger offiziell veröffentlicht, und einige Arbeitsplätze sind langsam zu neueren Versionen zu bewegen.
Doval

Erscheinungsdatum ist im März. Außerdem waren EAP-Builds für JDK 8 sehr beliebt :)
Silviu Burcea

Da Java 8-Lambdas lediglich eine Abkürzung für die Definition von Objekten mit nur einer öffentlichen Methode sind, machen sie hier jedoch keinen Unterschied.
Jules

5

Ich weiß, dass ich zu spät zur Party komme, aber wie jeder scheint es versäumt zu haben, darauf hinzuweisen:

Dies ist ein bekanntes Entwurfsmuster mit dem Namen: Strategy Pattern .

Ein Strategiemuster wird verwendet, wenn es mehrere mögliche Strategien zur Lösung eines Unterproblems gibt. In der Regel definieren Sie eine Schnittstelle, die einen Vertrag für alle Implementierungen erzwingt, und verwenden dann eine Form der Abhängigkeitsinjektion , um die konkrete Strategie für Sie bereitzustellen.

Zum Beispiel in diesem Fall könnten Sie haben interface VideoCompressorund haben dann mehrere alternative Implementierungen zum Beispiel class H264Compressor implements VideoCompressorund class XVidCompressor implements VideoCompressor. Aus dem OP geht nicht hervor, dass es sich um eine Schnittstelle handelt, auch wenn dies nicht der Fall ist. Es kann einfach sein, dass der ursprüngliche Autor die Tür offen gelassen hat, um bei Bedarf ein Strategiemuster zu implementieren. Was an und für sich auch gutes Design ist.

Das Problem, dass OP ständig die Klassen instanziiert, um eine Methode aufzurufen, besteht darin, dass sie die Abhängigkeitsinjektion und das Strategiemuster nicht korrekt verwendet. Anstatt es dort zu instanziieren, wo Sie es benötigen, sollte die übergeordnete Klasse ein Mitglied mit dem Strategieobjekt haben. Und dieses Mitglied sollte zum Beispiel in den Konstruktor injiziert werden.

In vielen Fällen führt das Strategiemuster zu Schnittstellenklassen (wie Sie zeigen) mit nur einer einzigen doStuff(...)Methode.


1
public interface IVideoProcessor
{
   void Split();

   void Compress();

   void Index();
}

Was Sie haben, ist modular und das ist gut, aber wenn Sie diese Verantwortlichkeiten in IVideoProcessor gruppieren würden, wäre dies aus DDD-Sicht wahrscheinlich sinnvoller.

Andererseits, wenn Teilen, Komprimieren und Indizieren in keiner Weise zusammenhängen, dann würde ich sie als separate Komponenten behalten.


Da der Grund für jede dieser Funktionen, die geändert werden müssen, ein anderer ist, würde ich argumentieren, dass eine solche Zusammenstellung die SRP verletzt.
Jules

0

Es ist ein Problem - Sie arbeiten eher vom funktionalen Aspekt des Designs als von den Daten. Was Sie tatsächlich haben, sind 3 eigenständige Funktionen, die OO-geprüft wurden.

Sie haben beispielsweise eine VideoCompressor-Klasse. Warum arbeiten Sie mit einer Klasse zum Komprimieren von Videos? Warum gibt es keine Videoklasse mit Methoden zum Komprimieren der (Video-) Daten, die jedes Objekt dieses Typs enthält?

Beim Entwerfen von OO-Systemen empfiehlt es sich, Klassen zu erstellen, die Objekte darstellen, anstatt Klassen, die Aktivitäten darstellen, die Sie anwenden können. Früher wurden Klassen als Typen bezeichnet - OO war eine Möglichkeit, eine Sprache mit Unterstützung für neue Datentypen zu erweitern. Wenn Sie an OO so denken, erhalten Sie eine bessere Möglichkeit, Ihre Klassen zu entwerfen.

BEARBEITEN:

Lassen Sie mich versuchen, mich ein wenig besser zu erklären. Stellen Sie sich eine String-Klasse mit einer concat-Methode vor. Sie können so etwas implementieren, bei dem jedes aus der Klasse instanziierte Objekt die Zeichenfolgendaten enthält

string mystring("Hello"); 
mystring.concat("World");

aber das OP möchte, dass es so funktioniert:

string mystring();
string result = mystring.concat("Hello", "World");

Jetzt gibt es Orte, an denen eine Klasse verwendet werden kann, um eine Sammlung verwandter Funktionen zu speichern. Dies ist jedoch kein OO. Es ist eine praktische Möglichkeit, die OO-Funktionen einer Sprache zu verwenden, um die Codebasis besser zu verwalten von "OO Design". Das Objekt ist in solchen Fällen völlig künstlich und wird einfach so verwendet, weil die Sprache nichts Besseres bietet, um diese Art von Problem zu lösen. z.B. In Sprachen wie C # würden Sie eine statische Klasse verwenden, um diese Funktionalität bereitzustellen - der Klassenmechanismus wird wiederverwendet, Sie müssen jedoch kein Objekt mehr instanziieren, nur um die Methoden dafür aufzurufen. Am Ende haben Sie Methoden wie string.IsNullOrEmpty(mystring)die, die ich für schlecht halte mystring.isNullOrEmpty().

Wenn also jemand fragt, wie ich meine Klassen entwerfe, empfehle ich, an die Daten zu denken, die die Klasse enthalten wird, anstatt an die Funktionen, die sie enthält. Wenn Sie sich für "eine Klasse ist ein Bündel von Methoden" entscheiden, schreiben Sie am Ende einen Code im "besseren C" -Stil. (was nicht unbedingt eine schlechte Sache ist, wenn Sie C-Code verbessern), aber es wird Ihnen nicht das beste von OO entworfene Programm geben.


9
-1, ich bin völlig anderer Meinung. Anfänger OO-Design funktioniert nur mit Datenobjekten wie a Videound neigt dazu, solche Klassen mit Funktionalität zu überschwemmen, was häufig in unordentlichem Code mit> 10 KB LOC pro Klasse endet. Das erweiterte OO-Design unterteilt die Funktionalität in kleinere Einheiten wie a VideoCompressor(und lässt eine VideoKlasse nur eine Datenklasse oder eine Fassade für das sein VideoCompressor).
Doc Brown

5
@DocBrown: Ab diesem Zeitpunkt handelt es sich jedoch nicht mehr um ein objektorientiertes Design, da das VideoCompressorkein Objekt darstellt . Daran ist nichts auszusetzen, es zeigt nur die Grenze des objektorientierten Designs.
Jan Hudec

3
Ah, aber Anfänger OO, bei denen eine Funktion in eine Klasse umgewandelt wird, sind nicht wirklich OO und fördern nur die massive Entkopplung, die zu tausend Dateien mit Klassen führt, die niemand verwalten kann. Ich denke, es ist am besten, sich eine Klasse als "Daten-Wrapper" und nicht als "Funktions-Wrapper" vorzustellen, um Anfängern ein besseres Verständnis für das Denken über OO-Programme zu vermitteln.
gbjbaanb

4
@ DocBrown tatsächlich genau mein Anliegen hervorgehoben; Ich habe zwar eine VideoKlasse, aber die Komprimierungsmethode ist keineswegs trivial, sodass ich die compressMethode tatsächlich in mehrere andere private Methoden aufteilen würde. Dies ist ein Teil des Grundes meiner Frage, nachdem ich " Don't create verb classes"
yjwong

2
Ich denke, es wäre in Ordnung, eine VideoKlasse zu haben , aber es würde sich aus einer VideoCompressor, einer VideoSplitterund anderen verwandten Klassen zusammensetzen, die in guter OO-Form sehr zusammenhängende Einzelklassen sein sollten.
Eric King

-1

Nach dem ISP- Prinzip (Interface Segregation) sollte kein Client gezwungen werden, sich auf Methoden zu verlassen, die er nicht verwendet. Die Vorteile sind vielfältig und klar. Ihr Ansatz respektiert den ISP voll und ganz, und das ist gut so.

Ein anderer Ansatz, der auch den ISP berücksichtigt, besteht beispielsweise darin, eine Schnittstelle für jede Methode (oder einen Satz von Methoden mit hoher Kohäsion) zu erstellen und dann eine einzige Klasse zu haben, die alle diese Schnittstellen implementiert. Ob dies eine bessere Lösung ist oder nicht, hängt vom Szenario ab. Dies hat den Vorteil, dass bei Verwendung der Abhängigkeitsinjektion möglicherweise ein Client mit verschiedenen Mitarbeitern (einer pro Schnittstelle) vorhanden ist. Letztendlich verweisen jedoch alle Mitarbeiter auf dieselbe Objektinstanz.

Übrigens hast du gesagt

Ich stelle fest, dass ich jede Klasse instanziiere

scheinen diese Klassen Dienste (und damit staatenlos) zu sein. Hast du darüber nachgedacht, sie zu Singletons zu machen?



3
Im Übrigen ist das Prinzip der Schnittstellentrennung zwar ein gutes Muster, bei dieser Frage geht es jedoch um die Implementierungen und nicht um die Schnittstellen. Daher bin ich mir nicht sicher, ob dies relevant ist.
Jan Hudec

3
Ich werde nicht eintreten, um zu diskutieren, ob der Singleton ein Muster oder ein Gegenmuster ist. Ich schlug eine mögliche Lösung für das Problem vor (es hat sogar einen Namen). Es liegt an ihm, zu entscheiden, ob es passt oder nicht.
Diegomtassis

In Bezug darauf, ob der ISP relevant ist oder nicht, lautet das Thema der Frage "Sind Klassen mit nur einer Methode ein Problem?", Das Gegenteil davon ist eine Klasse mit vielen Methoden, die zum Problem wird, sobald Sie eine erstellen Kunden hängen direkt davon ab ... genau das Xerox-Beispiel von Robert Martin, mit dem er den ISP formuliert hat.
Diegomtassis

-1

Ja, da ist ein Problem. Aber nicht schwerwiegend. Ich meine, Sie können Ihren Code so strukturieren und nichts Schlimmes wird passieren, er ist wartbar. Diese Strukturierung weist jedoch einige Schwächen auf. Überlegen Sie beispielsweise, ob sich die Darstellung Ihres Videos (in Ihrem Fall in der RawVideo-Klasse gruppiert) ändert, und aktualisieren Sie alle Ihre Operationsklassen. Oder denken Sie daran, dass Sie möglicherweise mehrere Darstellungen von Videos haben, die sich in der Laufzeit unterscheiden. Dann müssen Sie die Darstellung einer bestimmten "Operations" -Klasse zuordnen. Auch subjektiv ist es ärgerlich, für jede Operation, die Sie mit smth ausführen möchten, eine Abhängigkeit zu ziehen. und um die Liste der Abhängigkeiten zu aktualisieren, die jedes Mal übergeben werden, wenn Sie entscheiden, dass die Operation nicht mehr benötigt wird oder wenn Sie eine neue Operation benötigen.

Auch das ist eigentlich eine Verletzung von SRP. Einige Leute behandeln SRP lediglich als Leitfaden für die Aufteilung von Verantwortlichkeiten (und gehen zu weit, indem sie jedem Vorgang eine eigene Verantwortung zuweisen), vergessen jedoch, dass SRP auch ein Leitfaden für die Gruppierung von Verantwortlichkeiten ist. Und gemäß SRP sollten Verantwortlichkeiten, die sich aus dem gleichen Grund ändern, zusammengefasst werden, damit sie sich bei Änderungen auf so wenige Klassen / Module wie möglich beschränken. Für große Klassen ist es kein Problem, mehrere Algorithmen in derselben Klasse zu haben, solange diese Algorithmen miteinander verwandt sind (dh Wissen teilen, das außerhalb dieser Klasse nicht bekannt sein sollte). Das Problem sind große Klassen mit Algorithmen, die in keiner Weise zusammenhängen und sich aus verschiedenen Gründen ändern / variieren.

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.