Andreas Korthaus: Modular programmieren

Hallöchen zusammen!

Bin gespannt wer zu noch so später Stunde zu dieser für solche Zwecke unmöglichen Zeit noch den ein oder anderen Tip parat hat :)

Also - ich überlege mir gerade, wie ich am besten - ich nenne das jetzt mal so, evtl trifft es nicht ganz die genaue Bedeutung - modular programmiere. Was ich damit meine ist Teile eines Programms austauschen und unabhängig von anderen Teilen programmieren zu können und evtl auch an anderer Stelle direkt einsetzten zu können, ohne dass da noch groß Arbeit für notwendig wird, das in ein bestehendes Script einzumodeln.

Ich habe zur Zeit das Problem(beziehe mich hier auf PHP), dass ich zwar immer Scripte als Grundlage nehme, aber die dann immer etwas verbessere, wieder umschreibe... nur ein paar Funktionen habe ich bis jetzt "exportiert". Leider weiß ich aber gar nicht, wie ich das anfassen soll, halt ein PHP-Programm in selbständige Module aufzuteilen. Aber es gibt doch diese ganzen PHP-Projekte(Foren,Groupware,Portale...) die müssen doch mehr oder weniger so programmiert werden, überhaupt damit da mehrere Leute vernünftig dran arbeiten können. Soweit ich weiß verwenden die alle ein CVS(Current Version System - wenn ich nicht irre), aber das ist mir erstmal etwas übertrieben und ändert doch nichts an meiner Grundproblematik, oder?

Was ich erreichen will ist dass ich Programmteile eines PHP-Projektes austauschen, überarbeiten... kann, ohne das irgendwas großartig schief gehen kann, wenn ich zur Zeit machmal irgendwo was ändere, geht erstmal gar nix mehr, bis der Fehler gefunden ist! Außerdem möchte ich diese Module auch in anderen Projekten verwenden können. Mir geht es jetzt nicht um spezielle Scripte, sondern nur um die Technik im allgemeinen - wie macht man sowas am besten? Was gibt es für Tipps oder lesenswerte Tutorials?

Wer hatte nochmal so viel Spaß an PROGRAMMIERTECHNIK :)) ?

Viele Grüße
  Andreas

  1. Hi Andreas,

    Mir geht es jetzt nicht um spezielle Scripte, sondern nur
    um die Technik im allgemeinen - wie macht man sowas am besten?

    mein Zauberwort dafür lautet "dünne Kanten" zwischen den Code-Segmenten - also minimale Abhängigkeiten.

    • Überlege Dir, welche Informationen thematisch zusammen gehören.
    • Vermeide, daß ein Code-Abschnitt Wissen aus anderen als den ihm
        "zustehenden" Quellen bezieht.

    Ich modelliere immer zuerst die Datentypen und danach erst die Code-Strukturen.
    Dabei versuche ich, Wissen so gut wie möglich einer "zuständigen Instanz" zu geben, an welche sich alle "Bezieher" dieses Wissens zu wenden haben - ich entwerfe also im Prinzip APIs, aber auf einer von konkreten Sprachen noch völlig unabhängigen Ebene.
    Im Prinzip versuche ich, ungefähr objektorientiert zu denken, ohne mich aber zum Sklaven einer konkreten Implementierung machen zu wollen.

    Voraussetzung dafür ist eine hohe Disziplin.
    Es ist verlockend, Informationen "durch die Hintertür" weiterzugeben - es spart oftmals Quelltext-Zeilen, wenn man globale Variablen verwendet, auf das Environment zugreift, das Windows-Clipboard oder die Registry oder gemeinsame Dateien nutzt. Alle diese Mechanismen unterlaufen jedoch das Prinzip der Informationstrennung - diese aber ist m. E. Voraussetzung dafür, ein Modul so stabil und zuverlässig schreiben zu können (weil ihm niemand mehr ins Handwerk pfuschen kann), daß es sinnvoll wiederverwertbar ist.
    Dazu gehört natürlich auch, daß sich das Modul gegen Eingriffe von außen zur Wehr setzt - also aussschließlich über den "legalen" Zugriffsweg die geleisteten Dienste abzurufen erlaubt und Eingriffe an der "hohlen Gasse" vorbei unterbindet.

    Das alles kostet etwas. Einerseits erlauben die mir bekannten Programmiersprachen nicht, Verstöße gegen "sauberen Programmierstil" automatisch zu unterbinden - vor allem C und Perl gehen gnadenlos den Weg "der Programmierer wird schon wissen, was er sich dabei gedacht hat".

    Andererseits sind gerade bei kleinen Programmen die quickhacks mit globalen Variablen und ohne Funktionen oftmals wirklich schneller geschrieben als ein beliebig sauberer, strukturierter Entwurf. Ich denke, es gibt da keinen Königsweg. Das einzige, was hilft, ist Erfahrung - und ein Gefühl dafür, ob man eine konkrete Lösung irgendwann später nochmal brauchen wird.

    Es ist auch irgendwie eine Frage der kritischen Masse - ich fange oft ein Skript in einer einzigen Datei an und zerlege diese erst dann in Module, wenn ich andernfalls den Überblick verliere.
    Das läßt sich aber weder an der Zahl der Funktionen noch an der Zahl der Codezeilen festmachen - es ist eher eine Frage der Zahl der verschiedenen Aspekte der Aufgabenstellung, die das Programm zu erledigen hat, also der "intellektuellen Komplexität" des Programms. Und die kann wiederum sehr stark von der verwendeten Programmiersprache abhängen, weil die verschiedenen Sprachen unterschiedlich mächtige Elementarbefehle besitzen oder gar beliebig mächtige Funktionen in Form externer Bibliotheken zur Verfügung stellen können ... wenn ich dasselbe Problem in Perl und in Assembler zu lösen habe, muß ich bei Assembler viel gründlicher modularisieren.

    Was ich selbst also anstrebe, ist
    a) ein Bewußtsein dafür, wie es "richtig" geht und
    b) ein Gefühl dafür, wo die kritische Masse erreicht ist,
       ab der sich "Pfuschen" nicht mehr lohnt.

    Dabei ist die modulare Zerlegung etwas, das ich sehr viel später brauche als beispielsweise eine detaillierte Dokumentation des Qzelltextes - die brauche ich schon bei 20 Zeilen.
    Das wiederum liegt an der Vielzahl von Sprachen, die ich verwenden muß. Für jemanden, der ausschließlich in seinern Leib- und Magensprache programmiert, mag ein 1000-Zeilen-Quelltext mit sprechenden Variablennamen noch selbsterklärend sein. Für mich ist er das definitiv nicht - vor allem deshalb nicht, weil er mir nicht erklärt, warum das Programm bestimmte Dinge _nicht_ tut - beispielsweise, weil es eine Entscheidung dagegen gibt, weil es im verlangten Kontext nicht funktioniert, weil Performance-Gründe dagegen sprechen usw.; das alles versuche ich durch Kommentare im Quelltext (oftmals einfach durch Auskommentieren des gesamten Code-Abschnitts mit entsprechender Begründung) zu beschreiben.

    Was für modulare Programmierung ebenfalls notwendig ist, das ist Vertrauen in die Qualität der Implementierung. Du mußt wirklich das Selbstbewußtsein haben, ein Problem als "gelöst" zu klassifizieren - es kann sicherlich vorkommen, daß eine Bibliothek bugs hat, aber es sollte eben selten sein.
    Also keine Schönwetterprogrammierung, sondern gnadenlos _alles_ abfragen - und auch die "this can't happen: ..."-Meldungen nach dem Abfragen irgendwelcher API-Returncodes, bei denen "eigentlich" nichts schiefgehen kann. Wer immer einen Returncode zurückliefert, hat sich dabei normalerweise etwas gedacht, und es steht einem "seriösen" Modul nicht zu, diese Entscheidung in Frage zu stellen. Den täte es das, wäre seine Qualität schlechter als diejenige der von _ihm_ verwendeten Module ...

    Auch DEBUG-Code lasse ich mehr und mehr im Modul drin und mache ihn von Modul-globalen Konstanten abhängig (manchmal sogar von einem CGI-Parameter) - solange ich mir das in Sachen Performance leisten kann.

    Das war jetzt alles ein bißchen über Dein Thema hinaus geschossen - aber ich finde es schwierig, die einzelnen Aspekte von "Programmierstil" voneinander zu trennen.
    Modulare Programmierung alleine ist halt auch kein Allheilmittel - bloß eine gute Idee. Umsetzen mußt Du sie aber immer wieder auf's Neue.

    Viele Grüße
          Michael

    1. Hi Michael!
      Erstmal vielen Dank für die ausführliche und sehr interessante Antwort! Aber wie Du richtig sagst bist Du leicht über das Ziel hinaus geschossen, denn ich kann nicht unbedingt behaupten, dass ich das alles kpl. verstanden habe und alles verinnerlichen konnte :-)
      Aber ich hab es jetzt ein paar mal gelesen und mir die wichtigsten Punkte rausgesucht. Das werde ich dann sehr wohl in meine zukünftigen Überlegungen mit einbeziehen, aber ich werde es auch noch mal extra speichern, dass ich es evtl später nochmal lesen kann, wenn mein Horizont evtl etwas weiter ist ;-)
      Jedenfalls nochmal vielen Dank,

      viele Grüße
        Andreas

  2. Hi Andreas Korthaus ;-),

    Wer hatte nochmal so viel Spaß an PROGRAMMIERTECHNIK :)) ?

    obwohl ich Michaels Posting für hochinteressant und wertvoll halte, hier vielleich noch ein etwas einfacherer Ansatz:

    Modular programmieren heisst für mich meistens, eine eigene Klasse mit einem Satz thematisch zusammenhängender Funktionen zu erzeugen, die völlig unabhängig von globalen Variablen, Environment und anderen Daten ist (hat ja Michael schon geschrieben).

    Dazu bedient sich die Klasse eines eigenen API (Application Programming Interface). Über diese Schnittstelle "kommuniziert" das Programm mit der Klasse (eigentlich dem instantiierten Objekt) ausschliesslich! Damit ist es möglich, z.B. den Quellcode der Klasse völlig neu zu schreiben, wenn dabei das API beibehalten wird.

    Das ist dann wie eine Aufgabenverteilung. Das Programm besorgt die Daten, die es braucht um das Objekt über das API zu füttern. Die Klassenroutinen übernehmen die Verarbeitung dieser Daten und geben das Ergebnis über das API wieder zurück an das Programm.

    Viele Grüsse
    Achim (der hofft, dass das wenigstens ein bisschen verständlich ist, weil bei ihm klappt das modulare Programmieren bestens :-)

    1. Hi!

      Modular programmieren heisst für mich meistens, eine eigene Klasse mit einem Satz thematisch zusammenhängender Funktionen zu erzeugen, die völlig unabhängig von globalen Variablen, Environment und anderen Daten ist (hat ja Michael schon geschrieben).

      Mit Klassen verstehe ich aber nicht wirklich. Ich hab mal was allgemeines dazu in einem C Tutorial gelesen(und nur das:), Wenn ich mich Recht entsinne war das so allgemeines Geschwafel von die Klasse ist "Das Fahrrad", und die Funktionen in der Klasse sind z.B. "der Lenker", "die Bremse"...
      Mit Funktionen komme ich in PHP inzwischen ganz gut klar, benutze die viel. Man übergibt dieser Funktion halt die Variablen, und bekommt dafür irgendwas zurück. So weit so gut, die kann man dann ja ruhig mehrfach verwenden.
      Aber wo ich noch nicht so ganz hintergestiegen bin, ist wofür und wie ich jetzt Klassen verwende!? Was ist der Unterschied einer Klasse zu einer Datei mit gesammelten zusammen-gehörigen Funktionen?
      Und wie verwende ich Klassen in PHP? Ich habe zwar http://www.dynamic-webpages.de/php/language.oop.php gelesen, aber denn tieferen Sinn dahinter nicht wirklich begriffen. Ich verstehe cinfach nicht was man von einer Klasse hat?

      Dazu bedient sich die Klasse eines eigenen API (Application Programming Interface). Über diese Schnittstelle "kommuniziert" das Programm mit der Klasse (eigentlich dem instantiierten Objekt) ausschliesslich! Damit ist es möglich, z.B. den Quellcode der Klasse völlig neu zu schreiben, wenn dabei das API beibehalten wird.

      gilt das auch für PHP?

      Das ist dann wie eine Aufgabenverteilung. Das Programm besorgt die Daten, die es braucht um das Objekt über das API zu füttern. Die Klassenroutinen übernehmen die Verarbeitung dieser Daten und geben das Ergebnis über das API wieder zurück an das Programm.

      das auch?

      Achim (der hofft, dass das wenigstens ein bisschen verständlich ist, weil bei ihm klappt das modulare Programmieren bestens :-)

      Ja, in der Tat etwas einfacher für einen Nicht-richtigen-Programmier:)

      Grüße
        Andreas

      1. Hoi,

        Modular programmieren heisst für mich meistens, eine eigene Klasse mit
        einem Satz thematisch zusammenhängender Funktionen zu erzeugen, die
        völlig unabhängig von globalen Variablen, Environment und anderen Daten
        ist (hat ja Michael schon geschrieben).

        Mit Klassen verstehe ich aber nicht wirklich. Ich hab mal was allgemeines
        dazu in einem C Tutorial gelesen(und nur das:),

        Ueber Klassen? Das glaube ich nicht ;-) Hoechstens ueber Objekt-Orientierte
        Programmierung. Oder es war nicht C, sondern C++

        Mit Funktionen komme ich in PHP inzwischen ganz gut klar, benutze die viel.
        Man übergibt dieser Funktion halt die Variablen, und bekommt dafür irgendwas
        zurück. So weit so gut, die kann man dann ja ruhig mehrfach verwenden.

        Richtig.

        Aber wo ich noch nicht so ganz hintergestiegen bin, ist wofür und wie ich
        jetzt Klassen verwende!? Was ist der Unterschied einer Klasse zu einer
        Datei mit gesammelten zusammen-gehörigen Funktionen?

        Klassen sind der Versuch, die Realitaet nachzubilden (wohlgemerkt: ich sage,
        der Versuch ;-). Sie bilden eine Einheit: sie beinhalten ihre eigenen Daten
        und ihre eigenen Funktionen, sie bilden eine eigene Einheit. Sogesehen bildet
        also ein Modul durchaus eine eigene Klasse.
        Objekt-Orientierung ist nicht abhaengig von der Implementierung, es ist eine
        Betrachtungs-Weise und ein Programmier-Stil. Wenn du dich mit in Module
        ausgelagerten Funktionen wohler fuehlst, dann bitte sehr, benutze sie.
        Letztenendes ist es egal, ob du Klassen oder Module benutzt, solange die API
        sauber definiert ist.

        Und wie verwende ich Klassen in PHP? Ich habe zwar
        http://www.dynamic-webpages.de/php/language.oop.php gelesen,
        aber denn tieferen Sinn dahinter nicht wirklich begriffen. Ich verstehe
        cinfach nicht was man von einer Klasse hat?

        Nun, Klassen sind nur eine Notierungs-Art. Sie ist IMHO uebersichtlicher als
        andere Schreibweisen und verfuehrt nicht dazu, *noch* eine Funktion
        reinzupacken und *noch* eine Funktion und das ganze so zu ueberladen und
        unterstuetzt so IMHO eine saubere Trennung.

        Dazu bedient sich die Klasse eines eigenen API (Application Programming
        Interface). Über diese Schnittstelle "kommuniziert" das Programm mit der
        Klasse (eigentlich dem instantiierten Objekt) ausschliesslich! Damit ist
        es möglich, z.B. den Quellcode der Klasse völlig neu zu schreiben, wenn
        dabei das API beibehalten wird.
        gilt das auch für PHP?

        Das ist (fast) Sprachen-Unabhaengig ;-)

        Das ist dann wie eine Aufgabenverteilung. Das Programm besorgt die
        Daten, die es braucht um das Objekt über das API zu füttern. Die
        Klassenroutinen übernehmen die Verarbeitung dieser Daten und geben das
        Ergebnis über das API wieder zurück an das Programm.
        das auch?

        Das ist auch (fast) Sprachen-Unabhaengig.

        Gruesse aus dem schoenen LH,
         c.j.k

        1. Hallo!

          Oder es war nicht C, sondern C++

          Ach ja :)

          Klassen sind der Versuch, die Realitaet nachzubilden (wohlgemerkt: ich sage,
          der Versuch ;-). Sie bilden eine Einheit: sie beinhalten ihre eigenen Daten
          und ihre eigenen Funktionen, sie bilden eine eigene Einheit. Sogesehen bildet
          also ein Modul durchaus eine eigene Klasse.
          Objekt-Orientierung ist nicht abhaengig von der Implementierung, es ist eine
          Betrachtungs-Weise und ein Programmier-Stil. Wenn du dich mit in Module
          ausgelagerten Funktionen wohler fuehlst, dann bitte sehr, benutze sie.
          Letztenendes ist es egal, ob du Klassen oder Module benutzt, solange die API
          sauber definiert ist.

          Ja super, aber was denn jetzt für eine API???? Wo zwischen? zwischen Klasse und Script? Also ich denke ich schreibe eine Klasse (mit PHP) in eine extra Datei, z.B. Klassenname.class
          Dann binde ich diese Datei per include() in ein Script ein und kann die Klasse verwenden. Aber was hat das jetzt mit APIs zu tun?

          Nun, Klassen sind nur eine Notierungs-Art. Sie ist IMHO uebersichtlicher als
          andere Schreibweisen und verfuehrt nicht dazu, *noch* eine Funktion
          reinzupacken und *noch* eine Funktion und das ganze so zu ueberladen und
          unterstuetzt so IMHO eine saubere Trennung.

          Gut, unter http://www.dynamic-webpages.de/php/language.oop.php war da ja ein Beispiel für PHP, ganz einfach, eine Klasse "Einkaufswagen", in der verschiedene Funktionen und Variablen stehen, die man dann in dem Script abfragen und ändern kann. Nur was bringt mir das praktisch? Ich verwende zur Zeit immer Funktionen direkt und z.B. MySQL um irgendwelche Daten zu speichern, da behalte ich die wenigstrens, in der Klasse sind die Informationen am Ende des Scriptes doch weg, oder? Zur Zeit finde ich einfach keinen Vorteil zu Funktionen außer dass man das etwas übersichtlicher hat. Aber auch das könnte man ja mit Dateien genau so machen. Irgendwie ist der Groschen da noch nicht gefallen. An dem Beispiel des Links denke ich die ganze Zeit, mit Sessions oder DB wäre das doch viel besser gemacht!?

          Viele Grüße
            Andreas

          PS: Ist der Thread bei Dir auch so durcheinander???

          1. Hi,

            Ja super, aber was denn jetzt für eine API???? Wo zwischen? zwischen Klasse und Script? Also ich denke ich schreibe eine Klasse (mit PHP) in eine extra Datei, z.B. Klassenname.class

            der Dateiname nebst Endung spielt bei PHP keine Rolle. Du kannst auch mehrere Klassen in einer einzigen Datei definieren.

            Dann binde ich diese Datei per include() in ein Script ein und kann die Klasse verwenden. Aber was hat das jetzt mit APIs zu tun?

            Ein API ist nichts weiter als Deine (bzw. des Programmierers) Definition, welche Daten an eine Funktion (oder bei Klassen: Methode) übergeben werden und in welcher Art das Ergebnis zurückgeliefert wird. Sozusagen hat jede Funktion, die ein Argument annimmt und z.B. einen String zurückgibt ein eigenes API.

            Es stimmt, dass für modulares Programmieren (um beim Thema zu bleiben) nicht zwingend Klassen erforderlich sind. Aber gerade in PHP kannst Du damit für bestimmte Funktionen eigene Datenbereiche reservieren innerhalb derer Deine Funktionen agieren können. Das ist ein grosser Vorteil, wenn z.B. mehrere Funktionsbibliotheken in einem einzigen Skript verwendet werden sollen, da sich die Bibliotheken nicht in die Quere kommen mit z.B. gleichlautenden globalen Variablen. Mal ein Beispiel: Du schreibst eine Klasse, die ein HTML-Textfeld ausgeben soll (Klassenname: htmltext). Innerhalb dieser Klasse gibt es einige Methoden (Funktionen), die bestimmte Eigenschaften des Textfeldes verändern. Zum Beispiel eine Methode size(), die eben das Attribut für die Grösse setzt. Weiterhin enthält die Klasse Eigenschaften (also Variablen), in denen diese Eigenschaften gespeichert werden. Hier z.B. $size. Ausserdem gibt es eine Methode, die das HTML entsprechend den vorgenommenen Einstellungen als String zurückgibt (z.B. eine output()-Methode).

            Das API (in Deinem Kopf) sieht vor, dass ein Programmierer, der die Funktionen Deiner Klasse nutzen will, etwa folgenden Code schreiben muss:

            $myobj = new htmltext();
            $myobj -> size(35);
            echo $myobj -> output();

            Wenn Du den Code Deiner Klasse nun umschreiben willst, z.B. weil sich die HTML-Standards geändert haben, dann musst Du nur beachten, dass es bereits Skripten gibt, die in der obigen Form (also gemäss Deines API) die Funktionen der Klasse nutzen. Anonsten bist Du völlig frei in der Gestaltung deines Codes.

            Gut, unter http://www.dynamic-webpages.de/php/language.oop.php war da ja ein Beispiel für PHP, ganz einfach, eine Klasse "Einkaufswagen", in der verschiedene Funktionen und Variablen stehen, die man dann in dem Script abfragen und ändern kann. Nur was bringt mir das praktisch? Ich verwende zur Zeit immer Funktionen direkt und z.B. MySQL um irgendwelche Daten zu speichern, da behalte ich die wenigstrens, in der Klasse sind die Informationen am Ende des Scriptes doch weg, oder? Zur Zeit finde ich einfach keinen Vorteil zu Funktionen außer dass man das etwas übersichtlicher hat. Aber auch das könnte man ja mit Dateien genau so machen. Irgendwie ist der Groschen da noch nicht gefallen. An dem Beispiel des Links denke ich die ganze Zeit, mit Sessions oder DB wäre das doch viel besser gemacht!?

            Da sieht man mal wieder wie irreführend jedes noch so gut gemeinte Beispiel sein kann ;-) Die Klasse Einkaufswagen behält die Daten selbstverständlich nur für die Dauer der Skriptausführung, aber sie könnte ja z.B. erweitert werden um Sessionhandling und MySQL-speicherung. In dem Beispiel geht es nur darum, die grundsätzliche Funktion von Klassen aufzuzeigen.

            Der Vorteil von Klassen ist nicht nur die Übersicht, sondern der völlig eigene Datenbereich der Objekte, die auf der Klasse basieren. Ein neues Objekt wird mit

            $myobject = new yourclass();

            erzeugt. In einem Skript kannst Du zig Objekte der selben Klasse erzeugen, und alle sind völlig unabhängig voneinander. Jedes Objekt (also jeder Einkaufswagen) enthält seine eigenen Daten und die dazugehörigen Funktion, um die Daten zu bearbeiten. Das geht mit in Dateien ausgelagerten Funktionen nicht so leicht (eigentlich gar nicht).

            Ich denke, das ist vielleicht ein bisschen viel auf einmal für Dich, deshalb würde mich eigentlich interessieren, was Du eigentlich konkret "modular" programmieren willst, damit ich mir das besser vorstellen kann, was Du vorhast.

            Viele Grüsse
            Achim

            1. Hallo!

              der Dateiname nebst Endung spielt bei PHP keine Rolle. Du kannst auch mehrere Klassen in einer einzigen Datei definieren.

              Ja, richtig. Ich dachte nur halt von wegen modular programmieren, hab ja nix davon, wenn ich das alles immer wieder in die einzelenn Dateien packe.

              Ein API ist nichts weiter als Deine (bzw. des Programmierers) Definition, welche Daten an eine Funktion (oder bei Klassen: Methode) übergeben werden und in welcher Art das Ergebnis zurückgeliefert wird. Sozusagen hat jede Funktion, die ein Argument annimmt und z.B. einen String zurückgibt ein eigenes API.

              OK. Denke bei API immer an komplexe Schnittstellen zwischen 2 Programmen!

              Ich denke, das ist vielleicht ein bisschen viel auf einmal für Dich, deshalb würde mich eigentlich interessieren, was Du eigentlich konkret "modular" programmieren willst, damit ich mir das besser vorstellen kann, was Du vorhast.

              Ja, genau richtig, ist wie schon beschrieben ein sehr abstraktes Thema, und das Problem ist, das ich es eigentlich falsch mache, ich will Klassen verstehen, um zu gucken, wo ich die einsetzen kann, und habe kein echtes Problem wofür ich eine Lösung suche.

              Meine Motivation war folgende, und zwar habe ich ja mal einen Online-Shop mit Warenkorb, CMS... geschrieben(alles in PHP), da war ich super-happy als der lief, gedacht so, die Arbeit mußt Du Dir jetzt nicht mehr machen, enfach die Scripte nur noch ändern. Na - denkste! Das war so umständlich geschrieben, dass es schneller gegangen wäre, das kpl. neu zu schreiben. Also hab ich es so gut wie neu gemacht, aber diesmal für immer - wieder falsch! Immer wenn ich einen neuen Shop gemacht habe, kam es mir einfacher vor, einen neuen zu schreiben(vor allem da ich in der Zwischenzeit einiges dazu gelernt hatte!!!) und das jetzt 4 mal hintereinander. Und das kann es ja nicht sein, hab ich mir gedacht. Das muß man doch mal endlich modular hinbekommen, aber leider fand ich so gar keinen Ansatzpunkt hierfür - daher dieser Thread. Dasselbe Problem habe ich auch bei einem anderen projekt, das ich erst anfangen möchte, wenn ich das vernünftig modular machen kann.
              Daher war auch gerade das Bsp. mit dem Einkaufswagen eher verwirrend für mich :-)

              Ich muß gestehen, trotz Eurer guten uns sehr ausführlichen Antworten bin ich immer noch nicht 100%ig dahinter gestiegen, wie ich das z.B. bei einem Online-Shop einsetzten könnte. Wie das mit den Klassen funktioniert, das weiß ich jetzt, aber ich sehe leider immer noch nicht den Vorteil in meiner Anwendung.

              Ich kann ja mal grob(vereinfacht) skizzieren, wie ich das zur Zeit mache:
              Ich habe

              • eine Startseite, wo ich aus Kategorien auswähle,
              • eine Übrsichtsseite, die alle Produkte der ausgewählten Kategorie enthält,
              • eine Produktseite, mit Bestellbutton
              • eine Warenkorbseite
              • und ein Bestellformular.

              Erstmal ist jede Seite ein PHP-Datei und so aufgebaut, dass am Anfang erst ein allgemeines PHP-Script eingebunden wird (inclue()), dann der kpl. HTML-Head-bereich und der  anfang des Body Bereiches, der überall gleich ist, am Ende noch die entspechenden gleichen HTML-Endbereiche, und die Navigationsleiste. Also 4 PHP Scripte

              • global.php
              • header.php
              • footer.php
              • navigation.php
                Diese Scripte werden auf jeder Seite eingebunden, so kann ich das schön zentral ändern. Die global.php enthält dann so Sachen wie die Daten zur MySQL Verbindungsaufnahme, alle Funktionen die oft gebraucht werden(z.B. Daten/Preise umrechnen...) auch direkt ein paar SQL-Abfragen die oft gebraucht werden.
                Alles übrige schreibe ich in die Dateien selbst, oder binde die noch extra ein.
                Das ist jetzt super für den einen Shop, echt bequem, aber beim nächsten mal stehe ich vor dem Problem, dass ich ja nicht unbedingt genau denselben html-Code möchte, da darf ich alle Dateien wieder kpl. ändern, und meist ist da neu wieder einfacher, die include Dateien müssen neu gemacht werden, damit das am Ende wieder so funktoniert, und wenn dann noch die Produkttabelle mehr oder andere Felder braucht kann ich es ja alles vergessen.
                Ich weiß das da jedesmal Arbeit nötig werden wird, aber ich habe das Gefühl, dass ich mir extrem viel Arbeit mache, ich jedesmal die Scripte neu schreibe, und nur Teile reinkopiere. Anders verliere ich total den Überblick.
                Nun, jetzt weiß ich aber nicht, ob und wie mir hier z.B. Klasen oder überhaupt OOP weiterhelfen könnte! Ich würde es nur mal gerne schaffen, dass ich einfach ein Modul(Datei) nehme, und direkt verwenden kann, ohne dass ich sicher gehen kann, das noch ohne Ende Änderungen nötig sein werden. Oder dass ich die Änderungen(also für einen neuen Shop) irgendwie übersichtlicher durchführen kann, als in jede Datei "reinzufriemeln". Bei mir ist ja auch noch nicht der Code richtig vom Inhalt getrennt. Irgendwie müßte ich den HTML-Teil total unabhängig vom Code schreiben können, was mir bisher nicht gelungen ist.

              So, das war jetzt ne ganze Menge, ich hoffe Du verstehst jetzt genauer meine Problematik :)

              Grüße
                Andreas

              1. Hi,

                OK. Denke bei API immer an komplexe Schnittstellen zwischen 2 Programmen!

                kann sein, dass API - also Application Programming Interfache - für eine simple PHP-Klasse oder eine einzelne Funktion etwas übertrieben ist. Ich verwende diese Abkürzung halt oft in meinem Umfeld, wo die Leute wissen was gemeint ist, auch wenn es nicht ganz der eigentlichen Definition entspricht. Sorry, hätte mich auch gleich deutlicher ausdrücken können ;)

                Ich muß gestehen, trotz Eurer guten uns sehr ausführlichen Antworten bin ich immer noch nicht 100%ig dahinter gestiegen, wie ich das z.B. bei einem Online-Shop einsetzten könnte. Wie das mit den Klassen funktioniert, das weiß ich jetzt, aber ich sehe leider immer noch nicht den Vorteil in meiner Anwendung.

                Versuche einmal, Teile der Anwendung (also des kompletten Shops) gedanklich zu trennen und in Module (Klassen) zusammenzufassen. Eine Gesamt-Klasse "shop" wird Dich sicherlich nicht weiterbringen, aber mehrere kleine und übersichtliche Klassen wie z.B. "shop_datenbank", "shop_html" und "shop_statistik" schon eher. Und bedenke: modular programmieren heisst nicht zwingend OOP zu machen! OOP hilft nur dabei. Du kannst Deine Shop-Module sehr wohl auch in ganz normale Funktionen packen. Dabei ist aber sehr viel Programmierdisziplin nötig, damit die einzelnen "Module" gut miteinander zusammenarbeiten.

                In Deinem Fall würde ich mir eine Art Shop-Baukasten zusammenschrauben. Darunter stelle ich mir einen kleinen Satz Klassen vor, die getrennt Datenbankoperationen, HTML-Ausgabe etc. übernehmen. Für jeden neuen Shop müssten dann nur die Hauptdateien neu geschrieben werden, die z.B. mit Hilfe des Datenbankmoduls ein Produkt in den Warenkorb legen und danach den aktuellen Warenkorb mit Hilfe des DB-Moduls auslesen und mittels HTML-Modul anzeigen. Die beiden Module könnten sich dann über eine definierte Schnittstelle (API ;-), also meinetwegen ein Hash-Array mit der Produktliste, "unterhalten".

                Bei mir ist ja auch noch nicht der Code richtig vom Inhalt getrennt. Irgendwie müßte ich den HTML-Teil total unabhängig vom Code schreiben können, was mir bisher nicht gelungen ist.

                Dafür könntest Du freilich Templates verwenden. Klar, wenn Du z.B. Produktlisten oder Warenkorbseiten mit jeder Menge dynamischem Inhalt erzeugen möchtest, wird der Einsatz von Templates nicht gerade einfacher. Ich behelfe mir da immer mit "Sub-Templates" (meine Wortschöpfung). Damit meine ich z.B. eine Vorlage für eine einzelne Tabellenzeile, die einfach Platzhalter enthält. Im Skript gebe ich nie HTML direkt aus, sondern bediene mich der Vorlage, ersetze die Platzhalter durch Inhalte und gebe das Ergebnis aus. Meistens habe ich am Ende eines Projektes immer einen Satz von Seitentemplates und einen Satz kleinerer "Sub-Templates", die das Aussehen bestimmter dynamischer Elemente bestimmen.

                Natürlich muss dieser ganze Aufwand im Einklang mit der Performance der Anwendung stehen. Es macht keinen Sinn ein superuniverselles Shopsystem zu haben, das vor lauter Anpassparkeit nur auf Seiten < 10 Besucher/Tag einsetzbar ist. Hier gilt es auch Kompromisse zu finden.

                So, das war jetzt ne ganze Menge, ich hoffe Du verstehst jetzt genauer meine Problematik :)

                Das tue ich, aber wahrscheinlich ist das ganze im RL oder im Chat leichter auszudiskutieren ;-)

                Viele Grüsse
                Achim Schrepfer

          2. Moin,

            »»Also ich denke ich schreibe eine Klasse (mit PHP) in eine extra Datei, z.B. Klassenname.class

            Dann binde ich diese Datei per include() in ein Script ein und kann die Klasse verwenden. Aber was hat das jetzt mit APIs zu tun?

            Naja, Extradateien haben mit Klassen genau gar nichts zu tun (und .class ist als Endung äußerst unpraktisch da das zufälligerweise von Java verwendet wird).

            Mal OOP in einer Nußschale:
            Ein Objekt ist eine Ansammlung von Daten und Operationen über diesen Daten. Die Daten nennt man Eigenschaften, die Operationen nennt man Methoden.
            Die Eigenschaften und Methoden sind eigentlich nichts anderes als Variablen und Funktionen wie du sie bisher kennst, bloss das sie halt zu dem Objekt dazu gehören und jedes Objekt seine eigenen Eigenschaften und Methoden haben kann.

            Eine Klasse ist quasi ein Bauplan für ein Objekt. In der Klasse wird festgelegt welche Eigenschaften und Methoden das Objekt haben soll.

            Damit kann man ziemlich tolle Sachen machen. Glaubst du nicht? Pass mal auf: Nehmen wir an wir würden Autos beschreiben wollen (jaja, das Standardbeispiel). Konventionell würdest du dir jetzt ein paar Funktionen schreiben die die Operationen auf den Autos darstellen. Um ein Auto selbst darzustellen würdest du vielleicht ein assoziatives Array (in PHP) oder einen strukturierten Datentyp (in den meisten anderen Programmiersprachen) nehmen:

            function auto_starten($auto)
            { $auto["gestartet"] = true; }

            function auto_stoppen($auto)
            { $auto["gestartet"] = false; }

            function auto_neu()
            { $auto["gestartet"] = false; return $auto;}

            Zwei Sachen fallen auf:
             Ich habe überall "auto_" davorgeschrieben, das wird später auf jedenfall notwendig sein, wenn wir auch noch andere Sachen die man starten oder stoppen kann nachbilden wollen. Damit muss man immer rechnen wenn man schreiben will, was sich wiederverwenden lassen soll.
             Jeder Funktion muss das Auto auf dem sie operieren soll als erster Parameter übergeben werden, anders geht's nicht. Globale Variablen sind bei modularer Programmierung eine Todsünde da sie dazu neigen zu kollidieren.

            So, jetzt machen wir das ganze mal objektorientiert:
            class Auto {
             var $gestartet;
             function Auto()
             { $this->gestartet = false; }
             function starten()
             { $this->gestartet = true; }
             function stoppen()
             { $this->gestartet = false; }
            }

            Was fällt auf:
             Die Funktionen können benannt sein wie sie wollen da Objekte unterschiedlicher Klassen unterschiedliche Funktionen haben und diese nicht miteinander verwechselt werden können.
             Wir müssen das Ding was bearbeitet werden soll nicht mehr mit übergeben, es ist stets in $this verfügbar.
             Eigenschaften und Methoden eines Objektes werden in PHP mit -> angesprochen.

            Mit einem objektorientierten Auto zu arbeiten ist jetzt ganz einfach:
            $auto1 = new Auto(); // Auto erzeugen
            $auto1->starten();   // Auto anlassen

            Vorteile: Der Code in der Klasse ist vollkommen unabhängig von dem Code ausserhalb, sollte er zumindest sein. Wir können jetzt etwa eine Klasse AltesAuto schreiben die nur bei jedem zweiten Mal anspringt (oder so) und müssen dazu nur den Klassennamen, die starten()-Funktion der neuen Klasse sowie die new-Aufrufe ändern anstatt im Prefix jeder Funktion und jedes Aufrufes rumzufummeln.
            Andere Sprachen wie Java haben darüberhinaus noch ganz andere Möglichkeiten was die Zugangsbeschränkungen angeht: Da kann der Programmierer einer Klasse festlegen dass alle anderen Klassen keinen Zugriff auf bestimmte Elemente haben sollen. Das ist wichtig um die bereits von meinen Vorrednern erwähnte konsistente API durchhalten zu können: Wenn jemand von aussen gar nicht erst an bestimmten internen Details (die sich jederzeit ändern können, weil sie eben nicht für den externen Zugriff vorgesehen sind) rumspielen kann, dann kommt er auch nicht in Versuchung das zu tun.

            Etwas ganz wichtiges geht in PHP aber auch noch: Vererbung. Wenn du eine Klasse bauen willst die das gleiche tun soll wie eine bereits existierende Klasse, nur eben ein bisschen anders bzw. erweitert, dann erbst du einfach von dieser Klasse. Deine neue Klasse enthält dann alle Methoden und Eigenschaften der Elternklasse, plus die Teile die du ausgetauscht bzw. verändert hast. Zum Beispiel ein buntes Auto:

            class FarbigesAuto extends Auto {
             var $farbe;
             function anmalen($neuefarbe)
             { $this->farbe = $neuefarbe; }
             function abwaschen()
             { $this->farbe = "nix"; }
             function FarbigesAuto($farbe = "nix")
             { $this->farbe = $farbe; $this->gestartet = false;}
            }

            Zusätzlich zu der Möglichkeit das Auto anzuhalten bzw. zu starten kann man dieses Auto auch noch anmalen. Der Code zum Starten/Stoppen muss aber nicht noch einmal aufgeschrieben werden, und das beste ist: Wenn jemand den Code von dem geerbt wird verändert (verbessert) dann profitiert die erbende Klasse automatisch davon.

            Im Allgemeinen mag ich Objektorientierung sehr, wenn es darum geht viele gleichartige Dinge zu haben oder auch nur vorzusorgen irgendwann mal viele davon haben zu können (Zero-One-Infinity nicht vergessen).

            --
            Henryk Plötz
            Grüße aus Berlin