hotti: Trennung DAL?AL

hi,

hier im Forum sehe ich viel PHP-Code, in welchem SQL-Statements inmitten von Scripts notiert sind. Deswegen mal so gefragt:

Ist es in PHP möglich, eine Trennung zwischen Data Abstraction Layer (DAL) und Application Layer (AL) zu erreichen?

Das Ziel:

  • im AL wird nur mit Datenstrukturen operiert
  • im AL stehen keine SQL-Statements
  • der AL wird unabhängig von der Datenhaltungs-Schicht
  • Änderungen im DAL wirken sich nicht auf den AL aus, es ist lediglich die Vermittlungsschicht anzupassen
    ...

Hotti

  1. Hi!

    hier im Forum sehe ich viel PHP-Code, in welchem SQL-Statements inmitten von Scripts notiert sind.

    Das wäre sicherlich in jeder Sprache, die so populär wäre wie PHP der Fall.

    Ist es in PHP möglich, eine Trennung zwischen Data Abstraction Layer (DAL) und Application Layer (AL) zu erreichen?

    Natürlich, wie in jeder Sprache.

    Lo!

    1. hi,

      Ist es in PHP möglich, eine Trennung zwischen Data Abstraction Layer (DAL) und Application Layer (AL) zu erreichen?

      Natürlich, wie in jeder Sprache.

      Hast Du mal ein Beispiel für PHP, gerne auch als Link?

      Vielen Dank,
      Hotti

      1. Hi!

        Ist es in PHP möglich, eine Trennung zwischen Data Abstraction Layer (DAL) und Application Layer (AL) zu erreichen?
        Natürlich, wie in jeder Sprache.
        Hast Du mal ein Beispiel für PHP, gerne auch als Link?

        Beispielsweise kann man mit MVC die grundlegenden Zuständigkeiten einer Anwendung regeln. Das Model seinerseits, in dem ja die Geschäftslogik stattfindet, kann über ein Repository die Datenhaltung ansprechen. Das Repository hält dafür grundlegende und je nach Bedarf spezialisierte RUDI-Funktionalität bereit. Konkrete Implementierungen findest du in den diversen Frameworks.

        Aber nur weil man das so machen kann, heißt das nicht, dass man das so machen muss, um hip zu sein. Je kleiner das Projekt, desto übertriebener und unangemessener wirkt üblicherweise der Einsatz solcher Spatzenkanonen.

        Lo!

        1. hi, danke,

          Beispielsweise kann man mit MVC die grundlegenden Zuständigkeiten einer Anwendung regeln. Das Model seinerseits, in dem ja die Geschäftslogik stattfindet, kann über ein Repository die Datenhaltung ansprechen. Das Repository hält dafür grundlegende und je nach Bedarf spezialisierte RUDI-Funktionalität bereit. Konkrete Implementierungen findest du in den diversen Frameworks.

          Das ist nicht das, was ich meine. CRUD macht keine Trennung zwischen DAL?AL. DAL ist ein abstraktes Modell, das muss nicht unbedingt ein RDBMS sein.

          Der Zusammenhang zwischen DAL und AL sieht so aus:

          ------------------------------------------------
          |  Application Layer, main()                     |
          |  Operiert mit Datenstrukturen                  |
           ------------------------------------------------
            ------------------------------------------------
          | Vermittlungsschicht                            |
          | Binden der Datenstrukturen                     |
           ------------------------------------------------
           ------------------------------------------------
          | Data Abstraction Layer                         |
          | mySQL|Sybase|...|Filesystem                    |
           ------------------------------------------------

          Hotti

          1. Hi!

            Beispielsweise kann man mit MVC die grundlegenden Zuständigkeiten einer Anwendung regeln. Das Model seinerseits, in dem ja die Geschäftslogik stattfindet, kann über ein Repository die Datenhaltung ansprechen. Das Repository hält dafür grundlegende und je nach Bedarf spezialisierte RUDI-Funktionalität bereit. Konkrete Implementierungen findest du in den diversen Frameworks.

            Das ist nicht das, was ich meine. CRUD macht keine Trennung zwischen DAL?AL. DAL ist ein abstraktes Modell, das muss nicht unbedingt ein RDBMS sein.

            CRUD/RUDI muss sich auch nicht zwangsläufig nur auf DBMSe beziehen. Ich hab auch nicht behauptet, dass RUDI die Trennung machen würde. Als Bestandteil des Repositorys ist RUDI ein Teil des DAL. Das Repository kapselt den DAL.

            Lo!

            1. hi,

              CRUD/RUDI muss sich auch nicht zwangsläufig nur auf DBMSe beziehen. Ich hab auch nicht behauptet, dass RUDI die Trennung machen würde. Als Bestandteil des Repositorys ist RUDI ein Teil des DAL. Das Repository kapselt den DAL.

              Ahh, verstehe, danke Dir! Viele Begriffe, alle schonmal gehört irgendwie. Ich verliere mich in der Recherche. Ich suche ein PHP-Script, was über Datenstrukturen mit einer DB kommuniziert ohne scriptinterne SQL-Statements zu verwenden. Geht das nur mit so mächtigen Frameworks wie im Wiki genannt?

              Hotti

              1. Hi!

                Ich suche ein PHP-Script, was über Datenstrukturen mit einer DB kommuniziert ohne scriptinterne SQL-Statements zu verwenden. Geht das nur mit so mächtigen Frameworks wie im Wiki genannt?

                Nein. Aber kleine Scripts sind mit dem EVA-Prinzip in der Regel überschaubar genug strukturiert. Niemand hindert dich jedoch, das SQL-Statement in eine Funktion zu packen, um dir einen DAL zu bauen. Dann iterierst du aber zweimal über die Daten, einmal die Fetch-Schleife um das Rückgabe-Array zu erstellen und dann die Ausgabe-Schleife über dieses Array. Selbst wenn PHP so clever ist, bei Zuweisungen an andere Variablen keine wirklichen Kopien sondern Quasi-Referenzen der Daten erzeugt, solange sie sich nicht ändern, hast du immer noch den Zeitaufwand des Iterierens, der damit Teil der Kosten für deinen DAL ist.

                Lo!

                1. Hi!

                  Ich suche ein PHP-Script, was über Datenstrukturen mit einer DB kommuniziert ohne scriptinterne SQL-Statements zu verwenden. Geht das nur mit so mächtigen Frameworks wie im Wiki genannt?

                  Nein. Aber kleine Scripts sind mit dem EVA-Prinzip in der Regel überschaubar genug strukturiert. Niemand hindert dich jedoch, das SQL-Statement in eine Funktion zu packen, um dir einen DAL zu bauen.

                  Ok, das ist der erste Schritt, der auch in PHP sehr gut machbar ist: Objekterstellung, Methoden aufrufen.

                  Dann iterierst du aber zweimal über die Daten, einmal die Fetch-Schleife um das Rückgabe-Array zu erstellen und dann die Ausgabe-Schleife über dieses Array.

                  Bei kleinen Array ist das ok. Wenn es absehbar ist, dass ein Result ein bischen größer wird (oder wenn es eben nicht absehbar ist, wie groß das wird, maximal-Grenze festlegen), ist eine Callback-Funktion (CB) angebracht: damit liegt nicht die gesamte Tabelle im Hauptspeicher sondern nur ein Record, während der Iteration innerhalb der DB-Class bringt die CB die Daten sofort auf die Ausgabe.

                  Selbst wenn PHP so clever ist, bei Zuweisungen an andere Variablen keine wirklichen Kopien sondern Quasi-Referenzen der Daten erzeugt, solange sie sich nicht ändern, hast du immer noch den Zeitaufwand des Iterierens, der damit Teil der Kosten für deinen DAL ist.

                  Es hat alles seinen Preis/Kosten. Frameworks sind mächtige und respektable Gesellen. Ich möchte nicht mit Kanonen auf Spatzen schießen, ich möchte es verstehen. Die Trennung von DAL?AL muss nicht um jeden Preis erfolgen, das ist auch für mich ein bischen Neuland worauf noch Einiges zu optimieren ist. Optimierungen sind im Prinzip dieselben, nur anders verpackt und an einer anderen Stelle: in der Vermittlungsschicht.

                  Beispiel Darstellung eines Tree in einem Forum: Gebraucht werden nur die URLs und die jeweiligen Title, damit kann der Tree dargestellt werden. Es wäre bei einem

                    
                  tie %forum;  
                  
                  

                  etwas ungeschickt, mehr als das, was gebraucht wird, in den RAM zu laden. Wenn in %forum (url => title) steht, reicht das vollkommen. Anders hingegen, wenn eine Nachricht dargestellt werden soll, dazu der gesamte Thread als Teilbaum. Der Kompromiss besteht darin, für alle zum Teilbaum gehörigen Nachrichten die komplette Attributliste einzulesen, auch wenn das Attribut 'mesg' nur einer Nachricht gebraucht wird.

                  Hotti

                  1. Hi!

                    Dann iterierst du aber zweimal über die Daten, einmal die Fetch-Schleife um das Rückgabe-Array zu erstellen und dann die Ausgabe-Schleife über dieses Array.
                    Bei kleinen Array ist das ok. Wenn es absehbar ist, dass ein Result ein bischen größer wird (oder wenn es eben nicht absehbar ist, wie groß das wird, maximal-Grenze festlegen), ist eine Callback-Funktion (CB) angebracht: damit liegt nicht die gesamte Tabelle im Hauptspeicher sondern nur ein Record, während der Iteration innerhalb der DB-Class bringt die CB die Daten sofort auf die Ausgabe.

                    Um das als nicht wirklich zielführend zu erkennen, muss man die PHP-Interna und die MySQL-Client-API-Arbeitsweise ein wenig kennen. Das Ergebnis einer Query liegt üblicherweise sowieso im Hauptspeicher, weil die MySQL-Client-API selbiges bereits im Hintergrund abholt. Die Fetch-Vorgänge holen die Datensätze nur noch aus diesem Puffer. (Nur bei ungepufferten Querys holt das Fetchen die Daten live ab. Ungepuffert sollte man nur bei großen Datenmengen verwenden, wenn der Roundtrip für jeden Fetch-Vorgang nicht mehr ins Gewicht fällt.) Ab PHP 5.3 mit dem mysqlnd-Treiber wird der Puffer sogar so angelegt, dass das Fetchen in PHP-Variablen keine Kopien der Daten mehr erzeugt sondern die Variablen gleich direkt auf die Pufferstelle verweisen. Das heißt, dass beim Fetchen und Ergebnis-Array-Anlegen nur Variablencontainer für die Verweise auf die gepufferten Daten angelegt werden. Ein Callback bringt keine Vorteile, nur zusätzliche Funktionsaufrufe. Aber selbst mit ungepufferten Daten würde ich keine Callbacks nehmen, sondern würde das Iterator-Interface aus der SPL implementieren. Dann kann der AL in jedem Fall über das Ergebnis der DAL-Funktion mit foreach iterieren - entweder über ein echtes Array oder eben simuliert. Somit muss man im AL nicht beachten, ob man einfach iterieren kann oder callbacken muss.

                    Lo!

                    1. Hi!

                      Um das als nicht wirklich zielführend zu erkennen, muss man die PHP-Interna und die MySQL-Client-API-Arbeitsweise ein wenig kennen. Das Ergebnis einer Query liegt üblicherweise sowieso im Hauptspeicher, [..]

                      Wow, mein Lieber, das ist wirklich interessant, vielen Dank für die Infos!!

                      In der Hoffnung, dass Dich/Euch das auch ein bischen interessiert: Mittlerweile habe ich fürs Loggen meiner Seitenzugriffe eine neue Klasse geschrieben in Perl, so läuft nun ein Insert über einen gebundenen Hash, dem werden einfach die Werte zugewiesen. In der Klasse (Vermittlungsschicht, 'TieLog') gibt es dazu die Method TIEHASH{} und die Public-Method write{}.

                      Es ist das Erstemal, dass ich in Perl eine Klasse (Moduldatei) schreibe, in der es neben TIEHASH auch Method TIEARRAY gibt und freilich gibt es auch die Method new(). Es ist damit möglich, ein Objekt zu erstellen oder einen Hash oder ein Array zu binden.

                      Tie ist spannend. Mit Tie kannst Du lügen, was das Zeug hält ;)

                      Ein tie(my @array, 'TieLog'); heißt z.B. noch lange nicht, dass in @array die Daten liegen, @array ist nur ein Symbol hinter dem sich die Instanz der Klasse verbirgt, ein Objekt.

                      Erst wenn mit dem @array operiert wird, greifen die Methoden, die dafür zuständig sind. Das @array lässt sich 'füllen' mit einem Abfrageergebnis auf die DB, was da gemacht werden muss wird dem tie() als Parameter mitgegeben (z.B. für die Where-Klause). Wobei: 'gefüllt' mit Daten heißt, das Array liegt als Referenz im Objekt selbst, z.B. in $self->{ARRAY}.

                      Mit dem gebundenen @array ist es dann möglich, eine Callbackfunktion aufzurufen, oder die Daten über eine Array-Referenz abzuholen, auf jeden Fall ist eine wirkungsvolle Fehlerbehandlung auch sehr gut in der Vermittlungsschicht unterzubringen.

                      Schon länger her: Ein Change ist geplant, der Feldtyp in der Logtabelle, bisher unix-Timestamp, soll auf date_time geändert werden. Jetzt haben wir klare Verhältnisse: Im Programmcode muss dazu nichts geändert werden, nur die Klasse 'TieLog' ist dazu anzufassen, alter table und Anpassen der Statements, das ist alles ;)

                      Sorry fürs lange Gerede,
                      Hotti

                      --
                      Nebenbei: Beim Liquidieren von Ameisen entsteht Ameisensäure.
  2. Hello Hotti,

    wenn Du Gehirnschmalz darauf verwenden willst, dann mach Dir auch gleich Gedanken darüber, wohin in diesem Gesamtkunstwerk die Geschäftsregeln, Zugriffsrechte und Historiefunktionen gehören.

    Tabellen können in den üblichen Datenbanksystemen von Haus aus horizontal kontrolliert werden, die vertikale Kontrolle (z.B. welcher User welchen Zeile einer Tabelle sehen, ändern, löschen darf) hängt aber i.d.R. vom Anwendungsfall ab. Aber trotzdem kann man auch diese Dinge im DBMS unterbringen.

    In der Praxis wäre es außerdem schön, wenn Appliaktionen auf Veränderung der Datendefinitionen reagieren könnten, also automatisch realisieren, ob diese noch zur Applikation passen, oder nicht.

    Wo willst Du das unterbringen?

    Liebe Grüße aus dem schönen Oberharz

    Tom vom Berg

    --
     ☻_
    /▌
    / \ Nur selber lernen macht schlau
    http://bergpost.annerschbarrich.de
    1. Hello,

      wenn Du Gehirnschmalz darauf verwenden willst, dann mach Dir auch gleich Gedanken darüber, wohin in diesem Gesamtkunstwerk die Geschäftsregeln, Zugriffsrechte und Historiefunktionen gehören.

      in AL

      In der Praxis wäre es außerdem schön, wenn Appliaktionen auf Veränderung der Datendefinitionen reagieren könnten, also automatisch realisieren, ob diese noch zur Applikation passen, oder nicht.

      Wo willst Du das unterbringen?

      Im AL wird auf eine entsprechende Datenstruktur zugegriffen. Das ist unabhängig von das was Du "Datendefinition" nennst. Veränderungen in der Datenhaltungsschicht (DAL) wie z.B. alter table usw. erfordern keinen Eingriff in die Anwendung, solange die Datenstruktur nicht geändert werden muss. Änderungen sind nur in der Vermittlungsschicht notwendig. Die Trennung DAL?AL ermöglicht es, die Datenhaltung bei Bedarf von 'DB' auf 'Datei' umzustellen, ohne dass der Code in AL geändert werden muss, es wird nur die Vermittlungsschickt ausgetauscht, in welcher die Bindung der Datenstrukturen an DAL erfolgt.

      Beispiel in Perl (in AL, main-Script):

        
      # Binde einen hash (Datenstruktur) an die Klasse der Vermittlungsschicht  
      # Klasse TieLog vermittelt zu MySQL, Logtabelle  
      tie my %log, 'TieLog' or die $@;  
        
      # Füge einen neuen Eintrag in die Logtabelle ein  
      %log = (url => '/', ts => time, ref => 'referrer', hugo => 'Hugo');  
        
      # Änderungen sichern  
      untie %log;  
      
      

      Keinerlei SQL-Statements in main(), die liegen alle in der Klasse 'TieLog'.

      Noch ein Beispiel, weil es so schön geht ;)

        
      tie (my @dummy, 'TieLog', { url => '/apps', callback => \&cb_array}) || die "Fehler: $@";  
      print "============= Daten kommen ==============\n\n";  
      tied(@dummy)->callback;  
      print "\n============ Ende der Ausgabe ===========\n";  
      
      

      Dahinter verbirgt sich ein Select mit Where auf url. Natürlich muss es das sein, was in der main() wirklich gebraucht wird. So funktioniert der Zugriff auf die Benutzer auch über eine Datenstruktur. Die ist mittels tie() derzeit an eine Datei (DAL) gebunden, kann jedoch mit nur einer Zeile-Änderung (andere Tie-Klasse) auch an MySQL gebunden werden.

      Hotti

      1. Hello,

        wenn Du Gehirnschmalz darauf verwenden willst, dann mach Dir auch gleich Gedanken darüber, wohin in diesem Gesamtkunstwerk die Geschäftsregeln, Zugriffsrechte und Historiefunktionen gehören.

        in AL

        In der Praxis wäre es außerdem schön, wenn Appliaktionen auf Veränderung der Datendefinitionen reagieren könnten, also automatisch realisieren, ob diese noch zur Applikation passen, oder nicht.

        Wo willst Du das unterbringen?

        Im AL wird auf eine entsprechende Datenstruktur zugegriffen. Das ist unabhängig von das was Du "Datendefinition" nennst. Veränderungen in der Datenhaltungsschicht (DAL) wie z.B. alter table usw. erfordern keinen Eingriff in die Anwendung, solange die Datenstruktur nicht geändert werden muss.

        Genau, denn es wird in allen möglichen Anleitungen immer nur "vorwärts" gedacht. Im Zeitalter verteilter und gemeinsamer Datenhaltungen muss es aber auch möglich sein, Änderungen zu erkennen, wenn sie in einer anderen Schicht (vielleicht für eine andere Applikation) durchgeführt wurden.

        Änderungen sind nur in der Vermittlungsschicht notwendig.

        Diese muss aber ertüchtigt werden, notwendige Änderungen zu erkennen.

        Liebe Grüße aus dem schönen Oberharz

        Tom vom Berg

        --
         ☻_
        /▌
        / \ Nur selber lernen macht schlau
        http://bergpost.annerschbarrich.de
        1. hi,

          Änderungen sind nur in der Vermittlungsschicht notwendig.

          Diese muss aber ertüchtigt werden, notwendige Änderungen zu erkennen.

          Ja. Ich denke da in erster Linie an eine zweckmäßige Fehlerbehandlung, die mindestens erkennen sollte, ob der Stecker zum SQL-Server gezogen wurde ;)

          Oder meinst Du administrative Änderungen? Drop table Customers; Im produktiven Umfeld wäre das ein Change mit vielen Beteiligten und auch der Vorstand sollte davon wissen ;)

          Hotti

          1. Hello,

            Oder meinst Du administrative Änderungen? Drop table Customers; Im produktiven Umfeld wäre das ein Change mit vielen Beteiligten und auch der Vorstand sollte davon wissen ;)

            Wessen Vorstand?
            Ich sprach von der wolkigen Zukunft mit verteilter und gemeinsamer Datenhaltung.
            Alles, was Du speicherst, steht auch dem Finanzamt, dem Schäuble, der Arge, dem NSA und CIA, den Überbleibseln der Stasi usw. zur Verfügung. Ich dachte, du wolltest endlich mal eine intelligente Lösung für diese ganzen Hanseln entwickeln. :-P

            Liebe Grüße aus dem schönen Oberharz

            Tom vom Berg

            --
             ☻_
            /▌
            / \ Nur selber lernen macht schlau
            http://bergpost.annerschbarrich.de
            1. Alles, was Du speicherst, steht auch dem Finanzamt, dem Schäuble, der Arge, dem NSA und CIA, den Überbleibseln der Stasi usw. zur Verfügung. Ich dachte, du wolltest endlich mal eine intelligente Lösung für diese ganzen Hanseln entwickeln. :-P

              Das löst sich von selbst