ModelObserverManagingCompositorCompositeObservable



  • Mannmannmann,
    es kann doch nicht sein, dass Applikationsprogrammierung so dermaßen ätzend ist. Innerhalb von ein paar Stunden erstellt man interessante Algorithmen, die auf vernünftigen Datensätzen vernünftige Ergebnisse liefern. Und dann soll das ganze zu einem Anwenderprogramm gegossen werden. Man fängt an zu abstrahieren, unterteilt in Komponenten. Jeder Komponente hat ihren oder ihre Zustände, um die Komponenten unter einen Hut zu bringen, muss man irgendwie die Zustände konsistent halten. Dann erstellt man tausend Observer-Schnittstellen, damit sich alles schön updated wenn der Nutzer hier einen Button clickt, dort einen Datensatz löscht, hier am Mausrädchen fummelt und dort 'A' drückt. Wunderschön trällern die Models und die Observer verfallen in einen Wahn, ein Orchester an Zustandsgedöns geht los.

    Eine Liste hat sich geändert? Naja, das Listenmodell an der Combobox sorgt schon dafür. Oder das Combobox-Modell an der Liste? Oder aber ein ListModelObserverComboboxAdapterModel? Oder die Liste benutzt std::function-events? Ochjee, aber der Observer könnte die Information doch anders viel besser verarbeiten. Schade drum. 😞

    Das kann es doch nicht sein? Warum liest man nicht von einer erhöhten Suizidrate von Anwendungsprogrammierern?

    Jetzt sagt der Funktionalprogrammierer: Tja Pech gehabt, wenn Du (redundante) Zustände überhaupt erst zulässt. Der Pragmatiker unter den imperativen Programmierern sagt: Mehr Speicher, kürzere Wege, schnell schnell!

    Darum jetzt hier meine Fragen: Was ist die Antwort auf die Inflation der Zustände? Scheinbar führt die natürliche Intuition im Rahmen von UI-Programmen an der obersten Schicht zu extrem viel Java-like-Code. Wie schafft man es, ohne tausend Modellabhängige Observer oder observerabhängige Models, und ohne dass der Code, der die Komponenten verdahtet endlos mit Affencode anwächst?

    Und überhaupt, sollten Drogen nicht für Anwendungsprogrammierer legalisiert werden?

    Ich krieg' nen Zustand!



  • Hrmmm,
    also so eine Schnittstelle besteht ja nun immer aus Funktionen, die den Zustand verändern, oder solchen, die den Zustand offenbaren und vielleicht einigen, die beides tun.
    Man könnte ja nun, statt die Observer irgendwie durch Objektspezifische Schnittstellen in den Objekten zu verwalten, eine "globale" Liste von Funktionszeigern führen, für deren "Veränderung" der Rückgabewerte sich bestimmte andere Objekte interessieren.
    Wenn jetzt zB. vector::push_back aufgerufen wird, dann würde ja zum Beispeil vector::size und vector::operator[] mit einem bestimmten Parameter ein anderes Ergebnis liefern.
    Client-Code, der sich nun auf einen bestimmten vector synchronisiert, könnte sich nun für die Funktionen eintragen, die er aktiv verwendet, und auf dessen Rückgabewerte er sich synchronisiert.

    Irgendwie so:

    struct trackable_vector {
       void push_back() {
           size_t old_size = size();
    
           // ...  
    
           notify(this);
           notify(&vector::size, this);
           notify(&vector::operator[], this, old_size);
       }
    };
    
    struct client : tracker {
       client( trackable_vector* vec ) {
          subscribe(&trackable_vector::size, vec, this, [](){foo()} );
          subscribe(&trackable_vector::operator[], vec, this, [](int i) {bar(i);} );
       }
    }
    

    So wüsste trackable_vector nix von irgendeinem Observer-Interface und der client kann sich selber aussuchen, wie granular er es denn haben möchte, oder welche Veränderungen er überhaupt mitbekommen muss.
    Und überhaupt nur für solche Objekte, die aktiv getrackt werden, landet etwas im Speicher. Beim Lookup müsste man sich natürlich etwas einfallen lassen...
    Hrmmm... Aber ob das wirklich besser ist, als überall Observer-Schnittstellen zu definieren und die Listen in den Objekten zu führen?


Anmelden zum Antworten