2009-02-27 10 views
3

Ich arbeite an einer bestimmten Anwendung, schreibe immer wieder sehr ähnliche Abfragen, immer wieder. Sie sind nicht genau gleich, sondern haben eine sehr ähnliche Form und sind in fast identische Codestücke eingebettet, z. B. .,DRY und ähnliche Abfragen

$Mysqli = new mysqli; 
if ($Stmt = $Mysqli->prepare("SELECT foo 
           FROM tblFoo 
           WHERE something = ?")) { 
    $Stmt->bind_param('s', $this->_something); 
    $Stmt->execute(); 
    if (0 != $Stmt->errno) 
     throw new Exception("blah, blah, blah"); 
    $Stmt->bind_result($foo); 
    while ($Stmt->fetch()){ 
     $this->_foos[] = new Foo($foo); 
    } 
    $Stmt->close(); 
    } else { 
     throw new Exception("blah, blah, blah");); 
    } 
} 

und später woanders ...

$Mysqli = new mysqli; 
if ($Stmt = $Mysqli->prepare("SELECT bar, baz 
           FROM tblBar 
           WHERE somethingElse = ?")) { 
    $Stmt->bind_param('s', $this->_somethingElse); 
    $Stmt->execute(); 
    if (0 != $Stmt->errno) 
     throw new Exception("blah, blah, blah"); 
    $Stmt->bind_result($bar, $baz); 
    while ($Stmt->fetch()){ 
     // do something else with $bar and $baz 
    } 
    $Stmt->close(); 
    } else { 
     throw new Exception("blah, blah, blah");); 
    } 
} 

... und dann noch einen, und eine andere an anderer Stelle ... etc.

Ist dies eine echte Verletzung von DRY ? Es scheint nicht sinnvoll zu sein, eine Klasse zum Ausführen dieser Art von Abfrage (mit Konstruktorparametern oder Setter für Tabelle, Spalte, gebundene Variablen usw.) zu schreiben und sie dann in meiner gesamten App wiederzuverwenden. Aber gleichzeitig kann ich dieses quälende Gefühl, dass ich mich wiederhole, nicht abschütteln.

Vielleicht ist es nur so, dass es nur so viele Möglichkeiten gibt, eine einfache Abfrage zu schreiben und dass eine gewisse Anzahl von Wiederholungen wie diese zu erwarten ist.

Gedanken?

Antwort

1

Viele Menschen tun genau dies. Erstellen Sie eine Klasse für jede Tabelle, die alle von derselben Klasse erben. Die Basisklasse kann die Daten laden und speichern. Wenn Sie die Daten laden möchten, rufen Sie einfach die Methode load auf. Und Sie können die Feldwerte über die Eigenschaften der Objekte festlegen und darauf zugreifen.

Es gibt auch Bibliotheken wie hibernate, die eine Menge schmutzige Arbeit für Sie erledigen.

+0

@Kibbee - Danke. Ich werde nicht Hibernate verwenden, aber ich habe eine ActiveRecord-Klasse erstellt und dann einige Klassen für bestimmte Tabellen substriert. – PartialOrder

1

Ich würde sagen, es war eine Verletzung. Von einem Blick auf Ihren Code (wenn ich etwas nicht vermisse), sind diese beiden Aussagen identisch mit Ausnahme der Strings "foo" und "bar" (einige Male wiederholt) und Ihrer eigentlichen Geschäftslogik.

Zumindest könnten Sie das extrahieren. Genauer gesagt sollten alle SQL-Strings wahrscheinlich extrahiert werden. Sie sind mir immer mehr wie Daten erschienen als Code. Wenn Sie ein Array von SQL-Strings, -Tabellen usw. hätten - würde das das Refactoring offensichtlicher machen?

(Strings und andere Daten aus dem Code extrahiert eine gute Möglichkeit ist es, ein Refactoring zu beginnen)

Eine Möglichkeit, wenn Sie ein Objekt haben, das hatte die Tabellennamen und ein Verfahren mit Ihrer Business-Logik, könnten Sie passieren es in einen "Prozessor" mit dem ganzen boilerplate (das ist der ganze Rest des Codes, den Sie dort haben).

Ich denke, das könnte es trocken machen.

(PS. Bevorzugen immer Komposition der Vererbung. Es gibt keinen Vorteil ist die Vererbung über eine Klasse zu verwenden, die Ihre Objekte „Run“ können)

+0

@ Bill K. Dies war ein knapper Anruf, aber ich ging mit Kibbee's Antwort, weil es ein bisschen näher ist, wie ich damit eigentlich fertig wurde. Ihre Kommentare waren auch sehr hilfreich - besonders beim Extrahieren von Strings als ein erster Schritt beim Refactoring. +1 Danke! – PartialOrder

0

Sie sind einer der ersten Wünsche der Begegnung modularisieren. :-)

Es gibt zwei allgemeine Lösungen. Die erste besteht darin, den Aufruf für alle (oder die meisten) ähnlichen Abfragen zu abstrahieren. Und dann noch einmal zu einer anderen Reihe von Abfragen. Und dann zu einem anderen. Und so weiter. Leider führt dies zu zahlreichen Blöcken, die dasselbe tun: eine Abfrage aufrufen, nach Problemen suchen, eine Ergebnismenge zusammenstellen und sie zurückgeben. Es ist eine DAL, aber nur von einer Art. Es skaliert auch nicht.

Die zweite Lösung besteht darin, den Prozess zum Erstellen einer Abfrage und zum Zurückgeben des Ergebnisses zu abstrahieren und anschließend den Datenzugriff abstrahieren zu lassen (was im Grunde bedeutet, dass Sie etwas erstellen, das SQL zusammenstellt). Dies ist eher eine richtige ORM als eine einfache DAL. Es ist viel einfacher, dies zu skalieren.