Ich versuche, die Architektur eines Systems zu entwerfen, das ich in C ++ implementieren werde, und ich habe mich gefragt, ob die Leute sich einen guten Ansatz vorstellen oder den Ansatz, den ich bisher entworfen habe, kritisieren könnten.
Das allgemeine Problem ist zunächst eine Bildverarbeitungspipeline. Es enthält mehrere Stufen, und das Ziel besteht darin, eine hochmodulare Lösung zu entwerfen, so dass jede der Stufen leicht ausgetauscht und durch einen benutzerdefinierten Code ersetzt werden kann (so dass der Benutzer eine Geschwindigkeitssteigerung erzielen kann, wenn er es weiß dass ein bestimmtes Stadium in seinem Problem auf eine bestimmte Weise eingeschränkt ist).
Das gegenwärtige Denken ist ungefähr so:
struct output; /*Contains the output values from the pipeline.*/
class input_routines{
public:
virtual foo stage1(...){...}
virtual bar stage2(...){...}
virtual qux stage3(...){...}
...
}
output pipeline(input_routines stages);
Dies würde es den Leuten ermöglichen, input_routines zu unterklassifizieren und die gewünschte Stufe zu überschreiben. Das heißt, ich habe schon in solchen Systemen gearbeitet, und ich finde, dass die Unterklassen und die Standardmaterialien dazu neigen, chaotisch zu werden, und dass es schwierig sein kann, sie zu verwenden, so dass ich nicht schwindlig bin, selbst eines zu schreiben. Ich habe auch über einen STLish-Ansatz nachgedacht, bei dem die verschiedenen Stufen (es gibt 6 oder 7) standardmäßige Vorlagenparameter sind.
Kann jemand eine Kritik des obigen Musters, Gedanken zum Vorlagenansatz oder zu einer anderen Architektur abgeben, die ihm in den Sinn kommt?
quelle
Antworten:
Das Design hängt stark davon ab, was die verschiedenen Phasen tatsächlich tun. Ich bevorzuge meistens reine virtuelle Funktionen gegenüber nicht reinen virtuellen Funktionen (abstrakte Klassen).
Gemeinsame Stufen können in abstrakten Unterklassen zusammengefasst werden. Durch Ableiten von der abstrakten Hauptklasse können Sie immer noch jede Stufe anpassen, aber durch Ableiten von einer Unterklasse können Sie vorhandenes Verhalten wiederverwenden, das bereits geschrieben wurde. Es ist in der Regel weniger chaotisch, wie Sie für virtuelle Methoden erwähnen.
Wenn die verschiedenen Phasen auch für sich alleine existieren können (außerhalb der gesamten Pipeline), sollten Sie auch Klassen schreiben, um dieses Verhalten zu trennen.
quelle
Erstellen Sie möglicherweise eine Liste von Funktoren in einer Fabrik, die die Stufen implementieren. Pseudocode:
Benutzer können die Fabrik neu implementieren oder einfach die Liste der Funktoren bearbeiten. Pseudocode
oder
Wenn das Setup abgeschlossen ist, können Sie jeden Funktor mit dem Ergebnis des letzten aufrufen.
quelle
Werfen Sie einen Blick auf die in Haskell implementierten Monaden, die Ihnen möglicherweise eine gute Vorstellung davon geben, wie Sie die Dinge einrichten. Haskell macht so etwas wirklich richtig.
quelle
Ich würde einen Zwischentyp definieren. Alle Bilder würden in dieses Format konvertiert. Jede Stufe würde ein Intermediate nehmen und ein Intermediate zurückgeben - nicht dasselbe, ein neues.
Eine Bühne wäre dies:
Intermediate DoSomething(const Intermediate &i);
Normalerweise vermeide ich vererbungsbasierte Lösungen im Allgemeinen, es sei denn, sie sind eine ziemlich offensichtliche Abbildung auf das Problem, z. B. Objekte in einer 3D-Welt.
quelle