diff --git a/wiki/renderengine.html b/wiki/renderengine.html index ea8b4047d..0f4b4b38b 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -2177,12 +2177,32 @@ Similar to an Asset, an identification tuple is available (generated on the fly) → MetaAsset -
-
//The global ''Event Log'' records the fact that something ''has happened'' as result from a command or instruction.//
-The EventLog is a central element of the ''CQRS'' architecture model.
+
+
//~Command-and-Query-Responsibility-Separation (CQRS) describes an asynchronous architecture without a central data model.//
+In this arrangement of components, the old guideline to separate the processing of queries and mutations is applied to the relation of interfaces and functional clusters within the system. The chain of //business logic// processing is completely segregated from the date models and is organised essentially as a pipeline, where desired operations are instructed as //commands//. Each command is validated, and then performed within a conditioned environment, which is isolated from the persistent data in the system. The effect of a command execution is then propagated and distributed to various //»projections«// to produce the actual persistent mutation of the data in the system. On the other hand, any interface to query the state and the data content is provided by services altogether unrelated to any //processing// in the system.
+
+An architecture based on CQRS can be challenging to build properly, because any //effect// has to be //represented// instead of //just happening//. Yet this architecture style is known to offer several unique benefits:
+* processing is guaranteed to be side-effect free
+* it is easy to define and verify well-defined behaviour for each command
+* it is possible to maintain several, specialised projections which focus on specific aspects of the effect
+* the data model within some query-oriented service is an implementation detail and can be modified at will, as long as the defined effect is retained.
+
+CQRS is typically combined with EventSourcing to represent the effects of processing as a sequence of //events// in an EventLog
+
-
-
//''Event Sourcing'' is an Architecture pattern and used together with ''CQRS''.//
+
+
//The global ''Event Log'' records the fact that something ''has happened'' as result from a command or instruction.//
+The EventLog is a central element of the [[CQRS|EventCQRS]] architecture model.
+After some //event has been recorded,// it is propagated to the »projections«, which are listeners to the event log and may mutate their internal state in response to some event. Notably a data model is attached as a projection, and thus the complete content of such a data model can be seen as a materialisation of the event sequence. The entire state of the data in the model can any time be reproduced by //re-playing// the entire event log to a clean slate.
+
+!Structure of Events
+First and foremost, each event must be well defined and can be addressed by an unique identifier (hash based). Furthermore, each event is marked with a specification version -- and the implementation of the the expected effects of a given version is never changed. This allows the system to evolve while in use: improved implementations of some event can coexist with earlier versions of the same event in the same log.
+
+Events serve as foundation to allow corrections and revisions of the history of events: any event can be un-done, by replaying the event log without the event in question. In practice however this requirement can be difficult to uphold, since it might lead to a proliferation of complicated events. It is thus desirable to introduce //transactions// -- defined as a group of events which are considered to happen in compound. Each such group or transactional compound of events is considered itself an event. Notably the processing of some //command// might produce several events, some of which are generated automatically to reflect effects of this command based on the current state of data, rules and configuration. As an example, if the execution of business logic needs to query fro some default, this processing of a rule query might generate a //binding//, which also becomes part of the next state and thus need to be represented as a further event within that command's transactional event group.
+
+
+
+
//''Event Sourcing'' is an Architecture pattern and used together with [[CQRS|EventCQRS]].//
 Over the course of the years, it gradually became clear that the goals defined regarding consistency and fine-grained control of the arrangement in the session seem to converge towards an architecture based on these principles
 
 !Difficulties and Contradictions
diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm
index 9e8f2bf8b..6147644af 100644
--- a/wiki/thinkPad.ichthyo.mm
+++ b/wiki/thinkPad.ichthyo.mm
@@ -72073,6 +72073,16 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
 
 
 
@@ -75112,6 +75122,70 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  
+  
+    

+ Naiverweise dachte ich zunächst, daß da eine direkte Verbindung zum Eventlog besteht. Das widerspricht aber der Idee einer Projektion +

+ +
+
+ + + + +
+
+ + +
+
@@ -75150,7 +75224,7 @@ - + @@ -75163,6 +75237,7 @@ + @@ -75214,7 +75289,7 @@

- ...indem nämlich eine Regel oder Entscheidungsbasis gesperrt  wird, sobald sie einmal zur Anwendung gekommen ist; so ein Mechanismus ließe sich mit relativ geringem Aufwand realisieren, und würde zumindest stets ermöglichen, daß man das Entstehen eines Konflikts erkennt und dann warnt. Dies wäre sozusagen die »optimistische« Herangehensweise: meist geht ja alles gut.... + ...indem nämlich eine Regel oder Entscheidungsbasis gesperrt wird, sobald sie einmal zur Anwendung gekommen ist; so ein Mechanismus ließe sich mit relativ geringem Aufwand realisieren, und würde zumindest stets ermöglichen, daß man das Entstehen eines Konflikts erkennt und dann warnt. Dies wäre sozusagen die »optimistische« Herangehensweise: meist geht ja alles gut....

@@ -75703,6 +75778,7 @@
+ @@ -75727,6 +75803,24 @@ + + + + + + + + + + + + + + + + + + @@ -76130,11 +76224,18 @@ - + + + + + + + + @@ -76262,6 +76363,7 @@ + @@ -110101,9 +110203,10 @@ StM_bind(Builder<R1> b1, Extension<R1,R2> extension) - + + @@ -159947,8 +160050,7 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo Es wird also definitiv nicht »der Clip« den Code enthalten, wie er sich selber rendert, oder »der Track« den Code enhalten, mit dem Medien-Inhalte kombiniert und verarbeitet werden.

- - +
@@ -160047,8 +160149,7 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo Ort der Entscheidungs-Logik

- -
+ @@ -160058,8 +160159,7 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo der Code macht was — und man weiß darum

- -
+
@@ -160069,8 +160169,7 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo Trennung in Business-Kern, Framework und Library

- -
+
@@ -160081,8 +160180,7 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo Code ist faktorisiert in getrennte Sachverhalte

- - +
@@ -160092,8 +160190,7 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo Code führt aus, delegiert, stellt sicher

- -
+ @@ -160101,8 +160198,7 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo Solchen Code sieht man mit gemischten Gefühlen — er ist nicht das, was man gesucht hat, aber er legt einem nahe, ihn zu ignorieren, ohne zu verstehen was er tut

- -
+
@@ -160126,8 +160222,7 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo - - + @@ -160137,8 +160232,7 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo In solchem Code findet man typischerweise nur eine endlose Folge von Abgrenzungen, die Verhalten unterdrücken, ablenken oder transformieren; das intendierte Verhalten steht grade nicht im Code, sondern bleibt übrig oder fällt an

- -
+
@@ -160149,8 +160243,7 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo Hierzu zähle ich auch den in der Praxis sehr häufigen Fall weithin verteilter Entscheidungs-Kaskaden, deren Konsequenz nur sichtbar wird, wenn man in einer ganz bestimmten Weise durch die Codebasis navigiert; jedes Einzelstück, das man dabei zu fassen bekommt, ist für sich genommen nichtsagend. Eine ähnliche Situation kann aber auch bei hochgradig »algorithmischem« Code auftreten, der zwar ganz kompakt an einer Stelle steht, dessen eigentliche Relevanz sich aber nur erschließt, wenn man sein Verhaltensmuster entschlüsselt hat.

- - +
@@ -160311,7 +160404,7 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo - + @@ -160333,9 +160426,40 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo

- - - + + + + +

+ Das muß auf jeden Fall sowiso passieren, sobald ein Binding in den Regeln dauerhaft und global sichtbar etabliert wird — was schon allein dadurch geschehen kann, daß man eine ganz bestimmte Lösung verwendet. Dieser Vermerk einer etablierten Zuordnung ist es am Ende dann auch, der bei späteren Umordnungen und UNDO erkannt und umgekehrt werden muß, was dann die Überprüfung aller Konsequenzen nach sich zieht +

+ +
+ + + + +
+ + + + +

+ Die Regeln und Konfigurationsquellen müssen ohnehin dort repräsentiert sein (möglicherweise nur symbolisch); allerdings: alles, was sich hier niederschlägt, muß unter den Begriff einer Projektion passen. Ein weiteres Problem ergibt sich daraus, daß ja eine Verbindung aufgezeichnet werden soll zwischen einer Regelbasis, einem Binding (also einer Auswertung) und einem konkreten Element, dessen Wert dadurch beeinflußt ist — dazu müßte erst noch eine Referenz-Notation geschaffen werden (mutmaßlich auf Basis einer EntryID oder AssetID) +

+ +
+
+ + + + +

+ Diese Annotation hier zu speichern wirkt auf den ersten Blick etwas künstlich, ist aber durchaus möglich, da wir die Implementierung der Constraints in den Placements komplett unter unserer Kontrolle haben. Dadurch ergibt sich auch noch ein weiterer Vorteil: man könnte eine Detail-Einstellung markieren oder attributieren, ohne erst eine Pfad- oder Diff-Notation einführen zu müssen, denn die Marke wäre direkt in der Kette der Constraints, bereits an der richtigen Stelle... +

+ +
+
@@ -160667,6 +160791,13 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo
+ + + + + + + @@ -161952,6 +162083,22 @@ unsigned int ThreadIdAsInt = *static_cast<unsigned int*>(static_cast<vo
+ + + + + + + + + + + + + + + +