ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/docs/papp.sdf
Revision: 1.1
Committed: Sat Feb 3 23:05:01 2001 UTC (25 years, 8 months ago) by root
Branch: MAIN
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 !init OPT_STYLE="paper"
2    
3     !define DOC_NAME "PApp - Perl-Anwendungen für die Zukunft des WWW"
4     !define DOC_AUTHOR "Marc Lehmann <pcg@goof.com>"
5     !build_title
6    
7     H1: PApp - Eine kurze Übersicht
8    
9     PApp ist schwer zu beschreiben, da es sich nicht auf ein spezielles
10     Problem spezialisiert sondern möglichst eine offene Universallösung sein
11     will. Unter anderem ist PApp:
12    
13     - ein Embedded-Perl-Dialekt. Es gibt verschiedene Formen: Ein "literal
14     programming style", der nicht XML-konform ist sondern beliebige Daten
15     ausgeben kann und viele Möglichkeiten des Einbettens von Perl in
16     XML. Schliesslich gibt es noch den Standard-XML-Dialekt, der eine Mischung
17     aus beidem darstellt.
18    
19     - Perl-Module, die das Arbeiten in einer CGI-artigen Umgebung
20     erlauben. Die Umgebung hält sich mehr an Apache, ist jedoch unabhängig
21     davon, ob die PApp-Anwendung in einer CGI-Umgebung, unter mod_perl oder
22     unter CGI::SpeedyCGI ausgeführt wird.
23    
24     - Eine Bibliothek (aus vielen Modulen), die das Arbeiten mit HTML, XML,
25     SQL und anderen, häufig benutzten Umständlichkeiten vereinfacht.
26    
27     - Eine grosse "State-Maschine", die technisch getrennte Programmteile
28     (z.B. CGI) logisch zu {{einer}} Applikation zusammenfasst.
29    
30     - Ein XSLT-Stylesheet-Prozessor. Damit kann man Layout und Inhalt
31     voneinander trennen. Oder auch Ausgabeformat (PDF/HTML/XML etc.) vom
32     Layout. Oder vom Inhalt...
33    
34     H2: Warum man es unbedingt benutzen sollte
35    
36     Sollte man das? PApp ist meine ganz persönliche Vorstellung davon, wie
37     man CGI richtig macht. Es wächst und gedeiht in die Richtung, die ich
38     vorgebe, um auftretende Probleme {{besser}} zu lösen.
39    
40     PApp hat meine Motivation (die sich mit "nie wieder CGI" zusammenfassen
41     liess) gewaltig gesteigert - Ein einfaches aber dennoch komplettes
42     Content-Management-System kann man in weniger als 500 Zeilen hinlegen -
43     für mich ein wichtiger Faktor, denn ich hasse nichts mehr, als das Rad
44     jedesmal neu erfinden zu müssen.
45    
46     "Geschmack" ist in jedem Fall ein wichtiger Punkt, wenn es darum geht, ob
47     PApp das Richtige ist.
48    
49     H2: Warum PApp geschrieben wurde
50    
51     Grosse und kleine Applikationen für das WWW zu erstellen ist sehr
52     arbeitsaufwendig. Session-Variablen kennt Perl nicht, Session- und
53     Usertracking natürlich auch nicht. Es gibt sehr gute Module, die einem
54     einen Teil der Arbeit abnehmen, aber es ist immer sehr aufwendig und
55     umständlich. Dies führt zu unübersichtlichen Programmen, die noch dazu
56     auf viele Dateien aufgeteilt sind, die nicht unbedingt der inneren Logik
57     des Programmes entsprechen. Auch Sicherheitsfehler (wie das Übergeben
58     von sicherheitsrelevanten Daten über {{hidden-fields}} moder ähnliches)
59     passieren schnell, schliesslich muss man sich bei jeder Seite überlegen,
60     wie man seine Daten weiterreicht.
61    
62     Datenbankabfragen, das Einbauen des Layouts sind sehr
63     umständlich. Internationalisierung existiert praktisch nicht.
64    
65     PApp vereinfacht alle diese Probleme, indem es sie weitestgehend
66     automatisiert.
67    
68     H1: Grundlegende PApp-Features oder "Nie wieder CGI"
69    
70     H2: Ausrichtung auf ganze Anwendungen
71    
72     Bei CGI oder anderen Schnittstellen ist die Sicht auf die Anwendung
73     protokollbedingt seitenbasiert - jede "logische" Seite ist eine Datei
74     oder eine Fallunterscheidung innerhalb der Datei - gemeinsame Komponenten
75     müssen in Bibliotheken (oder auch nur Include-Dateien; ist im Prinzip
76     das gleiche) abgelegt werden die auf jeder Seite erneut geladen,
77     konfigurietr und eingebaut werden müssen. Perl-Programme funktionieren
78     jedoch anders, da gibt es keine Zustände, die beim anklicken wechseln,
79     sondern ein lineares Programm. Dies läßt sich zwar auch mit PApp nicht
80     verwirklichen, aber es tut sein Bestes, diese Einschränkungen wegzuheben,
81     indem es ganze Anwendungen bearbeitet: Ob mehrere Seiten in einer Datei
82     oder eine Seite auf mehrere Dateien verteilt wird ist in PApp egal.
83    
84     H2: Session/User-Management bzw. -Variablen
85    
86     PApp kümmert sich automatisch persistente Variablen. Damit kann man
87     beinahe automatisch Variablen erzeugen, die über eine gesamte Sitzung
88     (die mit dem Aufruf der ersten URL beginnt und dnan einen Baum bildet)
89     persistent sind. Es geht so einfach, dass man spezielle Hilfsmittel
90     braucht, um nicht an jeder Stelle der Sitzung Zugriff auf beinahe alles zu
91     besitzen.
92    
93     Persistente Variablen gibt es in verschiedenen Geschmäckern. Es gibt:
94    
95     - Session-Variablen (sogenannte {{state keys}}), die über eine gesamte
96     Sitzung erhalten bleiben. Diese werden im Hash C<%S> gespeichert. Man kann
97     beliebige Werte darin ablegen (solange C<Storable> diese serialisieren
98     kann). Meistens gescheiht dies durch Anklicken eines Links, weniger
99     häufig direkt.
100    
101     - Benutzerabhängige Variablen (die auch über Sitzungsgrenzen hinaus
102     erhalten bleiben und deshalb {{preferences items}}, Voreinstellungen,
103     heissen). Auch diese befinden sich in C<%S>, von wo sie automatisch in die
104     Benutzerdatenbank wandern bzw, von dort gelesen werden.
105    
106     - Lokale Variablen ({{local keys}}) zu nur innerhalb einer Seite oder
107     einer Gruppe von Seiten Bedeutung haben. Diese befinden sich ebenfalls in
108     C<%S> und werden automatisch daraus entfernt.
109    
110     - oder beliebige Kombinationen davon.
111    
112     Ein Beispiel für eine Sitzungsvariable ist die Information, ob der
113     Benutzer sich schon angemeldet/eingeloggt hat oder ob er bestimmte
114     Zugriffsrechte besitzt. Eine benutzerabhängige Variable ist z.B.die
115     Sprache, die der Benutzer zuletzt ausgewählt hat (global) oder die
116     Anzahl der Tabellenzeilen, die der Benutzer gerne auf einer bestimmten
117     Seite angezeigt haben möchte. Eine lokale Variable ist z.B. ein
118     Datenbank-Objekt, das über mehrere Seiten (z.B. einer Transaktion)
119     gebraucht wird und danach seine Gültigkeit verliert.
120    
121     Dadurch ergeben sich mehr Möglichkeiten, als man erwarten
122     würde: Unabhängige Komponenten (z.B. Werbebanner oder Foren) sind auf
123     normale Weise nur sehr schwer zu programmieren, da sie immer Hilfe vom
124     "Hauptprogramm" erfordern wenn es um die Parameterübergabe geht. In PApp
125     benutzt man einfach persistente Variablen.
126    
127     Ein Beispiel für eine etwas ungewöhnlichere Komponente ist die
128     {{editform}}-Bibliothek. Mit ihr kann man HTML-Formulare erstellen, die
129     sich direkt an eine bestimmte Variable binden:
130    
131     !block perl
132     ef_begin;
133     ef_string \$S{search};
134     ef_end;
135     !endblock
136    
137     Dieses Beispiel stammt von einer Seite, die Objekte aus einer Datenabnk
138     anzeigt und sich dabei auf solche beschränkt, die ein Suchwort
139     enthalten. Das Formular bindet die State-Variable C<search> an ein
140     HTML-Textfeld. Bei der Ausgabe wird der aktuelle Wert von C<$S{search}>
141     benutzt. Ändert der Benutzer den Text und schickt das Formular ab wird
142     die Seite neu aufgebaut - mit einem anderen Wert in C<$S{search}>. Da
143     editform beliebige Perl-Referenzen akzeptiert und man in PApp auch
144     Referenzen auf Dateien, SQL-Spalten etc... erzeugen kann werden viele
145     Formulare zum Kinderspiel.
146    
147     Zusätzlich zu den Sitzungsvariablen gibt es noch sogenannte
148     {{Argumente}}, die nur eine Seite lang "persistent" sind, d.h. bei einem
149     Link auf eine andere Seite übergeben werden:
150    
151     !block perl
152     echo slink "Klicken Sie hier", -argument1 => "wert1", var2 => "wert2";
153     !endblock
154    
155     Wenn man diesem Link folgt, steht der "wert1" im Hash C<%A> bzw. "wert2"
156     im Hash C<%S>:
157    
158     !block perl
159     printf "Das Argument argument1 ist %s, die State-Variable var2 ist %s",
160     $A{argument1}, $S{var2};
161     !endblock
162    
163     Werte, die von "Aussen" (z.B. GET-Request in CGI) kommen, stehen, um die
164     Verwirrung komplett zu machen, in C<%P>. Als Faustregel gilt: was in C<%S>
165     und C<%A> steht ist sicher (bzw. man hat es selbst dorthin gepackt), was
166     in C<%P> steht ist unsicher und muss erst gefiltert/geprüft werden.
167    
168     H2: Sicherheit
169    
170     In vielen CGI-Programmen (aber nicht nur dort) wird der Fehler
171     begangen, sensitive Daten in {{hidden}}-Feldern in einem Formular zu
172     "verstecken" oder sie in die URL zu kodieren um die Parameterübergabe zu
173     realisieren. Dies ist in PApp nicht nötig, da der persistente 'State' in
174     einer Datenbank gespeichert wird und nur der (mit 256 Bit verschlüsselte)
175     Zeiger darauf zum Client übertragen wird. Dadurch werden sensitive Daten
176     gar nicht erst zum Client übertragen, was natürlich auch Bandbreite
177     spart. Sollte der Schlüssel einmal bekannt werden kann man zwar auf
178     andere Sessions zugreifen, die Daten jedoch immer noch nicht verändern
179     (dieser Fall tritt beispielsweise auch auf, wenn ein kaputtes Proxy
180     zwischen Server und Client sitzt).
181    
182     Eine typische PApp-URL sieht übrigens so aus (Applikation "kis", Modul
183     "abteilungswahl"):
184    
185     !block verbatim
186     /kis/abteilungswahl/NIlRSJNDIfP3AHfVjxLF5F
187     !endblock
188    
189     Da eine "Seite" in PApp aus einem Modulbaum besteht, geht es auch
190     komplizierter:
191    
192     !block verbatim
193     /admin/+admin=poedit+poedit=view--?papp=eTDgL.I-lj9O9lTO3wznTk
194     !endblock
195    
196     Zusammen mit einem sicheren Transportprotokoll (z.B. SSL, wobei die
197     meisten Browser nur ungenügend oder garnicht gegenüber Attacken
198     schützen, nur so am Rande ;) schützt man sich damit gegen alle Seiten.
199     Benutzerauthentifizierung über Zertifikate ist auch im Einsatz (mit dem
200     C<ssl>-Modul von PApp).
201    
202     H2: Session/User-tracking
203    
204     Persistente Variablen erfordern Session-Tracking. Benutzerabhängige
205     Einstellungen (Preferences) darüber hinaus auch User-Tracking. Ersteres
206     geschieht mit einer Session-ID, die (auf verschiedene Arten) in die
207     URL-kodiert wird und die alle notwendigen Daten enthält, um die
208     gewünschte Seite komplett zu erzeugen. Darüber hinaus wird (optional)
209     ein Cookie benutzt, das aber z.Zt. nur zum Identifizieren des Benutzers
210     dient, da ich Session-Definitionen per Cookie als Unsinn erachte. Das
211     Cookie wird auch nur einmal am Tag gesetzt, so daß man auch mit der
212     Browser-Einstellung "vor Cookies warnen" arbeiten kann.
213    
214     Eine Anwendung wird darüber informiert, ob eine neue Session begonnen
215     wurde oder ob sich ein bisher unbekannter Benutzer angemeldet hat, so
216     daß man Benutzereinstellungen o.ä. initialisieren kann. Dies nützt
217     PApp selbst, um sich z.B. die Sprache des Benutzers zu merken oder um das
218     User-Cookie nur einmal täglich zu setzen.
219    
220     Eine "Sitzung" ist übrigens ein Baum (nicht nur in PApp), der mit dem
221     ersten "Hit" als Wurzel beginnt. Dadurch ist es unter anderem möglich,
222     die Anzahl der "Reloads" einer Seite zu bestimmen. Dies ist nützlich,
223     um potentiell gefährliche Aktionen (z.B. Löschen von Datenbanken,
224     abschicken von E-mails) nur einmal auszuführen.
225    
226     H2: Benutzerverwaltung
227    
228     Da PApp Benutzer (mehr oder weniger) eindeutig identifizieren muss,
229     implementiert es intern eine eigene Benutzerverwaltung inklusive einer
230     Unix-artigen Rechtevergabe (es gibt allerdings keinen Super-User im
231     Unix-Sinne). In vielen Anwendungen kann man diese gleich mitbenutzen, da
232     eine eindeutige Benutzer-ID automatisch vergeben wird.
233    
234     !block verbatim
235     Sie sind wahrscheinlich Benutzer Nummer <?$userid:><br/>
236     #if auth_p
237     Und ausserdem haben sie sich authentifiziert.<br/>
238     # if access_p "admin"
239     Oh, und "admin"-Rechte besitzen Sie auch noch! Meine Güte!!<br/>
240     # endif
241     #endif
242     !endblock
243    
244     H2: I18n
245    
246     I18n steht kurz für Internationalisierung: Das englische Wort
247     {{Internationalization}} hat 18 Buchstaben zwischen dem 'I' und dem
248     'n', und da das Wort für den Durchschnittsamerikaner viel zu lang und
249     kompliziert ist, hat man diese 18 Buchstaben einfach durch "18" ersetzt.
250    
251     In Kontext von PApp bedeutet dies, dass beinahe überall Textmeldungen
252     übersetzt werden können (wer das C<gettext>-Paket kennt, mit dem
253     üblicherweise C-Programme internationalisiert werden, wird sich fast
254     sofort Zuhause fühlen). Hier ist ein Beispiel:
255    
256     !block verbatim
257     <h1>__"Contents"</h1>
258     <:for (1..10) {:>
259     <?slink sprintf(__"Chapter %d", $i++),
260     "view_chapter", chapterid => $i:>
261     <:}:>
262     !endblock
263    
264     Wie man sieht, kann man C<__"text"> sowohl im
265     HTML/XML/wasauchimmer-Quelltext benutzen, als auch auf Perl-Ebene
266     aufrufen. Die C<__>-Funktion erledigt dabei zwei Aufgaben: Zunächst werden damit
267     Textkonstanten zum übersetzen {{markiert}}. Zur Laufzeit wird dann in der Übersetzungstabelle nachgesehen und
268     der (evt.) übersetzte String zurückgeliefert.
269    
270     Wenn man Daten z.B. aus einer Datenbank in eine Variable holt, darf man diese natürlich {{nicht}} markieren, da sie ja nur zur Laufzeit einen String {{enthält}}, selbst
271     aber keine Textkonstante ist. In solchen Fällen verwendet man C<gettext>:
272    
273     !block perl
274     my $st = sql_exec \my($id, $name), "select id, name from table";
275    
276     while ($st->fetch) {
277     echo "<li>", gettext$name, "</li><br/>";
278     }
279     !endblock
280    
281     In welche Sprache jeweils übersetzt wird, entscheidet bei HTTP die
282     Einstellung des Browsers, wobei man zweckmässigerweise ein Menü
283     anbietet, in dem der Benutzer dies überschreiben kann:
284    
285     !block perl
286     <?slink "I want English", SURL_SET_LANG => "en":>
287     <?slink "Deutsch willich!", SURL_SET_LANG => "de":>
288     !endblock
289    
290     Auch die Spracheinstellung ist eine Preferences-Variable. Im Gegensatz
291     zum C<gettext>-Paket müssen die Quelltext nicht alle in einer Sprache
292     sein. Bei C<gettext> ist das auch weniegr ein Problem, da der Quellcode
293     eines Programms meistens in einer (natürlichen) Sprache geschrieben
294     wurde, in PApp kann man aber Seiten dynamisch einfügen oder Datenbanken
295     übersetzen. Da diese meist nicht vom selben Team geschrieben werden, ist
296     es nützlich, dort unterschiedliche Sprachen verwenden zu können.
297    
298     <<poedit1.png>>
299     <<poedit2.png>>
300    
301     H2: Unicode / Zeichensatzunabhängigkeit
302    
303     Intern unterstützt PApp genau zwei Datentypen (genau wie Perl
304     selbst): {{Binärdaten}} und {{Text}}. Binärdaten verwendet man
305     üblicherweise für Bilder, Datei-Downloads und ähnliches. Diese Daten
306     werden von PApp nicht angerührt.
307    
308     Ganz anders Text: Perl arbeitet intern mit Unicode, das z.Zt. entweder in
309     ISO-8859-1 oder UTF-8 gespeichert wird. Dieser interne Zeichensatz ist
310     völlig unabhängig von der Ausgabe, d.h. der Text wird bei der Ausgabe
311     automatisch in den gewünschten Zeichensatz kodiert (das geschieht wieder
312     Browser/Benutzer/Programmabhängig wobei von den gebräuchlichen Browsern
313     nur Netscape und Lynx die entsprechenden Header liefern). Umgekehrt werden
314     Formulardaten u.ä. automatisch in Unicode gewandelt, d.h. in C<%P> steht
315     Unicode auch wenn der Browser ein Formular in ISO-2022-JP zurückgeschickt
316     hat.
317    
318     Ein JPEG-Bild kann man z.B. so ausgeben:
319    
320     !block perl
321     content_type "image/jpeg", undef;
322     $gd->jpeg(80);
323     !endblock
324    
325     Während man eine japanische Benutzerin vielleicht mit ISO-2022-JP
326     zufriedenstellen kann:
327    
328     !block perl
329     content_type "text/html", "iso-2022-jp";
330     echo __"Hoffentlich war der Übersetzer fleissig";
331     !endblock
332    
333     H2: Geschwindigkeit
334    
335     Geschwindigkeit war bei der Implementierung von PApp das zweitwichtigste
336     Ziel (Korrektheit ist das wichtigste ;). Als Marke dient mir ein
337     Pentium-II 266Mhz-Rechner, auf dem auch komplexe Seiten mit mindestens 15
338     Hits/Sekunde dargestellt werden, bzw. der Vergleich mit einem ähnlichen
339     C<Apache::Registry>-Skript.
340    
341     Das State-Management von PApp verschlingt pro Seite 1-3 Datenbankzugriffe,
342     die die Zeit bei weitem dominieren (andere Features wie I18n sind im
343     Prinzip kostenlos). Da komplexe Seiten im Allgemeinen wesentlich mehr und
344     kompliziertere Zugriffe enthalten bzw. man ja irgendwie seine Daten
345     speichern muss, ist dies in der Praxis selten eine Einschränkung
346     (Ausnahmen gab und gibt es immer). Andere PApp-Features (z.B. im
347     SQL-Bereich) bringen häufig sogar eine Steigerung der Geschwindigkeit.
348    
349     Da ich bisher keine Seite fabrizieren konnte, die die 15 Zugriffe/s-Marke
350     unterschritten hätte, glaube ich noch etwas Spielraum für noch mehr
351     Features zu haben. Wer sich übrigens fragt, woher diese 15 Hits/s
352     kommen: 15 Hits ist die Marke, die einen wirklich grossen Server von den
353     99.99% der restlichen Welt unterscheidet. Hat man auf seinem Server 15
354     oder mehr Zugriffe pro Sekunde kann man sich meistens auch eine schnellere
355     Datenbank oder mehrere Rechner leisten: PApp skaliert problemlos auf
356     mehrere Maschinen.
357    
358     H2: XML
359    
360     XML wird in mehreren Teilen von PApp unterstützt bzw. gefordert: Der
361     Standard-Dialekt von PApp ist in XML geschrieben, d.h. um "normale"
362     PApp-Applikationen zu schreiben muss man sich XML bedienen. Die Ausgabe
363     von PApp (meistens Text) ist beliebig, sofern man keine Stylesheets
364     benutzt. Tut man das, muss die Ausgabe natürlich in XML-Syntax sein. Und
365     last-not-least gibt es ein PApp-Modul, mit dem man beliebige XML-Fragmente
366     mit eingebettetem Perl-Quelltext bearbeiten/ausführen/anzeigen kann.
367    
368     Die Entscheidung, XML so zentral einzusetzen, fiel mir nicht
369     leicht: Meiner Meinung nach ist XML wunderbar dafür geeignet,
370     Daten innerhalb von Programmen zu verarbeiten und vor allem
371     auszutauschen. Toll ist, dass Menschen XML notfalls lesen und auch
372     schreiben können. Ansonsten ist doch die Mächtigkeit von SGML (oder
373     etwas anderem) vorzuziehen.
374    
375     XML jedoch hat bestechende Vorteile: HTML ist eine XML-Applikation (und
376     HTML ist wichtig ;); es existiert eine breite Unterstützung für XML;
377     es gibt bestehende Standards für Stylesheets, Layout, Metadaten und
378     mehr. Schliesslich ist XML auch noch sehr schnell. Nun ja.
379    
380     Das hat mich trotzdem nicht davon abgehalten, etwas oben
381     draufzusetzen: Fast alle Dokumente können in einem "Meta-Format" mit
382     eingebettetem Perl-Quelltext geschrieben werden. Die Standard-Syntax
383     dafür bedient sich vier sog. "Modus-Umschalter", die jeweils vom
384     "Verbatim" in den "Perl"-Modus bzw. zurück schalten:
385    
386     !block verbatim
387     <: schalte von HTML in Perl um
388     <? wie <:, füge jedoch das Ergebnis in die Ausgabe ein
389    
390     :> schalte in den HTML-Modus
391     ?> schalte in den interpolierten HMTL-Modus
392     !endblock
393    
394     Diese Modus-Umschalter habe ich in den Beispielen schon verwendet, z.B.
395     kann man eine HTML-Seite so schreiben:
396    
397     !block perl
398     <h1>Ein bisschen HTML</h1>
399     <: echo "mit eingebautem perl" :>
400     <: print "so gehts auch, ist aber unendlich wenig langsamer ;)" :>
401     <?"So gehts am schnellsten":>
402     <:for my $text (qw(Noch eine komische Methode)) {
403     ?>$text&#160;<:
404     }:>
405     !endblock
406    
407     Die Modus-Umschalter verhalten sich dabei wie eine Statement-Grenze in Perl (also C<;>).
408    
409     H2: Protokol- und Layout-Unabhängigkeit
410    
411     Sprache und Quelltext ternnt PApp ja schon. Jetzt muss man noch das Layout
412     vom eigentliche Programm bzw. das Protokoll von den eigentlichen Daten
413     trennen.
414    
415     Mit XSLT-Stylesheets geht das. Und mehr: "Browser XYZ hat ein Problem? Ich
416     fix' es im Stylesheet und vergesse es dann einfach." (z.B. sollte man
417     leere HTML-Tabellenzellen für Netscape lieber mit einem C<&nbsp;>
418     füllen). "Es soll WML (oder CHTML) sein? Ich weiss zwar nicht, wozu
419     das ganze WML-Zeugs sinnvoll sein soll, aber dann mache ich halt' ein
420     Stylesheet dafür." Und eine der wichtigsten Anwendungen: "Wir brauchen
421     eine Version zum drucken. Dafür wandeln wir unser XML-Dokument in XSL" (und dann
422     nach Latex, PDF...).
423    
424     Das bedeutet, dass man - Planung natürlich vorausgesetzt - einen hohen
425     Grad an Protokollunabhängigkeit erreichen kann, ohne den Quelltext zu
426     sehr mit Layout-Entscheidungen o.ä. belasten zu müssen.
427    
428     Leider gibt es noch keine Web-Designer, die XSLT statt HTML/CSS liefern,
429     aber (meine) Vision des Webs der Zukunft sieht so aus: Der Server liefert
430     XML zusammen mit einem XSLT (vom Designer), welches XSL erzeugt. Dieses
431     wird dann angezeigt/gedruckt etc.a.. Metadaten (mit dem etwas besseren
432     Nachfolger von RDF) gestatten dann Fragen wie: "Wer hat dieses Dokument
433     geschrieben?", "Wozu dient es?" aber auch: "Wieso ist das Ding so bunt?".
434    
435     H2: Platform-Unabhängigkeit
436    
437     Ein toller Begriff. Was bedeutet er? Nicht viel. Bei PApp bedeutet dies,
438     dass auf Unix-Abhängigkeiten möglichst verzichtet wurde und sich PApp
439     nicht an einen bestimmten Server (z.B. Apache) bindet. In der Praxis kann
440     man als Platform mod_perl oder CGI verwenden, aber auch Text-Interfaces
441     sind denkbar: Da PApp der Applikation immer eine gleichbleibende Umgebung
442     anbietet, muss man lediglich ein Schnitstellenmodul schreiben.
443    
444     H2: Datenbanken
445    
446     Wie soll man ohne auskommen? Natürlich garnicht. In Perl gibt es ein ganz
447     wunderbares System (DBI!) um mehr-oder-weniger genormt auf SQL-Datenbanken
448     zugreifen zu können. Jetzt ist "nacktes" DBI recht umständlich,
449     zumindest für mich, für den vier Aufrufe pro SQL-Befehl entschieden zu
450     viel sind. Vor allem, wenn man diese über das Programm verstreuen muss.
451    
452     In PApp erledigt man die meisten Aufgaben mit der C<sql_exec>-Funktion
453     (den Rest erledigt man mit C<sql_fetch/fetchall/exists/insertid>). Der
454     folgende Aufruf ersetzt C<prepare>, C<bind_params>, C<execute> und
455     C<bind_columns>:
456    
457     !block perl
458     my $st = sql_exec \my($p, $w),
459     "select purzel, wurzel from table
460     where name like ?",
461     $S{search};
462    
463     while ($st->fetch) {
464     echo "$p, $w\n";
465     }
466     !endblock
467    
468     Der besondere Clou: Die SQL-Statements werden gecached, d.h. im
469     Allgemeinen nur ein einziges mal C<prepare>d. Bei Datenbanken, die einiges
470     an Aufwand in diesem Schritt investieren (Stichwort Query-Optimizer)
471     ist das ein grosses Plus. Sogar bei Datenbanken, die dies nicht tun
472     (z.B. MySQL) steigt die Geschwindigkeit merklich. Zudem sind das
473     C<prepare> und das C<execute> in normalen Programmen getrennt voneinander
474     (die Befehle stehen weit auseinander).
475    
476     Bei Datenbanken, die eine Art "insertid" unterstützen (zum Glück fast
477     alle), kann man diese nach einem C<INSERT> gleich mit abfragen:
478    
479     !block perl
480     my $id = sql_insertid
481     sql_exec "insert into tiere (name) values (?)",
482     "hase";
483     !endblock
484    
485     Den Database-Handle habe ich übrigens nicht vergessen: Wenn ich
486     keinen angebe, wird ein Default-Handle benutzt. Geschickterweise wird
487     dieser von PApp selbst gesetzt, so dass man sich im Normalfall noch
488     nicht einmal um die Datenbankverbindung kümmern muss (weil diese auf
489     dem Produktionssystem meistens andere Passwörter hat als auf dem
490     Entwicklungssystem stellt man diese geschickterweise bei der Konfiguration
491     der Applikation ein).
492    
493     <<admin.png>>
494    
495     H2: Hilfreiche Hilfsobjekte
496    
497     Ich habe es schon angesprochen: Persistenz von fast allem, zusammen mit
498     den Möglichkeiten von Perl können einen schon auf Ideen bringen, z.B.
499     auf eine Bibliothek (editform), die HTML-Formularfelder an Perl-Refrenzen
500     bindet.
501    
502     Nun ist es an der Zeit, einmal eine Referenz auf eine SQL-Tabelle zu
503     erzeugen:
504    
505     !block perl
506     <:
507     my $row = new PApp::DataRef 'DB_row',
508     table => "user",
509     where => [id => $userid],
510     delay => 1,
511     autocommit => 1;
512    
513     # pre-set name
514     $row->{name} ||= "<username>";
515    
516     ef_begin;
517     :><br>__"ID:" <?ef_string \$row->{id} , 5:><:
518     :><br>__"Name:" <?ef_string \$row->{name}, 20:><:
519     ef_submit __"Update";
520     ef_end;
521     :>
522     !endblock
523    
524     Die Referenz auf die Zeile steht in C<$row> un verhält sich wie eine
525     Referenz auf einen herkömmlichen Perl-Hash. Das C<autocommit> sorgt
526     dafür, dass die geänderten Daten automatisch zurückgeschrieben werden
527     sobald das C<$row>-Objekt gelöscht wird (ausser Scope geht, C<DESTROY>ed
528     wird). Sie ist lokal (C<my>!) gespeichert, da aber die C<ef_>-Funktionen
529     die Referenz persistent speichern, wird das Objekt erst auf der nächsten
530     Seite (also nachdem die Ergebnisse hineingeschrieben wurden!) zerstört,
531     bzw. die Daten geschrieben. Etwas kompliziert, aber zum Benutzen muss man
532     die Details ja auch nicht kennen.
533    
534     Nun macht das Beispiel keine Fehlerüberprüfung, meistens das
535     schwierigste. Mit PApp kein Problem. Zuerst schalten wir das C<autocommit>
536     ab, damit die Daten nicht "aus Versehen" geschrieben werden. Ausserdem
537     übergeben wir die Referenz als Argument an die "nächste" Seite.
538    
539     !block perl
540     <:
541     my $row = $A{row}
542     || new PApp::DataRef 'DB_row',
543     table => "user",
544     where => [id => $userid],
545     delay => 1,
546     autocommit => 0;
547    
548     ef_begin -row => $row; # Daten als Argument übergeben
549     !endblock
550    
551     Nun brauchen wir ein Flag, das uns sagt, ob der Datensatz fehlerhaft ist
552     und schon können wir loslegen:
553    
554     !block perl
555     my $err = 0; # Daten fehlerhaft?
556    
557     :><br/>__"ID:" <?ef_string \$row->{id} , 5:><:
558     #if $row->{id} !~ /^(\d+)$/
559     <error>__"The ID must be an integer!"</error>
560     <:$err++:>
561     #endif
562     :><br/>__"Name:" <?ef_string \$row->{name}, 20:><:
563     #if 2 > length $row->{name}
564     <error>__"The Name must contain at least two characters!"</error>
565     <:$err++:>
566     #endif
567     ef_submit __"Update";
568     ef_end;
569     !endblock
570    
571     Die Daten schreibt man dann bei Bedarf in die Datenbank:
572    
573     !block perl
574     #if $row->dirty
575     # if $err
576     <error>__"The entered Data is invalid, please surrender or die (or correct it ;)</error>
577     # else
578     <:$row->flush:>
579     __"The record has been updated."
580     # endif
581     #endif
582     :>
583     !endblock
584    
585     H2: "Entwicklungshilfe"
586    
587     Programme - auch solche, die mit PApp geschrieben werden - müssen erst
588     entwickelt werden. Dabei werden Fehler gemacht. Da bei PApp sehr viele
589     Komponenten zusammenwirken können die Fehler entsprechend komplex
590     sein. Eine gute Unterstützung bei der Fehlersuche ist also wichtig.
591    
592     Dies fängt damit an, dass die Zeilennummern des Quelltextes auch nach
593     der Kompilierung von Perl/XML zu reinem Perl oder z.B. in ein XSLT
594     erhalten bleiben. Sollte ein Fehler auftreten, so hat man sofort Zugriff
595     auf die Qeulldateien, einen kompletten Backtrace und natürlich die
596     State-Daten. Das Exception-System von PApp ist einfach zu benutzen (C<die>
597     genügt, will man es schöner haben benutzt man C<fancydie> ;) und
598     erweiterbar.
599    
600     Im Betrieb will man natürlich keine ausführlichen Fehlermeldungen,
601     komplett mit Passwort der Datenbank usf... Deshalb protokolliert PApp
602     alle Fehler in eine SQL-Datenbank zusammen mit der State-ID, so dass
603     nur die Fehlerkategorie (plus ein nettes Textfeld, in dem der Benutzer
604     zusätzliche Informationen eingeben kann). Solange die Seite nur
605     wiederholbare Aktionen enthält, kann der Entwickler den Fehler jederzeit
606     reproduzieren.
607    
608     H2: "Web-Widgets"
609    
610     The newest addition to PApp (and therefore not final in its
611     implementation) are reusable components also dubbed {{Web-Widgets}},
612     similar to reusable GUI-objects named "widgets". An example for such a
613     component would be a standard "forum" widget. In one of our projects we
614     use the same forum widget to provide "web chat", "small ads" and the
615     "news!" page, all with the same code but using different stylesheets to
616     customize the layout.
617    
618     A PApp-application is, in some sense, a large state-machine. this is a
619     limitation of stateless protocols which is hard, but not impossible, to
620     circumvent (if perl only had efficient continuations). Any application can
621     be embedded into other applications, while retaining their own state and
622     their own state machine and of course their own set of variables / state
623     keys. Standard PApp applications are not much more than a single page with
624     html header/footer, authenticitation check and an embedded "Web-widget".
625    
626     H2: Logging
627    
628     Logging is a required part of any serious business. Gathering statistical
629     data is a basic requirenment today. PApp saves every state key to a
630     database for each page impression/request (usually between 300 and 900
631     bytes). This saved information contains everything nedeed to recreate a
632     given page except the actual program code. When session/state data is
633     being expired (necessary to put a sensible bound on the size of the state
634     database), PApp conviniently allows applications to gather statistical
635     data from individual "hits", using almost the same environment as at
636     runtime. Expiring and data gathering can, of course, be done seperately if
637     necessary.
638    
639     H2: PApp is Free Software
640    
641     Although we are not sure wether we'll publish all versions of PApp
642     under the GPL, or which modules from our own applications might become
643     standard components (like the forum), we are determined to make PApp free
644     software. The principal PApp architect (me!) did a lot of free software
645     modules and works at quite a few free software programs (like GCC or The
646     Gimp) and is determined to make PApp as free and as powerful as possible.
647    
648     H1: Disadvantages
649    
650     PApp is not actually a revolution, judged by its components. It
651     does, however draw a lot of functionality and ideas into a single,
652     well-contained package. Nevertheless, there are quite a few reasons on why
653     {{NOT}} to use PApp, or at least not to use PApp {{YET}}.
654    
655     * PApp is not yet a released module, its API is in flux (with respect to
656     recent features), and not everything is working as it should yet. This
657     is fortunately only a question of time.
658    
659     * Only a single person is currently developing and designing PApp for
660     free. This means that advances might sometimes not lead into the
661     direction you want, and maybe not in the schedule you want.
662    
663     * PApp requires the very latest perl - at the moment, this is perl
664     5.7 + custom patches, due to the buggy unicode support in earlier
665     versions. The latest released PApp module (on CPAN) does not rely on
666     unicode, but is already quite outdated with respect to current features.
667    
668     * There is a total lack of tutorials or introductory courses. While all
669     PApp modules are documented, it is very much impossible to learn it
670     using the reference documentation alone. Basically a one-day course
671     under four eyes is necessary to get you up and running - PApp is
672     not trivial. The lost time is generally made up with the increase in
673     productivity experienced with PApp, though, similar to learning Perl ;)
674    
675     A1: References
676    
677     * PApp is available as a standard module from CPAN, although the current
678     version uploaded is very old.
679    
680     * The PApp homepage is available at the author's homepage, under
681     {{URL:http://www.goof.com/pcg/marc/papp.html}}. This page includes
682     links to the current manpages. Online demos are, unfortunately, not yet
683     available.
684    
685     * The newest versions of PApp can be accessed using CVS as a sourceforge project,
686     at {{URL:http://www.sourceforge.net}}.
687    
688     * The slides for this presentation will be available at the author's
689     homepage, at {{URL:http://www.goof.com/pcg/marc/docs.html}}, shortly
690     after the linuxworldexpo.
691    
692     A2: Apology
693    
694     I'd like to apologize for any typoes or other mistakes in this
695     document. It was written in a single session without access to a
696     spellchecker and so has not been debugged it yet ;)
697     %page
698    
699     Basic features
700    
701    
702    
703     Persistence is almost automatic
704    
705     Variables ("state keys") can last for a session or longer
706    
707     Session/User-tracking is automatic
708    
709     Sensitive data does not leave the server
710    
711     PApp gives great error feedback ;)
712    
713     %page
714    
715     What does it look like?
716    
717     %font "t", prefix " "
718     <package name="dunno"> <domain lang="en">
719    
720     <language lang="en" desc="English"/>
721     <language lang="de" desc="Deutsch"/>
722    
723     <database dsn="DBI:mysql:dunnodb"/>
724     <translate fields="project.name place.name"
725     lang="en"/>
726     <translate fields="project.description"
727     lang="mixed" style="auto"/>
728    
729     <import src="macro/util"/>
730    
731     <module src="dunno/somepages"/>
732    
733     </domain> </package>
734    
735     %page
736    
737     Modules
738    
739    
740     PApp is application centric - one application can consist of many pages (called 'modules').
741    
742     Each web-page is (usually) a seperate module.
743    
744     Modules and even applications can be nested or embedded.
745    
746     State keys can be shared with ease within a session or user context.
747    
748     One module == one state of the state machine (http and wap are statemachines!).
749    
750     %page
751    
752     A simple module
753    
754    
755     %font "t", prefix " "
756     <module name=""><phtml><![CDATA[
757     <html> <title>
758     __"PApp - demo", <?localtime:>
759     </title>
760    
761     <?slink "English", "/lang" => 'en':>
762     <?slink "Deutsch", "/lang" => "de":>
763    
764     <p><?slink __"To the editor", "editor":>
765     <p><?slink __"Edit project 1", "editor",
766     projectid => 1:>
767    
768     </html>
769     ]]></phtml></module>
770    
771     %page
772    
773     phtml mode switches
774    
775    
776    
777     <: switch to perl statement mode
778    
779     <? evaluate perl expression
780    
781     :> switch to plain html/text mode
782    
783     ?> switch to interpolated (qq) html/text mode
784    
785    
786     %page
787    
788     Another simple module - "editor"
789    
790    
791     %font "t", prefix " "
792    
793     <module name="editor">
794     <state keys="projectid" local="yes"/>
795     <phtml><![CDATA[
796     <:header:>
797    
798     #if defined $S{projectid}
799     ... edit the specific project
800     #else
801     ... show a list of projects
802     #endif
803    
804     <:footer:>
805     ]]></phtml></module>
806    
807     %page
808    
809     SQL support - the project list
810    
811    
812     %font "t", prefix " "
813     <table><tr><th>__"Project"<th>__"Budget"
814     <:
815     my $st =
816     sql_exec \my($id, $name, $budget),
817     "select id, name, budget
818     from project";
819    
820     while ($st->fetch) {
821     :><tr><td>
822     <?slink gettext$name,
823     projectid => $id?>
824     <td>$budget
825     <:
826     }
827     :>
828     </table>
829    
830     %page
831    
832     SQL support - persistent rows
833    
834     %font "t", prefix " "
835     <:ef_begin:>
836    
837     <:my $row = new PApp::DataRef 'DB_row',
838     table => "project",
839     where => [id => $S{projectid}]:>
840    
841     <p>__"Name":
842     <:ef_string \$row->{name}, 40:>
843     <p>__"Budget":
844     <:ef_string \$row->{budget}, 8:>
845     <p>__"Description":
846     <:ef_text \$row->{description}, 60, 10:>
847    
848     <:ef_submit __"Update":>
849     <:ef_end:>
850    
851     %page
852    
853     Internationalization (I18n)
854    
855    
856    
857     Strings inside source files can be "tagged"
858    
859     Database columns can be tagged
860    
861     PApp is unicode-only
862    
863     Output conversion (e.g. utf8>latin1, utf8>iso2022jp)
864    
865     Translation editor ("poedit") included
866    
867     %page
868    
869     Speed
870    
871    
872    
873     Speed is slightly worse than Apache::Registry - on simple pages!
874    
875     Complex pages usually make no difference (database overhead!)
876    
877     Many PApp features deliver a performance that would be tedious to match in plain perl!
878    
879     PApp scales to many server machines, if necessary
880    
881     %page
882    
883     XML
884    
885    
886     No, XML is not a feature.
887    
888     XML might be nice to computers, it isn't usually for humans, though.
889    
890     XML is robust
891    
892     XML is fast
893    
894     XML is well supported
895    
896     %page
897    
898     XML + XSLT = protocol independency
899    
900    
901     PApp can support XML as well as HTML
902    
903     You can write your pages in XML
904    
905     XSLT stylesheets can be applied
906     at parse time
907     before module execution
908     to the resulting output
909    
910    
911     Thus, PApp applications can easily be made protocol-independent by writing them in XML and using a stylesheet that outputs either HTML, XML, WML or whatever you like!
912    
913     %page
914    
915     Dynamic stylesheet example
916    
917     %font "t", prefix " "
918     <perl><![CDATA[
919     $stylesheet[0] =
920     $papp->load_stylesheet("dunno1");
921     $stylesheet[1] =
922     $papp->load_stylesheet("dunno2");
923     ]]></perl>
924    
925     <style apply="output"
926     expr="$stylesheet[ $S{style} ]">
927    
928     <module name=""><phtml><![CDATA[
929     <p/><?slink __"To the edito...
930     <p/><?slink __"Edit projec...
931     ]]></phtml></module>
932    
933     ...
934     </style>
935    
936     %page
937    
938     "Web-Widgets"
939    
940    
941     A nice term - what is it?
942    
943    
944     PApp applications can be "embedded" into host applications
945    
946     With careful coding, reusable objects be created (e.g. a forum module, an ad-banner module etc.)
947    
948     Embedded apps come with their own state machine, own environment etc.
949    
950     Apply stylesheets to customize, if necessary
951    
952     %page
953    
954     PApp
955    
956    
957    
958    
959    
960     seperates
961    
962     layout
963     semantics
964     language
965    
966     from each other!
967    
968     %page
969    
970     Disadvantages
971    
972    
973     perl 5.7.0 + patches is currently required
974    
975     many modules are necessary
976    
977     mod_perl is currently the only supported platform
978    
979     written by one overworked person only
980    
981     the api is in flux
982    
983     no stable release yet
984    
985     %page
986    
987     More info
988    
989    
990    
991    
992    
993    
994    
995    
996