Johnny B.: Datenbankhandle an Subroutine übergeben

Hallo geehrtes Forum,

ich habe in meinem Script ein Datenbankhandle:

my $db_go = DBI->connect( "DBI:mysql:$name_db", $username_db, $password_db, { RaiseError => 1 } );

Nun möchte ich Teile des Scriptes in ein Modul mit eigenem Namensraum (per Require aufgerufen) auslagern. Zur Zeit funktioniert dies so:

  
HAUPTSCRIPT:  
add_update({    tabelle => 'tabellenname',  
                daten   => $fields,  
                db_go   => $db_go,  
            });  
  
MODUL:  
sub add_update {  
    my ( $arg_ref ) = @_;  
    my $tabelle   = $arg_ref->{tabelle};  
    my $fields    = $arg_ref->{daten};  
    my $db_go     = $arg_ref->{db_go};  

Auf diese Weise kann ich das Datenbankhandle in der Subroutine weiter verwenden. Ich frage mich gerade, ob es so optimal ist. Ich stehe vor drei Alternativen:

1. lassen so wie es ist
   Nachteil: der ewig gleiche Parameter $db_go bei jedem Aufruf

2. $db_go als globale Variable definieren
   use vars qw( $db_go );
   Vorteil: der gleiche Parameter fällt weg
   Nachteil?

3. in der Subroutine ein neues Datenbankhandle aufmachen
   Vorteil: der gleiche Parameter fällt weg
   Nachteil: mehrere Handles = weniger Performance?
             könnte später zu Verwirrung führen, wenn im Hauptscript ein anderes Datenbankhandle geöffnet wird

Der Versuch, innerhalb der Subroutine auf diesem Weg auf die Variable zuzugreifen, führt nicht zum Ziel und ist wahrscheinlich auch pfuibäh?
    my $db_go     = $main::db_go;

Ich tendiere momentan zu der Lösung mit der globalen Variable. Ist das schlau?

Besten Gruß
JOhnnY

  1. Das hängt schwer davon ab, ob es wirklich immer nur die eine Variable geben wird, oder ob irgendwann mal vielleicht doch eine zweite parallele Verbindung benötigt wird.
    Das Vorhandensein des Parameters an sich finde ich noch keinen Nachteil.

    1. Hallo Encoder,

      Das hängt schwer davon ab, ob es wirklich immer nur die eine Variable geben wird, oder ob irgendwann mal vielleicht doch eine zweite parallele Verbindung benötigt wird.

      schwer zu sagen. Ich wüßte nicht, wann das der Fall sein müßte. Ich weiß allerdings nichts über das interne Verhalten der Datenbankzugriffe, wie das organisiert ist und wie teuer eine neue Verbindung ist. Bisher konnte ich alle Queries hintereinander abarbeiten. Zwei parallele Queries lösen sich auf durch einen JOIN, oder verstehe ich das falsch? Also ich sag mal von meinem jetzigen Wissensstand aus: 'Nein. Keine parallelen Verbindungen.'

      Das Vorhandensein des Parameters an sich finde ich noch keinen Nachteil.

      ja, naja, also da er unveränderbar in jedem Funktionsaufruf mitgeliefert werden muß, macht er imho eigentlich nur den Quellcode fett.

      Besten Gruß
      JOhnnY

      1. Zwei parallele Queries lösen sich auf durch einen JOIN, oder verstehe ich das falsch?

        Das kann ich jetzt in keinen für mich sinnvollen Zusammenhang bringen. Ich glaube fast du verstehst es falsch.

        Ein JOIN verknüpft in einer Abfrage zwei Tabellen, um Daten aus beiden Tabellen auszulesen.
        Mehrere Verbindungen bedeuten, du kannst über verschiedene Verbindungen (und somit parallel) Abfragen starten. Jede mit oder ohne JOIN, wie du willst. Aber das eine hat mit dem anderen nichts zu tun.

        ja, naja, also da er unveränderbar in jedem Funktionsaufruf mitgeliefert werden muß, macht er imho eigentlich nur den Quellcode fett.

        Dazu noch ein Gedanke.
        Die Datenbankverbindung würde ich mir (wie woanders auch schon erwähnt wurde) sowieso als zentrales Objekt halten.
        Ich würd mir nur überlegen, ob die einzelnen Funktionen oder Methoden zum Zugriff auf die Datenbank ihre Verbindung selber von diesem zentralen Objekt holen sollen, oder ob du ihnen die mitgibst.
        Das heißt also, soll die Methode selber wissen wo das Handle ist, oder will der Aufrufer deiner Methode sich das aussuchen können.

        1. Hallo Encoder,

          Mehrere Verbindungen bedeuten, du kannst über verschiedene Verbindungen (und somit parallel) Abfragen starten. Jede mit oder ohne JOIN, wie du willst. Aber das eine hat mit dem anderen nichts zu tun.

          Ja, das hab ich wohl durcheinander bekommen. Ich kann mir momentan noch keine Notwendigkeit für parallele Abfragen vorstellen. Gibt es bestimmt und reichlich, aber vielleicht erst für die Profis...

          Dazu noch ein Gedanke.
          Die Datenbankverbindung würde ich mir (wie woanders auch schon erwähnt wurde) sowieso als zentrales Objekt halten.

          ja, cool. So kann ich mir das gut vorstellen. Hast Du eventuell noch eine Pflegeanleitung für mein Datenbankhandle? ;-)

          Das heißt also, soll die Methode selber wissen wo das Handle ist, oder will der Aufrufer deiner Methode sich das aussuchen können.

          woOow, schöne Frage. Ich versteh leider nicht im Ansatz, worum es geht: Methoden können wissen, wo Handles sind und Aufrufer können es sich aussuchen? WTF? Ich freu mich schon auf die Zeit, wenn ich diesen OOP-Style gelernt habe. Was für eine Welt...

          Besten Gruß
          JOhnnY

          1. Ich kann mir momentan noch keine Notwendigkeit für parallele Abfragen vorstellen.

            Kommt eher selten vor, vor allem in Webgeschichten würd ichs kaum vermuten.

            Hast Du eventuell noch eine Pflegeanleitung für mein Datenbankhandle? ;-)

            Das braucht keine Pflege, erstells und weise es irgendwo zu, dann passt das.

            Methoden können wissen, wo Handles sind

            indem du in der Methode auf das globale Handle zugreifst. Dann muss die Methode (bzw. eher der, der die Methode schreibt) wissen wo das globale Handle ist.

            und Aufrufer können es sich aussuchen?

            Ein Aufrufer kann ja auch das globale Handle als Aufrufparameter in die Methode mitgeben. Dann nimmt die Methode dieses Handle das sie da bekommt, egal welches das ist. In dem Fall kann sich der Aufrufer aussuchen, welches Handle er übergibt.

            Das hat übrigens noch nicht viel mit oo zu tun. Da gehts nur darum, woher ein Wert kommt.

            Vielleicht solltest du fürs erste noch gar nicht so sehr drüber nachdenken wie du alles perfekt machst. Ich hör da irgendwie raus dass du noch nicht ganz so fit bist. Dann hast du dir wahrscheinlich auch erst mal ein kleineres Projekt rausgesucht, bei dem es noch nicht um Leben und Tod geht.
            Mach am besten erst mal etwas das überhaupt funktioniert und dann denk langsam weiter.

  2. Ein Singleton wäre hier sinnvoll.

    1. Hallo Pragma,

      Ein Singleton wäre hier sinnvoll.

      Zitat des Artikels: "Es besteht die große Gefahr, durch exzessive Verwendung von Singletons quasi ein Äquivalent zu globalen Variablen zu implementieren und damit dann prozedural anstatt objektorientiert zu programmieren[1]."

      Hhhhmmmm. Objektorientierte Programmierung ist für mich noch ein Buch mit 6,5 Siegeln. Bei dem Artikel kann ich hinter jedes dritte Wort ein Fragezeichen stellen. Objekt, Klassen, Methoden - puh. Wahrscheinlich alles gar nicht so schwer, aber momentan bin ich noch ein old-school-prozedual-Programmierer.

      Ich kann inzwischen OO-Module anwenden, wobei mir oftmals selbst dabei nicht 50% klar ist, was genau ich da tue. Daher spreche ich auch einfach von $db_go als einer Variablen. Es ist wohl vielmehr ein Objekt mit Klassen und Methoden...

      Besten Gruß
      JOhnnY

      1. Zitat des Artikels: "Es besteht die große Gefahr, durch exzessive Verwendung von Singletons quasi ein Äquivalent zu globalen Variablen zu implementieren und damit dann prozedural anstatt objektorientiert zu programmieren[1]."

        Man braucht aber nunmal in ziemlich jedem Programm oder System Werte, die es a) einmalig geben soll und b) die überall verfügbar sein müssen.
        Zum Beispiel eine Konfiguration, oder eben ein DB-Handle.

        Man kann sich ja ein Singletonobjekt machen, das die ganzen Variablen enthält. Statt lauter einzelner Singletonvariablen. Dann hat man sein Gewissen beruhigt und trotzdem funktionierts noch :-)

  3. h1,

    Ich tendiere momentan zu der Lösung mit der globalen Variable. Ist das schlau?

    Es ist nicht unschlau. Wohin ich jedoch tendiere: Betrachte einen Datensatz als Objekt mit Eigenschaften und Methoden. Dann hast Du es nur noch mit dem Objekt zu tun.

      
    use AccessLog; # Klasse fürs Loggen der Seitenzugriffe  
    my $obj = AccessLog->new();  
    $obj->update; # fertisch  
    
    

    Siehste irgendwow einen DB-Handle im Code? ;-)

    Hotti