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, 7 months ago) by root
Branch: MAIN
Log Message:
*** empty log message ***

File Contents

# Content
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