Ankündigung

Einklappen
Keine Ankündigung bisher.

Realisierung der Modulverwaltung

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Realisierung der Modulverwaltung

    Schönen Sonntag allerseits!

    Ich habe mich in der letzten Woche mal hingesetzt und mir überlegt, wie ich die Verwaltung von Modulen in einem "Framework" möglichst abstrakt umsetzen könnte.

    Ich habe mich auf zwei Klassen verständigt, ModuleElement und ModuleManager.
    Die Klasse ModuleElement arbeitet immer mit einem Element eines Moduls. Attribute sind der Modulname und die ID, die Methoden Add(), Delete(), Edit() und Get. Bei Add() und Edit() werden jeweils die Felder via Parameter als Array übergeben.
    So kann eine News in etwa so hinzugefügt werden.

    PHP-Code:
    <?php
    // Inhalt der News
    $NewsContent = array('Titel' => 'Testtitel''Datum' => time(), 'Inhalt' => 'Testinhalt');

    // News hinzufügen
    $News = new ModuleElement('news');
    $News->Add($NewsContent);
    ?>
    Das Bearbeiten erfolgt auf ähnliche Weise:

    PHP-Code:
    <?php
    // Inhalt der News
    $NewsContent = array('Titel' => 'Testtitel''Datum' => time(), 'Inhalt' => 'Testinhalt');

    // News bearbeiten (ID der News = 6)
    $News = new ModuleElement('news'6);
    $News->Edit($NewsContent);
    ?>
    Analog verhält es sich beim Löschen und Zurückliefern der News (natürlich ohne das Array) via Get().

    Das Zurückliefern der News soll nun aber nicht exklusiv über diese Klasse gehandhabt werden, da sie sich, wie der Name schon sagt, stets nur mit einem Element eines Moduls beschäftigt.
    Hierfür wäre die Klasse ModuleManager zuständig. Parameter benötigt sie nicht, instanziiert werden soll sie auch nicht.
    Methoden der Klasse ModuleManager sind Get() zum Auslesen eines einzigen Elements, GetInterval(), um ein Intervall von Elementen auszulesen, und GetConfig() zum Auslesen der Konfiguration aus der Datenbank.

    Ablaufen würde das in etwa so:

    PHP-Code:
    <?php
    // Intervall auslesen (Modulname, Start-ID, End-ID und Sortiermethoden als Paramter)
    $NewsArray ModuleManager::GetInterval('news'130'ID''DESC');

    // Eine News auslesen (ID = 6)
    $News ModuleManager::Get(6);

    // Konfiguration auslesen
    $NewsPerPage ModuleManager::GetConfig('news''perpage');
    ?>
    Hier muss natürlich immer überprüft werden, ob die entsprechende Tabelle (wessen Name das Modul quasi repräsentiert) und deren Felder existieren.
    Vielleicht wäre hier auch eine Art Rohling nützlich, um das Modell einer Tabelle auch im Code selbst zu definieren.
    Nützlich wäre zudem wohl noch eine Methode, um die Gesamtanzahl der Einträge auszulesen.


    Ansonsten wäre ich mit der Präsentation dieser Realisierung erst einmal am Ende angelangt. Meine Fragen: Ist das alles soweit verständlich? Ist der Realisierungsansatz sinnvoll oder nicht? Gibt es hier oder da vom Konzept her Sackgassen, die zu Problemen führen werden? Oder fehlt es einfach noch an Features, die ihr hinzufügen würdet?

    Wäre dankbar für jede Kritik, jeden Rat oder Hinweis.

    Mit freundlichen Grüßen
    Matze

    EDIT: Ich sehe gerade, dass dieses Thema vielleicht eher in den Bereich Software-Design passt. Sorry dafür.

  • #2
    Hallo Matze,

    ich habe den Thread mal in das "Softwarearchitektur"-Forum verschoben, da ich auch der Meinung bin, dass es dort besser aufgehoben ist.

    Das Zurückliefern der News soll nun aber nicht exklusiv über diese Klasse gehandhabt werden, da sie sich, wie der Name schon sagt, stets nur mit einem Element eines Moduls beschäftigt.
    Irgendwie werde ich das Gefühl nicht los, dass du mehr an Modul-Abstraktion denn an Modul-Verwaltung denkst?!

    Hierfür wäre die Klasse ModuleManager zuständig. Parameter benötigt sie nicht, instanziiert werden soll sie auch nicht.
    Das halte ich für einen Fehler. Der ModuleManager muss doch wissen, in welchem Umfeld ein Modul ausgeführt wird und das dem Modul mitteilen. Unterlässt du das, wird es nicht möglich sein, eine allgemeingültige Konfigurationsmöglichkeit zu schaffen. Weiterhin müsstest du dann sehr viele Funktionen in deinen Modulen nochmals implementieren, die man im Fall der Kenntniss des Umfeldes auslagern kann (z.B. Link-Generierung).

    Ansonsten wäre ich mit der Präsentation dieser Realisierung erst einmal am Ende angelangt. Meine Fragen: Ist das alles soweit verständlich? Ist der Realisierungsansatz sinnvoll oder nicht? Gibt es hier oder da vom Konzept her Sackgassen, die zu Problemen führen werden? Oder fehlt es einfach noch an Features, die ihr hinzufügen würdet?
    Ehrlich gesagt kann ich kein Konzept erkennen. Du schaffst mit der bisherigen Implementierung keinen Mehrwert für dein Modul, da du es nicht ohne Anpassungen in Umgebung A und in B einsetzen kannst. Weiterhin mischst/verwechselst du Aufbau und Verwaltung ein wenig. Man kann sicher viele Gemeinsamkeiten zwischen Modulen erkennen und diese auslagern, nur ein Modul hart auf definierte Methoden zu begrenzen halte ich für einen Fehler.

    Ich erachte es deshalb als wichtig, dass du dir zunächst Gedanken machst, wie die Kopplung deiner Module stattfindet. Ist es auf der Ebene der Präsentation? Bindest du deine Module "hart" in einer Bootstrap-Datei ein? Dient ein Modul nur der Kapselung einer bestimmten Funktion?
    Nur wenn die Basisfragen geklärt sind, kann eine zufriedenstellende Beurteilung getroffen oder ein (Software-)Design erstellt werden.

    Kleiner Exkurs zum APF: dort biete ich einen gemeinsamen Schnittpunkt in der Präsentationsschicht an. Dieser ermöglicht es per Tag ein Modul einzubinden ohne Änderungen am bisherigen Konstrukt tätigen zu müssen. Diese "Tag-Schnittstelle" bietet jedoch dem eingebundenen Modul alle Informationen seines Umfelds in dem es ausgeführt wird. Das sind Umgebung, Kontext, Sprache, ... mit denen das Modul auch umgehen muss, da es schließlich auch eine Web-Anwendung ist wie sein Rahmen. Mit diesem Informationen kann das Modul dann agieren, als wäre es alleine im selben Umfeld unterwegs. Agieren bedeutet in diesem Fall dann Konfigurationen für das richtige Umfeld laden, Links für den aktuellen Betriebsmodus generieren (URL-Rewriting vs. "normale" URLs) und falls notwendig mit der Tag-Schnittstelle kommunizieren (beziehen weiterer Informationen oder Inhalt des Moduls zur Ausgabe zurückgeben). All diese Themen sollten IMHO für eine derartige Schnittstelle bedacht werden.
    Viele Grüße,
    Dr.E.

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1. Think about software design [B]before[/B] you start to write code!
    2. Discuss and review it together with [B]experts[/B]!
    3. Choose [B]good[/B] tools (-> [URL="http://adventure-php-framework.org/Seite/088-Why-APF"]Adventure PHP Framework (APF)[/URL][URL="http://adventure-php-framework.org"][/URL])!
    4. Write [I][B]clean and reusable[/B][/I] software only!
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Kommentar


    • #3
      Danke für deine Antwort! Auf dich habe ich gezählt, vor Ewigkeiten haben wir auch schonmal via PN kommuniziert.

      Zitat von dr.e. Beitrag anzeigen
      Irgendwie werde ich das Gefühl nicht los, dass du mehr an Modul-Abstraktion denn an Modul-Verwaltung denkst?!
      D'accord. Ich war mir nicht sicher, wie ich das nun am besten formuliere.

      Zitat von dr.e. Beitrag anzeigen
      Das halte ich für einen Fehler. Der ModuleManager muss doch wissen, in welchem Umfeld ein Modul ausgeführt wird und das dem Modul mitteilen. Unterlässt du das, wird es nicht möglich sein, eine allgemeingültige Konfigurationsmöglichkeit zu schaffen. Weiterhin müsstest du dann sehr viele Funktionen in deinen Modulen nochmals implementieren, die man im Fall der Kenntniss des Umfeldes auslagern kann (z.B. Link-Generierung).
      Du hast es ja auch weiter unten im Bezug auf dein Framework schonmal angesprochen, die Schnittstelle brauch irgendwelche Informationen für die Umgebung. Kannst du das etwas konkretisieren? Was für Informationen sollten an den Module-Manager übergeben werden? Wie sollten diese verarbeitet werden?

      Zitat von dr.e. Beitrag anzeigen
      Ehrlich gesagt kann ich kein Konzept erkennen. Du schaffst mit der bisherigen Implementierung keinen Mehrwert für dein Modul, da du es nicht ohne Anpassungen in Umgebung A und in B einsetzen kannst. Weiterhin mischst/verwechselst du Aufbau und Verwaltung ein wenig. Man kann sicher viele Gemeinsamkeiten zwischen Modulen erkennen und diese auslagern, nur ein Modul hart auf definierte Methoden zu begrenzen halte ich für einen Fehler.
      Danke trotzdem für die Einschätzung.
      Der "Mehrwert" soll darin liegen, nicht für jedes Modul eine Klasse "news", "user" oder "guestbook" schreiben zu müssen, in dem jeweils ein Teil der News oder alles ausgelesen werden soll. Das war der Grundgedanke. Konzept ist vielleicht auch etwas blöd formuliert, Ansatz trifft es eher.
      Inwiefern sind die beiden Klassen nicht allgemeingültig? Wo könnten Probleme auftauchen?
      Auf was für einer Ebene werden Aufbau und Verwaltung gemischt oder auch verwechselt?
      Inwiefern kann ich es realisieren, die Module eben nicht auf die gemeinsamen Methoden zu begrenzen. Überhaupt möglich mit meinem Ansatz oder nur über weitere spezifische Modulklassen, die dann von meinen präsentierten Klassen erben?

      Zitat von dr.e. Beitrag anzeigen
      Ich erachte es deshalb als wichtig, dass du dir zunächst Gedanken machst, wie die Kopplung deiner Module stattfindet. Ist es auf der Ebene der Präsentation? Bindest du deine Module "hart" in einer Bootstrap-Datei ein? Dient ein Modul nur der Kapselung einer bestimmten Funktion?
      Nur wenn die Basisfragen geklärt sind, kann eine zufriedenstellende Beurteilung getroffen oder ein (Software-)Design erstellt werden.
      Ich muss hier ehrlich gesagt etwas passen. Das Verständnis für Design Pattern geht mir etwas ab. Die Präsentationsschicht ist doch eigentlich zuständig für die Kommunikation zwischen Benutzereingabe und Verarbeitung dieser Daten. Dafür sollten eigentlich noch weitere Dateien geschaffen werden, die dann die Daten aus den URLs auslesen und daraufhin die oben genannten Klassen aufrufen.
      Was nun mit harter Einbindung in eine Bootstrap-Datei gemeint ist, sorry, da muss ich vollkommen passen.

      Gut möglich, dass das auch einfach nur ein kleines Missverständnis aufgrund des Wortes "Verwaltung" ist. Abstraktion trifft es definitiv besser.

      Versteh mich nicht falsch, ich will jetzt nicht zwanghaft versuchen meine Idee zu verteidigen. Meine Intention ist es Unklarheiten zu beseitigen. Du hast mir bei unserem damaligen Kontakt via PN auch den Tip gegeben, möglichst alles Unverständliche zu hinterfragen.

      Kommentar


      • #4
        Hallo Matze,

        melde mich Morgen Abend mit einem ausführlichen Post, muss jetzt ins Bett.
        Viele Grüße,
        Dr.E.

        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        1. Think about software design [B]before[/B] you start to write code!
        2. Discuss and review it together with [B]experts[/B]!
        3. Choose [B]good[/B] tools (-> [URL="http://adventure-php-framework.org/Seite/088-Why-APF"]Adventure PHP Framework (APF)[/URL][URL="http://adventure-php-framework.org"][/URL])!
        4. Write [I][B]clean and reusable[/B][/I] software only!
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

        Kommentar


        • #5
          Hallo Matze,

          Kannst du das etwas konkretisieren? Was für Informationen sollten an den Module-Manager übergeben werden? Wie sollten diese verarbeitet werden?
          Aus meiner Erfahrung heraus sollte vor Allem das das Thema Konfiguration erfasst werden. Hierfür sehe ich im Allgemeinen
          • Basis-Pfad
          • Context (=Umfeld der Anwendung)
          • Environment (=Infrastruktur/Server)
          • Name der Konfigurationsdatei

          vor. Dies ermöglicht es, eine sehr generische Konfiguration, die alle mir bisher untergekommenen Fälle abdecken. Daneben habe ich in der Page-Controller-Implementierun die Sprache als wichtigen Bestandteil aufgenommen, um die Grundlagen für mehrsprachige Anwendungen bereits im Kern zu ermöglichen.

          Über mindestens diese Informationen sollte die Schnittstelle verfügen und sollte sie dem erzeugten / verwalteteten Modul übergeben. Weitere Parameter sind aus meiner Erfahrung
          • URL-Rewriting (oder eben nicht)
          • Konfigurationsattribute eines Moduls, die von aussen dynamisch durch die Einbindung/Schnittstelle mitgegeben werden
          • evtl. eine Referenz auf ein zentrales Objekt-Repository (Registry), sofern dieses dazu genutzt wird, globale Informationen in Form von Objekten zu referenzieren.

          Bei komplexen Systemen ist es weiterhin wichtig, dass Module an unterschiedlichen Stellen eingebunden werden können sollten. Das bedeutet, dass ich als Entwickler die Flexibilität habe, in einem Modul ein weiteres Sub-Modul über den gleichen Mechanismus einzubinden. Beispiel: ich habe ein Listen-Ausgabe-Widget, dann möchte ich das in meinem Gästebuch und in meiner News-Ausgabe gleichermaßen wiederverwenden können. Falls das nicht geht, macht die Modularisierung auf dieser Ebene (Schnittstelle) IMHO nur begrenzt Sinn, sondern stellt quasi nur einen Wrapper für einen Modul-Aufruf dar.

          Der "Mehrwert" soll darin liegen, nicht für jedes Modul eine Klasse "news", "user" oder "guestbook" schreiben zu müssen, in dem jeweils ein Teil der News oder alles ausgelesen werden soll. Das war der Grundgedanke. Konzept ist vielleicht auch etwas blöd formuliert, Ansatz trifft es eher.
          Das geht dann aber eher in die Richtung der Datenschicht-Abstraktion. Sprich (fabuliert): ich habe eine generische Komponente, die mir z.B. an Hand einer Konfiguration Objekte meiner Anwendung zur Verfügung stellt (Gästebuch mit Einträgen und Kommentaren, News mt Kommentaren, ...). Das hat dann schon mal den Vorteil, dass ich diese Komponente in unterschiedlichen Modulen wiederverwenden kann und diese Funktionalität nicht wieder neu geschrieben werden muss. Um deine Intension abgrenzen zu können, hier den Hinweis auf den GenericORMapper des APF. Vielleicht ist es in etwa das, was du suchst? (Nach dem nochmaligen Durchlesen deines Codes gehe ich sogar stark davon aus, dass du etwas in der Art suchst )

          Inwiefern sind die beiden Klassen nicht allgemeingültig? Wo könnten Probleme auftauchen?
          Nehmen wir an, ein Eintrag deines Gästebuchs besitzt noch einen Kommentar. Wie kann ich diesen mit Hilfe des ModuleManagers abbilden? Zweite Fragestellung: warum unterstützt der Manager keine Ausgabe-Komponente für das Paging? Dies ist IMHO sehr einfach allgemeingültig abbildbar und würde dir das Leben bei der Erstellung eines konkreten Moduls viel Arbeit abnehmen.

          Auf was für einer Ebene werden Aufbau und Verwaltung gemischt oder auch verwechselt?
          An sich - so denke ich - möchtest du zwei Dinge erreichen: Datenabstraktion und Einbindung/Aufruf eines Moduls. Beide Bereiche werden jedoch nicht so abgebildet, dass ich mit einem einfachen

          PHP-Code:
          $mod = new Module('...','...');
          echo 
          $mod->display(); 
          ein Modul aufrufen/einbinden/darstellen kann. Innerhalb dieses "Containers" kann es ja immer wieder Abstraktionsschichten und Komponenten geben, die dir bestimmte Dinge abnehmen. Es fehlt mir einfach momentan ein Hinweis, wie bei dir der "Container" aussieht und wie dieser mit einem Modul agiert.


          Inwiefern kann ich es realisieren, die Module eben nicht auf die gemeinsamen Methoden zu begrenzen. Überhaupt möglich mit meinem Ansatz oder nur über weitere spezifische Modulklassen, die dann von meinen präsentierten Klassen erben?
          Du musst natürlich ein gemeinsames Interface definieren. Es kommt nur darauf an, wo du das definierst. Mit dem von dir beschriebenen Ansatz schränkst du dich IMHO zu stark ein, da er nur sehr starr begrenzte Methoden unterstützt. Wählst du den oben skizzierten Ansatz, bist du freier in der internen Gestaltung eines Moduls, hast jedoch trotzdem die Freiheit, intern weitere generische Komponenten zu verwenden. Das bedeutet folgende Struktur:

          Code:
          Container
             -> Modul
                 -> Präsentationskomponenten
                     -> verwendet Listen-Widget
                     -> verwendet interne gemeinsame Komponenten
                 -> Datenlogik
                     -> verwendet Datenschicht-Abstraktion  
                 -> ...
          Ich hoffe, ich konnte dir weiterhelfen.
          Viele Grüße,
          Dr.E.

          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          1. Think about software design [B]before[/B] you start to write code!
          2. Discuss and review it together with [B]experts[/B]!
          3. Choose [B]good[/B] tools (-> [URL="http://adventure-php-framework.org/Seite/088-Why-APF"]Adventure PHP Framework (APF)[/URL][URL="http://adventure-php-framework.org"][/URL])!
          4. Write [I][B]clean and reusable[/B][/I] software only!
          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

          Kommentar


          • #6
            Manchmal lohnt es sich ja bestehende größere Anwendungen und die dort vorhandene Modulintegration anzuschaun.

            Grob unterschieden werden meist Plugins und Module,
            wobei Plugins die Grundfunktionalität der Anwendung
            erweitern und Module eben zusätzliche Programmteile sind.
            Die Anwendung erkennt bei prozeduraler Programmierung
            ein Modul an seinem Speicherplatz und anhand einer Konfigdatei (XML) und bindet die Dateien per include ein.
            Die Anwendung stellt dem Modul bestimmte Funktionen
            zur Verfügung welche in einer API-Doc beschrieben sind
            und an die sich das Modul halten muß (z.B. Basispfad,
            Templateeinbindung, Sprachintegration).


            Vor dem Hintergrund einer OOP/MVC - Umsetzung
            können wir "Plugins" vergessen. Das wären dann
            schlicht Erweiterungen des Frameworks.

            Damit ein Modul erkannt wird müßte es für das Framework
            irgendwie als Modul erkennbar sein.
            Das Modul müßte aus mindestens einer der Komponenten
            Model, View, Controller bestehen und das Framework
            müßte dem Modul verschiedene Methoden zur Verfügung
            stellen, z.B. "AddJavascript()", "AddView()", "ViewPosition()",
            "AddCSS()", "GetRAWPostData()", "GetModulConfig()"(mit den
            Infos über das Modul:Name, Ersteller, Datum, Anzahl der Dateien etc.).

            Darüber hinaus sollte das Modul möglichst unabhängig sein können.
            Also z.B. selbst entscheiden können ob es ein eigenes Template/View
            benutzt oder sich in ein bestehendes "einklinkt".
            Es sollte auch möglich sein, daß ein "fremder" Programmierer sein
            Modul prozedural und mit möglichst geringer Kenntnis des Frameworks
            schreiben kann wenn er das denn möchte.

            Ich hoffe, daß meine Überlegungen nicht völliger Stuss sind,
            aber so würd ich an die Sache rangehn.
            Eine if-else-Abfrage nimmt, ordentlich geschrieben eine Menge Platz weg. Platzsparend geht es mit einem ternären Operator.

            Kommentar


            • #7
              Ich hoffe, daß meine Überlegungen nicht völliger Stuss sind,
              aber so würd ich an die Sache rangehn.
              Nein, was du beschreibst ist eine allgemeinere Darstellung der von mir skizzierten Schnittstelle. Exakt das brauchst du bei "Modulen" um sie unabhängig, jedoch allgemeingültig einsetzbar, zu gestalten.
              Viele Grüße,
              Dr.E.

              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
              1. Think about software design [B]before[/B] you start to write code!
              2. Discuss and review it together with [B]experts[/B]!
              3. Choose [B]good[/B] tools (-> [URL="http://adventure-php-framework.org/Seite/088-Why-APF"]Adventure PHP Framework (APF)[/URL][URL="http://adventure-php-framework.org"][/URL])!
              4. Write [I][B]clean and reusable[/B][/I] software only!
              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

              Kommentar

              Lädt...
              X