$::request als globale Variable eingeführt.
authorSven Schöling <s.schoeling@linet-services.de>
Fri, 14 Oct 2011 10:40:04 +0000 (12:40 +0200)
committerSven Schöling <s.schoeling@linet-services.de>
Fri, 14 Oct 2011 10:40:14 +0000 (12:40 +0200)
SL/Dispatcher.pm
doc/20111013_globale_variablen.txt [new file with mode: 0644]
scripts/console
scripts/rose_auto_create_model.pl
scripts/task_server.pl
t/structure/globals.t

index 291953b..cfb4fb8 100644 (file)
@@ -95,6 +95,7 @@ sub pre_startup_setup {
     $::auth        = SL::Auth->new;
     $::form        = undef;
     %::myconfig    = ();
+    $::request     = undef;
   }
 
   $SIG{__WARN__} = sub {
@@ -171,6 +172,7 @@ sub handle_request {
   $::locale        = Locale->new($::lx_office_conf{system}->{language});
   $::form          = Form->new;
   $::instance_conf = SL::InstanceConfiguration->new;
+  $::request       = { };
 
   my $session_result = $::auth->restore_session;
   $::auth->create_or_refresh_session;
@@ -251,6 +253,7 @@ sub handle_request {
   $::locale   = undef;
   $::form     = undef;
   $::myconfig = ();
+  $::request  = undef;
   Form::disconnect_standard_dbh;
 
   $::lxdebug->end_request;
diff --git a/doc/20111013_globale_variablen.txt b/doc/20111013_globale_variablen.txt
new file mode 100644 (file)
index 0000000..37af087
--- /dev/null
@@ -0,0 +1,216 @@
+nachdem Holger heute den Bug eingestellt hat den ich schon lange befürchtet
+habe, bin ich heute mal die globalen Variablen angegangen. Das ganze ist über
+die Jahre leider recht komfus geworden, deshalb hier ne Erklärung, die
+hoffentlich sowas in Zukunft vermeidet.
+
+
+Wie sehen globale Variablen in Perl aus?
+----------------------------------------
+
+Globale Variablen liegen in einem speziellen namespace namens "main", der von
+überall erreichbar ist. Darüber hinaus sind bareword globs global und die
+meisten speziellen Variablen sind... speziell.
+
+Daraus ergeben sich folgende Formen:
+
+  $main::form           - expliziter namespace main
+  $::form               - impliziter namespace main
+  open FILE, "file.txt" - FILE ist global
+  $_                    - speziell.
+
+(Ja, da fehlen noch ein paar Sachen, ich weiß)
+
+Im Gegensatz zu PHP gibt es kein Schlüsselwort wir "global" mit dem man
+importieren kann, my, our und local machen was anderes.
+
+  my $form              - lexikalische Variable, gültig bis zum Ende des scopes
+  our $form             - $form referenziert ab hier $PACKAGE::form.
+  local $form           - Alle Änderungen an $form werden am Ende des scopes zurückgesetzt
+
+Warum ist das ein Problem?
+--------------------------
+
+Das erste Problem ist FCGI.
+
+sql-ledger hat fast alles im globalen namespace abgelegt, und erwartet, dass es
+da auch wiederzufinden ist. Unter FCGI müssen diese Sachen auch wieder
+aufgeräumt werden, damit sie nicht in den nächsten Request kommen. Einige
+Sachen wiederum sollen nicht gelöscht werden, wie zum Beispiel
+Datenbankverbindungen, weil die ne Ewigkeit zum initialisieren brauchen.
+
+Das zweite Problem ist strict.
+
+Unter strict werden alle Variablen die nicht explizit mit Package, my oder our
+angegeben werden als Tippfehler angemarkert, was einen vor so mancher Stunde
+suchen nach einem Bug erspart. Da globale Variablen aber implizit mit Package
+angegeben werden, werden die nicht geprüft, und ein Tippfehler da fällt
+niemandem auf.
+
+Kanonische globale Variablen
+----------------------------
+
+Um dieses Problem im Griff zu halten gibt es einige wenige globale Variablen,
+die kanonisch sind, und alles andere sollte anderweitig umhergereicht werden.
+
+Diese Variablen sind im Moment die folgenden neun:
+
+  $::form
+  %::myconfig
+  $::locale
+  $::lxdebug
+  $::auth
+  $::lx_office_conf
+  $::instance_conf
+  $::dispatcher
+  $::request
+
+Damit diese nicht als Müllhalde misbrauch werden, im Folgenden eine kurze
+Erläuterung was man von denn erwarten kann.
+
+
+$::form
+
+- Ist ein Objekt der Klasse "Form"
+- Wird nach jedem Request gelöscht
+- Muss auch in Tests und Konsolenscripts vorhanden sein.
+- Enthält am Anfang eines Requests die Requestparameter vom User
+- Kann zwar intern über Requestgrenzen ein Datenbankhandle cachen, das wird
+  aber momentan absichtlich zerstört
+
+$::form wurde unter sql ledger als Gottobjekt für alles misbraucht. Sämtliche alten
+Funktionen unter SL/ mutieren $::form, das heißt, alles was einem lieb ist,
+sollte man vor einem Aufruf von zum Beispiel IS->retrieve_customer  in Sicherheit bringen.
+
+Das Objekt der Klasse Form  hat leider im Moment noch viele zentrale Funktionen
+Gdie vom internen Zustand abhängen, deshalb bitte nie einfach zerstören oder
+überschreiben. Es geht ziemlich sicher etwas kaputt.
+
+$::form ist gleichzeitig der Standard Scope in den Template::Toolkit Templates
+ausserhalb der Controller, der Ausdruck [% var %] greift auf $::form->{var} zu.
+Unter Controllern ist der Standard Scope anders, da lautet der Zugriff [%
+FORM.var %]. In Druckvorlagen sind normale Variablen ebenfall im $::form Scope,
+d.h. <%var%> zeigt auf $::form->{var}. Innerhalb von Schleifen
+wird $::form->{TEMPLATE_ARRAYS}{var}[$index] bevorzugt wenn vorhanden.
+
+
+%::myconfig
+
+- Das einzige Hash unter den globalen Variablen
+- Wird spätestens benötigt wenn auf die Datenbank zugegriffen wird
+- Wird bei jedem Request neu erstellt.
+- Enthält die Userdaten des aktuellen Logins
+- Sollte nicht ohne Filterung irgendwo gedumpt werden oder extern serialisiert
+  werden, weil da auch der Datenbankzugriff für diesen user drinsteht.
+- Enthält unter anderem Listenbegrenzung vclimit, Datumsformat dateformat und
+  Nummernformat numberformat
+- Enthält Datenbankzugriffinformationen
+
+%::myconfig ist im Moment der Ersatz für ein Userobjekt. Die meisten Funktionen,
+die etwas anhand des aktuellen Users entscheiden müssen befragen %::myconfig.
+
+
+$::locale
+
+- Objekt der Klasse "Locale"
+- Wird pro Request erstellt
+- Muss auch für Tests und Scripte immer verfügbar sein.
+- Cached intern über Requestgrenzen hinweg benutzte Locales
+
+Lokalisierung für den aktuellen User. Alle Übersetzungen, Zahlen- und
+Datumsformatierungen laufen über dieses Objekt.
+
+
+$::lxdebug
+
+- Objekt der Klasse "LXDebug"
+- Wird global gecached
+- Muss immer verfügbar sein, in nahezu allen Funktionen
+
+$::lxdebug stellt Debuggingfunktionen bereit, wie "enter_sub" und "leave_sub",
+mit denen in den alten Modulen ein brauchbares Tracing gebaut ist, "log_time",
+mit der man die Wallclockzeit seit Requeststart loggen kann, und  "message" und
+"dump" mit denen man flott Informationen ins Log packen kann.
+
+
+$::auth
+
+- Objekt der Klasse "SL::Auth"
+- Wird global gecached
+- Hat eine permanente DB Verbindung zur Authdatenbank
+- Wird nach jedem Request resettet.
+
+$::auth stellt Funktionen bereit um die Rechte des aktuellen Users abzufragen.
+Obwohl diese Informationen vom aktuellen User abhängen wird das Objekt aus
+Geschwindigkeitsgründen nur einmal angelegt und dann nach jedem Request kurz
+resettet.
+
+
+$::lx_office_conf
+
+- Objekt der Klasse "SL::LxOfficeConf"
+- Global gecached
+- Repräsentation der config/lx_office.conf[.default] Dateien
+
+Globale Konfiguration.
+
+Configdateien werden zum Start gelesen, und nicht mehr angefasst. Es ist
+derzeit nicht geplant, dass das Programm die Konfiguration ändern kann oder
+sollte.
+
+Der Konfigurationskey
+
+  [Debug]
+
+  file = /tmp/lxoffice_debug_log.txt
+
+ist im Programm als $::lx_office_conf->{Debug}{file} erreichbar.
+
+Warnung: Zugriff auf die Konfiguration erfolgt im Moment über Hashkeys, sind
+also nicht gegen Tippfehler abgesichert.
+
+
+$::instance_conf
+
+- Objekt der Klasse "SL::InstanceConfiguration"
+- wird pro Request neu erstellt.
+
+Funktioniert wie $::lx_office_conf, speichert aber Daten die von der Instanz
+abhängig sind. Eine Instanz ist hier eine Mandantendatenbank. Prominentestes
+Datum ist "eur", die Information ob Bilanz oder Einnahmenüberschussrechnung
+gemacht wird.
+
+
+
+$::dispatcher
+
+- Objekt der Klasse "SL::Dispatcher"
+- wird pro Serverprozess erstellt.
+- enthält Informationen über die technische Verbindung zum Server
+
+Der dritte Punkt ist auch der einzige Grund warum das Objekt global gespeichert
+wird. Wird vermutlich irgendwann in einem anderen Objekt untergebracht.
+
+
+
+$::request
+
+- Hashref
+- Wird pro Request neu initialisiert.
+- Keine Unterstruktur garantiert.
+
+$::request ist ein generischer Platz um Daten "für den aktuellen Request"
+abzulegen. Sollte nicht für action at a distance benutzt werden, sondern um
+lokales memoizing zu ermöglichen, das garantiert am Ende des Requests zerstört
+wird.
+
+Vieles von dem was im moment in $::form  liegt sollte eigentlich hier liegen.
+Die groben Differentialkriterien sind:
+
+- Kommt es vom User, und soll unverändert wieder an den User?
+  => $::form, steht da eh schon
+
+- Sind es Daten aus der Datenbank, die nur bis zum Ende des Requests gebraucht werden?
+  => $::request
+
+- Muss ich von anderen Teilen des Programms lesend drauf zugreifen?
+  => $::request, aber Zugriff über Wrappermethode
index d567c56..df9f6bf 100755 (executable)
@@ -66,6 +66,7 @@ sub lxinit {
   $::form          = Form->new;
   $::auth          = SL::Auth->new;
   $::instance_conf = SL::InstanceConfiguration->new;
+  $::request       = { };
 
   die 'cannot reach auth db'               unless $::auth->session_tables_present;
 
index fb6ef7e..5a7a122 100755 (executable)
@@ -63,6 +63,7 @@ sub setup {
   $::auth         = SL::Auth->new();
   $::user         = User->new($login);
   %::myconfig     = $auth->read_user($login);
+  $::request      = { };
   $form->{script} = 'rose_meta_data.pl';
   $form->{login}  = $login;
 
index 1931b6a..66e81e7 100755 (executable)
@@ -43,6 +43,7 @@ sub lxinit {
   $::cgi     = CGI->new qw();
   $::form    = Form->new;
   $::auth    = SL::Auth->new;
+  $::request = { };
 
   die 'cannot reach auth db'               unless $::auth->session_tables_present;
 
index 232dca6..14e0445 100644 (file)
@@ -7,7 +7,7 @@ use Support::Files;
 my (@globals, $testcount);
 
 BEGIN {
-  @globals = qw(lxdebug auth myconfig form cgi lx_office_conf locale dispatcher instance_conf);
+  @globals = qw(lxdebug auth myconfig form cgi lx_office_conf locale dispatcher instance_conf request);
   $testcount = scalar(@Support::Files::testitems);
 }