Sven Rautenberg: Guter Code-Analysator

Beitrag lesen

Moin!

Das stimmt zwar, aber es gibt noch viele andere Beispiele, die man so nicht lösen kann.

Bsp:
<?php
$db = new DB;
$db->query("SELECT * FROM $tb_user");
?>

Mit vernünftiger Ausgestaltung der Klassen wird es zu so einem Konstrukt niemals kommen, weil das so abläuft:

  
<?php  
$db = new DB;  
$db->getUserList();  
  
class DB  
{  
  var $dbconnect;  
  var $lasterror;  
  
  function DB ()  
  {  
    $this->dbconnect = mysql_connect(...);  
    mysql_select_db(...);  
  }  
  
  function selectquery($select)  
  {  
    $result = array();  
    if ($res = mysql_query($select))  
    {  
      while ($cell=mysql_fetch_assoc($res))  
      {  
        $result[] = $cell;  
      }  
      return $result;  
    }  
    else  
    {  
      $this-lasterror = mysql_error();  
      return false;  
    }  
  }  
  
  function getUserList()  
  {  
    return $this->selectquery("SELECT spalte1, spalte2 FROM usertabelle");  
  }  
  
}  
?>  

Der SQL-Code bleibt so schön separat und nur in der DB-Klasse, und an jeder Stelle, die was von der Datenbank will, muß man sich halt eine Methode definieren, die die entsprechende Abfrage realisiert.

Vorteil: Es taucht nirgendwo sonst mehr SQL-Code auf, nur noch in der SQL-Klasse. Das hat den unschätzbaren Vorteil, dass man, sollte sich an der Datenbank was ändern (neue Version, vollkommen anderes Programm, neue/ergänzte Struktur), ausschließlich in dieser DB-Klasse etwas verändern muß.

Und durch das eindeutig durch die Methoden definierte Interface kann es eigentlich auch keine Anpassungsprobleme geben, denn die Methode muß einfach nur sicherstellen, dass das Interface eingehalten wird - völlig unabhängig davon, ob sich beispielsweise die User-Tabelle nun vollkommen anders strukturiert, weil sie sich z.B. künftig nur noch per JOIN auslesen läßt, um an die gewünschte Information zu kommen.

Und sollte es mal tatsächlich der Fall sein, dass die Datenbankperformance gesteigert werden muß, würde man in der Datenbankklasse ansetzen und z.B. Caching einbauen können, oder andere geschwindigkeitsfördernde Initiativen ergreifen. Alles jeweils ohne notwendige Eingriffe in den restlichen Programmcode.

Wenn die Tabellen-Namen variable gehalten werden müssen, aufgrund eines Prefix wie es bei jedem größerem Massenscript der Fall ist (z.B. phpBB), dann würde ich pro SQL Anweisung also einen Meldung erhalten.
Zwar könnte ich mit Konstaten arbeiten, z.B. so:
$tabelle = "";
$db->quer("SELECT * FROM _tabelle_","TB_USER");

Das wäre aber in meinen Augen umständlich, denn die Class müsste erst _tabelle_ durch $tb_user ersetzen (oder ähnliches).

Da ja der SQL-Code sowieso in der Klasse steht, mußt du dich im restlichen Programmcode ja gar nicht damit rumschlagen. Die korrekte Ersetzung des Tabellennamens mit Prefix etc. ist allein Sache der Klasse, und diese Information liest sie natürlich aus der globalen Konfiguration aus, die diese Informationen am Besten als echte PHP-Konstante verfügbar macht, denn Konstanten sind automatisch global verfügbar - also auch in der DB-Klasse.

Zu leicht werden diese zwei Dateien - ggf. unabsichtlich - getrennt und funktionieren einzeln dann nicht mehr wie geplant.
Wenn man aber bestimmte Config Dateien Variable halten muss, dann wird das nicht funktionieren.

Ich hab nicht behauptet, dass der Code-Analysator von Zend supertoll ist. Wie gesagt, ich benutze gar keinen, weil ich das nicht brauche.

Analysiert man per Zend-Code-Analyse z.B. die profile.php (2600 Zeilen) vom vBB 3.x, so erhält man fast 200 Meldungen.
Bei der admincp/user.php (2200 Zeilen) sind es sogar fast 500 Melunden.
Ich glaube kaum das man dort von "schlampiger" Programmierung seitens vBulletin sprechen kann.

Naja, viele dieser Boards sind tatsächlich schlampig programmiert, weil sie schlampig begonnen wurden, und heutzutage niemand mehr gegen diesen gewachsenen Code ankommt, um dort vernünftige Programmierrichtlinien unterzubringen. Und einen Start von Null zu wagen ist eben auch extrem aufwendig.

Die übliche Vorgehensweise wäre, zu Beginn

$fehler = "";


> Das ist mir ja auch alles bekannt, aber bei ~1000 Zeilen Code kann es passieren, sollte aber nicht, dass eine Variable durchrutsch.  
  
Und deswegen gibts eben gewisse Dinge, die man unbedingt tun sollte. Register\_globals auf off und beim Entwickeln alle Meldungen an, auch Notice.  
  

> Und damit es kein folgen schweren Fehler gibt, sollte eine Maschine den Code gegenprüfen.  
  
Wie schon erwähnt: Es gibt tausende Möglichkeiten, in seinen Code Müll einzubauen, den sogar Menschen nicht erkennen.  
  
Und wirklich beweisbar sicheren Code zu schreiben, ist sehr teuer und wird nur in den üblichen Ausnahmefällen wie bei Atomkraftwerken, in der Flugsicherheit oder der Raumfahrt eingesetzt.  
  
 - Sven Rautenberg

-- 
My sssignature, my preciousssss!