hotti: Fatal Error abfangen

hi,

s.Thema, spezieller Fehler:
eine Methode ist nicht definiert (Schlamperei *G*).
Bitte mal um Hinweise.

Hotti

--
Das As im Ärmel nützt Dir nichts, wenn es der Gegener ausspielen kann.
  1. Bitte mal um Hinweise.

    ein __call könnte helfen.

    1. Bitte mal um Hinweise.

      ein __call könnte helfen.

      Oh, Mann, und ob das hilft, danke Dir!!!!
      Da hab ich stundenlang an der falschen Stelle gesucht....

      Herzliche Grüße,
      Hotti

      1. hi,

        Da hab ich stundenlang an der falschen Stelle gesucht....

        Offensichtlich besteht in PHP-Kreisen absolut kein Bedarf, Methoden so auszulagern, dass deren Source erst auf Anforderung kompiliert wird. Das waren meine Suchkriterien ;)

        Wozu das Auslagern gut sein kann: Es verringert den Overhead, der beim Kompilieren der Source einer Klasse besteht, insbesondere dann, wenn die Klasse sehr viele Methoden bereitstellt. Beispielsweise gäbe es in einer Klasse 'Shop' die Methode 'order', die erst dann gebraucht wird, wenn der Kunde seine Bestellung absendet. Das Laufzeitverhalten wird verbessert, wenn diese Source nicht bei jedem Klick, den der Kunde tätigt, kompiliert wird.

        Darüber nachzudenken lohnt sich schon bei einer Methode, umsomehr, wenn es mehrere Methoden gibt, die vergleichsweise selten gebraucht werden. Nun denn, ich habe diese Anforderung gestern mit __call() gelöst.

        Es gibt noch einen anderen Grund, darüber nachzudenken, das ist der Overload an sich, Beispiel:

        Klasse Foo hat eine Methode foo(). Klasse Bar erbt von Klasse Foo alle Methoden und in Klasse Bar wird die Methode foo() überschrieben.

        Kompiliert werden die Klassen Foo und Bar und damit alle Methoden der Basisklasse und alle Methoden der Subklasse. Wenn jedoch Foo::foo() ausgelagert ist, wird die nicht kompiliert. Kompiliert wird in diesem Fall nur die in der Subklasse überschriebene Methode.

        Haben eingefleischte PHP-Programmierer dafür eine andere Lösung?

        Hotti

        1. Wozu das Auslagern gut sein kann: Es verringert den Overhead, der beim Kompilieren der Source einer Klasse besteht, insbesondere dann, wenn die Klasse sehr viele Methoden bereitstellt. Beispielsweise gäbe es in einer Klasse 'Shop' die Methode 'order', die erst dann gebraucht wird, wenn der Kunde seine Bestellung absendet. Das Laufzeitverhalten wird verbessert, wenn diese Source nicht bei jedem Klick, den der Kunde tätigt, kompiliert wird.

          Das Laufzeitverhalten wird vor allem verschlechtert, wenn man solche "all in one" skripte schreibt. Und nicht nur das. Du willst erst alles in einem Skript einlagern und dann Teile davon auslagern. Das ist wie als würdest Du im Winter die Straße erst mit Wasser bespritzen (damit es glatt wird) und dann Streusalz darauf streuen (weil es glatt ist). Dann noch eine "all-in-one-Klasse" shop: Ich finde, Du übertreibst absolut maßlos.

          Haben eingefleischte PHP-Programmierer dafür eine andere Lösung?

          Ja. Eine index.php (zeigt den Shop an), eine bestell.php (übernimmt die Bestellung in die Session), eine warenkorb.php ... und niemals "Hier packe ich alles rein-Klassen". Das Konzept mag für monolythische Programme mit einer eigenen Oberfläche gut sein - aber bei PHP, dass dafür gemacht ist nach einem Request auch eine eng umrissene Aufgabe zu erledigen, erscheint mir das höchst unsinnig weil dann durch des Programmierers Wille zwingend aber ohne wirklichen Grund eine ganze Menge nicht benötigter Programmcode geladen wird.

          Ob ein

          if ($bar) {
             include 'foo.php';
          }

          dazu führt, dass foo.php nur bei Bedarf interpretiert wird können Dir andere erklären.

          Was jetzt Dein All-in-One-Konzept betrifft: Es mag schöne Theorien dazu geben. Ich bezweifle aber, dass diese für den Einsatzzweck in einer verteilten Umgebung mit einzelnen Requests anwendbar sind und rate zu mehr Pragmatismus.

          Programme sollen ja nicht nur schnell laufen, sondern auch irgend wann mal fertig werden.

          fred

          1. Moin,

            Haben eingefleischte PHP-Programmierer dafür eine andere Lösung?

            Ja. Eine index.php (zeigt den Shop an), eine bestell.php (übernimmt die Bestellung in die Session), eine warenkorb.php ...

            Ja, Deine Code-Verteilung ist die Physik, das ist völlig in Ordnung. Was dabei fehlt ist die Logik. Sprechende Namen sind nicht alles...

            ... und niemals "Hier packe ich alles rein-Klassen".

            Bringe mehr Logik in Deinen Programmaufbau:
            bestell.php    ist eine Methode
            warenkorb.php  ist eine Methode

            ... das ist die Botschaft!

            Schöne Feiertage,
            Hotti

            1. Bringe mehr Logik in Deinen Programmaufbau:
              bestell.php    ist eine Methode
              warenkorb.php  ist eine Methode

              ... das ist die Botschaft!

              Nö. Das ist Philosophie. Freilich sind es, letztendlich betrachtet, auf den Webshop anzuwendende Methoden. Aber den Webshop als ein Objekt zu realisieren halte ich als alter Pragmatiker bei aller Sympathie für wissenschaftlich korrekte Herangehensweisen für überzogen und sehe eine Menge Nachteile. Man kann das wollen wollen, aber man muss es nicht müssen.

              Fred

        2. Tach!

          Offensichtlich besteht in PHP-Kreisen absolut kein Bedarf, Methoden so auszulagern, dass deren Source erst auf Anforderung kompiliert wird.

          Offensichtlich besteht kein Bedarf daran, die Dinge auch noch in die Richtung zu verkomplizieren. Zudem geht das bereits, indem man in den Rumpf ein require_once schreibt und den Code der Methode (oder auch einer Funktion) dorthin auslagert.

          Wozu das Auslagern gut sein kann: Es verringert den Overhead, der beim Kompilieren der Source einer Klasse besteht, insbesondere dann, wenn die Klasse sehr viele Methoden bereitstellt.

          Hast du das durch Tests nachvollzogen oder ist das einfach nur so ins Blaue hineingeraten?

          Vor einiger Zeit diskutierten einige PHP-Verwender, ob es besser sei, alle verwendeten Code-Dateien mit require_once einzubinden oder einen Autoloader zu schreiben, der erst bei Bedarf die Quelldatei nachlädt. Das Hauptargument war dabei immer der (gesparte) Dateizugriff. Wenn du nun viele Teile auslagerst, kostet das am Ende eventuell sogar mehr als der zusätzliche Parse-Aufwand. Ich hab diese Diskussion nur am Rande verfolgt und Messergebnisse sind mir auch keine in Erinnerung. Inwieweit das also wirklich relevant ist, würde ich erst im Bedarfsfall analysieren wollen. Bis dahin nehme ich den Autoloader aus Bequemlichkeit, weil ich mir dadurch das Pflegen der require_once-Statements spare.

          Klasse Foo hat eine Methode foo(). Klasse Bar erbt von Klasse Foo alle Methoden und in Klasse Bar wird die Methode foo() überschrieben.
          Kompiliert werden die Klassen Foo und Bar und damit alle Methoden der Basisklasse und alle Methoden der Subklasse. Wenn jedoch Foo::foo() ausgelagert ist, wird die nicht kompiliert. Kompiliert wird in diesem Fall nur die in der Subklasse überschriebene Methode.
          Haben eingefleischte PHP-Programmierer dafür eine andere Lösung?

          Ordentliches Klassendesign, anwendungsfallspezifisch. Dazu Autoloader.

          Die große Frage ist aber: Wieviel kostet das Zerhackstücken des Codes an Wartungsaufwand und wieviel Gewinn bekommt man durch diese vermutlich doch nur sehr geringe Optimierung.

          dedlfix.

          1. hi,

            Wozu das Auslagern gut sein kann: Es verringert den Overhead, der beim Kompilieren der Source einer Klasse besteht, insbesondere dann, wenn die Klasse sehr viele Methoden bereitstellt.

            Hast du das durch Tests nachvollzogen oder ist das einfach nur so ins Blaue hineingeraten?

            Der Compile-Overhead ist ein wesentlicher Grund für die Entwicklung von mod_perl. Während im reinen CGI-Betrieb die ganze Source bei jedem Request neu kompiliert werden muss, liegt bei mod_perl der Code im Hauptspeicher, die Sourcen dafür wurden bereits beim Starten des Webservers kompiliert.

            Der AutoLoader von Perl macht genau das, was ich gestern für PHP realisiert habe, nämlich Sourcen von Methoden auf Anforderung kompilieren. Die Einbindung dieses Features ist in Perl bereits seit Jahren möglich und bringt bereits mit der Base-Method AUTOLOAD hervorragende Ergebnisse hinsichtlich Code-Optimierung. In Perl ist die Verzeichnisstruktur außerdem im Default vorgegeben (s. Wartungsaufwand).

            Die große Frage ist aber: Wieviel kostet das Zerhackstücken des Codes an Wartungsaufwand und wieviel Gewinn bekommt man durch diese vermutlich doch nur sehr geringe Optimierung.

            Diese Frage kannst Du ebenso an jeden PHP-Programmierer durchreichen, der seinen Code auf mehrere Dateien verteilt (danke Fred F.).

            Der Wartungsaufwand hängt im Wesentlichen davon ab, wie das Zerstückeln organisiert ist und welche Default-Organisation es dazu gibt, so wird Perls AutoLoader eine Methode, die in der Klasse selbst nicht deklariert ist, standardmäßig in lib/auto/Class suchen. In Perl sind die Entwickler mit 'AutoSplit' sogar noch einen Schritt weiter gegangen, das automatisiert die Installation von Klassen in denen Methoden für den AutoLoader vorgesehen sind.

            Viele Grüße,
            Hotti

            1. Tach!

              Hast du das durch Tests nachvollzogen oder ist das einfach nur so ins Blaue hineingeraten?
              Der Compile-Overhead ist ein wesentlicher Grund für die Entwicklung von mod_perl. [...]
              Der AutoLoader von Perl macht genau das, was ich gestern für PHP realisiert habe, nämlich Sourcen von Methoden auf Anforderung kompilieren. [...]

              Und was bei Perl so ist, muss nun zwingend auch für PHP gelten?

              Um wieviele Zeilen Code geht es denn in deiner einen Methode? Ist sie so riesig, dass die Compile-Zeit signifikant ist? Dann solltest du vielleicht lieber deine Codestrukturierung überdenken. Selbst wenn du diese Methode nun in viele kleine aufteilst, solltest du dich dann immer noch fragen, warum diese Klasse nun immer noch so riesig ist. Speck deine Klasse auf jeweils eine Aufgabe ab, dann werden deine Code-Dateien kleiner und damit auch die Compile-Zeit. Ein Autoloader verhindert, dass immer alle von einer Klasse jemals benötigten anderen Klassen geladen werden, sondern nur die zur Laufzeit tatsächlich benötigten. Wenn dir immer noch die Compile-Zeit zu groß ist, nimm einen OpCode-Cache. - Insgesamt sollte sich durch eine solche auch wartungsfreundliche Strukturierung gar kein Bedarf einer Methoden-Code-Auslagerung mehr ergeben.

              Die große Frage ist aber: Wieviel kostet das Zerhackstücken des Codes an Wartungsaufwand und wieviel Gewinn bekommt man durch diese vermutlich doch nur sehr geringe Optimierung.
              Diese Frage kannst Du ebenso an jeden PHP-Programmierer durchreichen, der seinen Code auf mehrere Dateien verteilt (danke Fred F.).

              Warum sollte ich? Du willst eine Optimierung erreichen, also musst du dir diese Frage stellen. Ich habe sie nur für dich formuliert.

              dedlfix.

              1. Guten morgen;

                Und was bei Perl so ist, muss nun zwingend auch für PHP gelten?

                Selbstverständlich müssen auch PHP-Sourcen kompiliert werden oder was hast du gedacht?

                Hotti

                1. Tach!

                  Und was bei Perl so ist, muss nun zwingend auch für PHP gelten?
                  Selbstverständlich müssen auch PHP-Sourcen kompiliert werden oder was hast du gedacht?

                  Zum einen müssen sie das nicht. Bis PHP 3 wurden sie jedenfalls nicht, erst mit PHP 4 kam ein OpCode-Compiler hinzu. OK, Schwamm drüber. Zum anderen hatte ich nicht an solch eine allgemeine Aussage gedacht, sondern bezog mich auf deinen ausführlicheren Vergleich mit Perl, den du anscheinend 1:1 auf PHP überzustülpen versuchst.

                  Auf die Hauptargumente aber gehst du mal wieder nicht ein.

                  dedlfix.

                  1. hi,

                    Auf die Hauptargumente aber gehst du mal wieder nicht ein.

                    OK. Wenn Du eine ganze Klasse zur Laufzeit hinzunimmst, stehen Dir alle Methoden zu Verfügung, auch Diejenigen, die gar nicht gebraucht werden. Wenn Du jedoch anders herangehst und lädst nur eine Methode nach, kannst Du dabei auch weitere Klassen nachladen, die erst zur Laufzeit kompiliert werden. Es ist nur eine andere Herangehensweise zu einer sinnvollen Codeverteilung und im Grunde genommen ist das alles nüschs Neues ;)

                    Hotti

                    1. Tach!

                      Wenn Du eine ganze Klasse zur Laufzeit hinzunimmst, stehen Dir alle Methoden zu Verfügung, auch Diejenigen, die gar nicht gebraucht werden.

                      Ja, das passiert manchmal. Es gibt auch Code innerhalb einer Methode/Funktion, der aufgrund von Laufzeitbedingungen nicht ausgeführt wird. Wenn du konsequent wärst, müsstest du jeden Funktionsblock einzeln nachladen wollen. Spätestens dann kommst irgendwann an einen Punkt, da kosten die die I/O-Operationen mehr als der Compile-Vorgang. Den Wartungsaufwand hast du damit aber schon weit vorher in die Höhe getrieben.

                      Wenn Du jedoch anders herangehst und lädst nur eine Methode nach, kannst Du dabei auch weitere Klassen nachladen, die erst zur Laufzeit kompiliert werden. Es ist nur eine andere Herangehensweise zu einer sinnvollen Codeverteilung und im Grunde genommen ist das alles nüschs Neues ;)

                      Wenn du jedoch anders herangehst und einen OpCode-Cache verwendest, kannst du deinen Code so strukturieren, wie er für die Aufgabe sinnvoll ist und musst dich nicht um solche Microoptimierung selbst kümmern.

                      Bekommst du denn durch das Nachladen bei Bedarf solch ausreichende Kapazitäten frei, dass du ein Vielfaches der Besucher mt dem Server abhandeln kannst? Wenn nicht, bringt dir eine schnellere CPU oder etwas mehr Speicher für den OpCode-Cache deutlich mehr Reserven.

                      Und nun versuch mal deine theoretischen Betrachtungen mit Testszenarien und deren Messergebnissen zu überprüfen.

                      dedlfix.

                      1. hi Du,

                        Und nun versuch mal deine theoretischen Betrachtungen mit Testszenarien und deren Messergebnissen zu überprüfen.

                        Nicht nur theoretisch, auch praktisch. Letztendlich wird eine Klasse nur geladen, damit deren Methoden ausgeführt werden können. PHP's Autoloader ist mangelhaft: damit werden die Methoden nur bereitgestellt. Dein Programm muss die Namen der Methoden kennen, damit sie aufgerufen werden können.

                        Hotti

                        1. Dein Programm muss die Namen der Methoden kennen, damit sie aufgerufen werden können.

                          Und wie sollte es anders sein?Wie sollte ich denn eine Methode nutzen, wenn ich deren Namen und damit ihre Eigenschaften nicht kenne?

                          Und wenn PHP über irgendeine Funktion die Methodennamen bereitstellt, ginge das wieder zu Lasten der Performance, was deine Argumente ad-absurdum führt.

                          der Autoloader von PHP ist IMO das optimale Werkzeug. Er stellt zur Verfügung, was ich brauche und macht das so ressourcenschonend wie möglich. Alles andere wäre Luxus und damit rechenintensiv.

                          1. Dein Programm muss die Namen der Methoden kennen, damit sie aufgerufen werden können.

                            Und wie sollte es anders sein?Wie sollte ich denn eine Methode nutzen, wenn ich deren Namen und damit ihre Eigenschaften nicht kenne?

                            MVC Pattern, ein Controller, den ich seit vielen Jahren verwende:

                              
                            sub control{  
                            	my $self = shift;  
                            	if(! $self->launcher(qw(diffcalc add jd date))){  
                            		die "Unbekannter Parameter!\n";  
                            	}  
                            }  
                            
                            

                            Die Schlüsselparameter (diffcalc, add, jd, date) rufen gleichnamige Methoden.

                            der Autoloader von PHP ist IMO das optimale Werkzeug.

                            Keine Widerrede, das Feature ist nicht schlecht. Gelegentlich nutze ich das auch in Perl ;)

                            1. Die Schlüsselparameter (diffcalc, add, jd, date) rufen gleichnamige Methoden.

                              Aber die namen der Methoden muss ich ja trotzdem kennen, oder seh ich das falsch?

        3. Offensichtlich besteht in PHP-Kreisen absolut kein Bedarf, Methoden so auszulagern, dass deren Source erst auf Anforderung kompiliert wird. Das waren meine Suchkriterien ;)

          Wozu auch?
          Wenn ich eine Klasse hätte, die so viele Methoden hat, dass ich sie auslagern muss, würde ich mir Gedanken um mein Konzept machen.

          Ich habe einige Projekte hinter mir, auch Projekte mit mehr als 50 Programmierern (bei PHP-Projekten, bei anderen Sprachen ist das eher Popelkram, diese Grössenordunng, da fang ich gar nicht erst an :D) und trotzdem gabs dafür nie einen Bedarf.

          Über eine Autoloader werden nur die Klassen geladen, die aktuell nötig sind und die beinhalten die Methoden, die gebraucht werden.
          Wenn da mal ein paar Methoden nicht benötigt werden, steht der Nutzen in keinem Verhältnis zum Aufwand.

          Da IMO das Lesen von Festplatte mehr Zeit braucht als das Kompilieren von ein paar Methoden, dürfte dein Konzept massive Performanceverschlechterungen nach sich ziehen, mal abgesehen davon, dass der Code wesentlich unübersichtlicher wird.

          Du willst ja den Code nicht nach der logischen Struktur trennen sondern nach der Anzahl der Methodenaufrufe.

          Das würde z.B. bedeuten, dass in einem Shop die Methode zum Anzeigen des Warenkorbes nicht in der Klasse mit Kaufabschluss steht sondern in der Artikelübersicht, da der Warenkorb zwischendurch angezeigt werden kann. Erfahrungsgemäss machen das die Kunden recht häufig.

          Das grösste Problem ist IMO aber, wer entscheidet, welche Methoden wieoft gebraucht werden? Da dauert das Ausarbeiten ja länger als das Programmieren. Und wenn sich am Projekt was ändert, muss das alles umgeworfen und umstrukturiert werde.

          Fazit: bevor ich sowas umsetzen würde, würde ich mir Gedanken machen, wieso mein Projekt das nötig hat, denn dann ist es eine völlige Fehlplanung/-umsetzung

          1. Moin,

            Über eine Autoloader werden nur die Klassen geladen, die aktuell nötig sind und die beinhalten die Methoden, die gebraucht werden.

            Ja, das ist PHP's Autoloader. Es gibt Aufgabenstellungen, wo sowas nützlich sein kann. Andererseits scheint es mir, als hätten die Entwickler von PHP damit das Rad neu erfunden.

            Schöne Grüße,
            Hotti