Bei dieser Frage geht es darum, ein Programm so zu gestalten, dass bestimmte Änderungen leicht vorgenommen werden können.
Ich habe eine Klasse, die einige (nicht-triviale) Daten enthält und mehrere Mitgliedsfunktionen hat, die diese Daten ändern.
Manchmal muss ich eine Eigenschaft dieser Daten berechnen. Aber es ist langsam, es bei jeder Änderung von Grund auf neu zu berechnen. Es ist viel schneller, stattdessen ein kleines Update für diese Eigenschaften zu berechnen.
Ich habe mehrere solcher Eigenschaften, die ich leicht zu meiner Klasse hinzufügen oder von ihr entfernen (oder ein- / ausschalten) kann, um einige numerische Experimente durchzuführen. Die Klasse wird nur von mir selbst modifiziert und für numerische Simulationen (wissenschaftlicher Code) verwendet.
Nehmen wir an, ich habe eine Klasse, die eine Zahl x
enthält. Aber ich brauche auch 2^x
(eine "Eigenschaft" von x
). Die grundlegende Klasse ist:
Aber jetzt muss ich 2^x
im Auge behalten und diesen Wert jedes Mal aktualisieren, wenn sich x
ändert. Also habe ich am Ende
XX
markiert Änderungen, die ich an der Klasse C
vornehmen musste. Das sind viele Änderungen, die fehleranfällig sind. Es wird noch komplizierter mit mehreren Eigenschaften, die sogar voneinander abhängen.
Frage: Was ist ein gutes Design für ein solches Programm? Ich bin sicher, dass es möglich ist, besser als das oben genannte zu machen. Die Ziele sind: 1) Machen Sie es einfach, solche Eigenschaften hinzuzufügen / zu entfernen, oder schalten Sie ihre Berechnungen ein oder aus. 2) Leistung ist entscheidend. inc
und dec
werden in engen inneren Schleifen aufgerufen und tun relativ wenig. Sie können aus Leistungsgründen nicht virtuell gemacht werden.
In Wirklichkeit ist x
eine komplexere Datenstruktur. Denke z.B. Hinzufügen / Entfernen von Kanten zu / von einem Diagramm und Verfolgen der Gradreihenfolge während des Prozesses.
Aktualisieren
@ tobi303 hat gefragt, dass ich zeige, wie diese Klasse verwendet wird. Es ist in ähnlicher Weise wie folgt:
%Vor%Oder in Worten:
Es ist tatsächlich eine Monte-Carlo-Simulation ähnlich einem Metropolis-Hasting-Algorithmus .
Ein konkretes Beispiel könnte sein, dass die "Daten" in der Klasse C
(state) der Spin-Zustand eines Ising-Modells
Just sei faul und berechne die Eigenschaften nicht, wenn du es brauchst zu. Es wird viel Code und unnötige Berechnungen entfernen.
Wenn Ihre Eigenschaft benötigt, berechnen Sie sie, wenn sie nicht bereits im Cache ist. Daher benötigen Sie für jede Eigenschaft einen booleschen Wert, um festzustellen, ob der Cache aktuell ist, und Sie müssen die booleans jedes Mal ungültig machen, wenn x
selbst aktualisiert wird.
Grundsätzlich:
%Vor% Edit: Eine even lazier -Lösung soll anstatt einen Booleschen Wert in cache
zu speichern, eine Ganzzahl speichern, die der letzten Aktualisierung entspricht, und einen Zähler in C
beibehalten. Jedes Mal, wenn der Cache ungültig gemacht wird, wird der Zähler in C
erhöht. Wenn propX
abgerufen wird und der Zähler nicht mit propX.lastUpdate
übereinstimmt, aktualisieren Sie 'propX.
Auf diese Weise ist das Ungültigmachen des Caches nur eine Operation und muss nicht den gesamten Cache der Eigenschaften aktualisieren.
Hier ist ein Ansatz, der für Sie funktionieren könnte:
%Vor% Wenn Sie eine neue Eigenschaft hinzufügen, müssen Sie nur einen Aufruf in for_each_property()
hinzufügen. Die Verwendung von Variadics vermeidet die Notwendigkeit, neue Überladungen für verschiedene Parameter bereitzustellen, solange Sie sich an die gleiche Formel halten.
Dies beseitigt die Duplizierung im Konstruktor nicht, es sei denn, Sie sind bereit, zu einer Standardinitialisierung der Eigenschaften überzugehen und dann set(0.0)
aufzurufen.
Tags und Links c++