Warum ich so bei Rails meine Zweifel habe

könnte klar werden, wenn man sich den Artikel hier durchliest: Choose a single layer of cleverness (Loud Thinking) - ja, genau, seine Meinung ist, raus mit Referentieller Integrität, Stored Procedures und Triggern aus der Datenbank, weil er die alle in seinem Code halten will. Wie wärs mit "das Kind mit dem Bade ausschütten"?

Das ist sowas von peinlich, das ich schon fast nicht mehr weiss ob ich nicht drüber lachen sollte - aber eines werd ich sicherlich nicht: meine Karten auf so ein Pferd setzen ...

Hemdsärmelige Ansätze mit einfachen, pfiffigen Lösungen die auch mal gegen Konventionen verstossen sind ok (und wichtig - sonst würden wir alle bei Java und J2EE landen ...) - aber wenn die Programmierung nur noch aus aneinandertackern von halbgaren Lösungen besteht, dann halt ich mich da lieber raus. Da könnte ich ja auch gleich PHP benutzen ...

tags: Programmierung, Ruby

ralle Sept. 28, 2005, 9:22 a.m.

Naja, hast Du schon einmal eine Applikation "geerbt", wo die Applikationslogik teilweise in die Datenbank ausgelagert wurde? Von "stored procedures" habe ich die Nase gestrichen voll, sie haben die Tendenz "unmaintable" Applikationen zu erleichtern.

Aber ich schreibe ja auch PHP, bin daher sowieso kein "real programmer". ;-)

P.S.: "Wie ist der Nachname von Georg Bauer?" Das ist zu schwierig für mich, mal schauen ob dieser Kommentar überhaupt erscheinen wird. ;-)

hugo Sept. 28, 2005, 9:38 a.m.

Klar, auch mit Stored Procedures kann man einen grossen Haufen Mist machen - und ein altes gewachsenes System zu debuggen kann da manchmal schon ziemlich in Nerverei ausarten. Aber stored procedures sind ein sehr wichtiges Mittel zur besseren Partitionierung einer Anwendung über die Systemlayer - und damit ein sehr wichtiges Werkzeug der Performanceoptimierung. Es ist eben manchmal schlichtweg die bessere Idee wenn Code möglichst nah bei den Daten ausgeführt wird.

Und was Trigger und Referentielle Integrität und Value-Constraints angeht - die sind essentiell. Viel zu viele Programmierer schludern dabei und legen eigentlich die ganze Logik in die Anwendung - was dann ziemlich scheisse ist, wenn weitere Systeme auf die gleiche DB zugreifen, weil deren Zugriffe eben nicht mehr den Validitätsregeln unterliegen und damit inkonsistente Daten vorprogrammiert sind ... (denk einfach an die typischen Maintenance-Jobs oder Adhoc-Tools zur Datenumstellung etc.).

Was PHP angeht: ich habe viel zu viele PHP-Anwendungen gesehen die _alles_ in PHP machen und SQL nur als verhärmte Datenablage benutzen. Was ausgesprochen dämlich ist, denn wenn man das macht, nimmt man lieber Datenbanksysteme die explizit für diese Art der Arbeitsweise geeignet sind. Denn SQL ist dann nur noch unnötiger Overhead. SQL macht nur Sinn wenn man wirklich die SQL-Möglichkeiten auch voll nutzt. Andererseits werden in PHP-Anwendungen SQL-Statements auch immer noch aus reinen Strings zusammengedengelt, anstelle prepared statements zu benutzen - was SQL-Injection Tür und Tor öffnet (und dann über diesen Weg Tür und Tor beim Server öffnet). Sowas kann ich einfach nicht ernst nehmen :-)

Gerd Riesselmann Sept. 28, 2005, 10:44 a.m.

Jein. Die Frage nach Stored Procedures et al lässt sich nicht generell beantworten, sondern ist anhängig vom Projekt. Für eine durchschnittliche Webapplikation gelten andere Maßstäbe als für eine Fabriksteuerung, die Terrabyte an Daten in Realtime verarbeiten muss.

Datenbank-Abstraktionen, sei es Active Record oder andere objekt-relationale Mapping-Schichten, haben bei Projekten mit durchschnittlichem Datenaufkommen (nicht nur im Web) durchaus ihre Berechtigungen. Denn erstens verhindern sie SQL-Injections, da das Bauen der SQL-Strings zentralisiert ist (weniger Code ist immer sicherer), zweitens reduzieren sie den Entwicklungsaufwand erheblich, da das manuelle Coden struktureller Anwendungsfälle (Update, Delete, Load, Links etc.) wegfällt. Je nach Projekt können das bis zu 80 Prozent des Business-Codes sein! Und drittens erhöht das natürlich auch die Wartbarkeit und senkt die Fehlerwahrscheinlichkeit.

Ich habe bisher jedenfalls für jedes meiner Projekte solche Abstraktionsschichten geschrieben oder externe verwendet und bin damit immer gut gefahren. Dies setzt erst mal strikte Benennungsregeln für Tabellen und Felder voraus,die dann mittels Reflection ermittelt werden können. Natürlich muss es aber möglich sein, bei eventuellen Performance-Engpässen lokal manuelle Optimierungen einzubauen, dies ist aber nachgeordnet und passiert nur, wenn es wirklich nötig ist.

Wo ich dir aber 100 Prozent Recht gebe ist die referenzielle Integrität und andere Contraints (zum Beispiel Enums in MySQL). Dieses Feature einer DB ist wirklich unverzichtbar, weshalb ich bei MySQL nie ISAM-Tables verwende, sondern immer auf die Inno DB gehe. Einerseits weil das Code spart (warum ein vorhandenes DB-Feature noch mal programmieren und eventuell Fehler einbauen?), anderseits weil es eine zusätzliche Sicherung einbaut, gerade wenn man mal von außerhalb der Applikation auf die DB zugreifen muss, wie du ja richtig sagst.

Bei Triggern bin ich da vorsichtiger. Mir wäre lieber ich könnte Contraints besser definieren als mich da auf Trigger verlassen zu müssen, zumindest Oracle kommt mir da immer etwas fimschig vor und invalide Trigger können die Pest sein. Und wenn man Trigger benutzt um Daten in Tabelle B upzudaten, wenn Tabelle A geändert worden ist, dann stimmt ganz einfach das Design nicht :-).

PS: Ist der Vorname von Georg Bauer nicht Hugo? ;-)

hugo Sept. 28, 2005, 11:05 a.m.

Es geht nicht drum das ich was gegen ORMs oder ähnliche Abstraktionsschichten hätte - beiweitem nicht. Aber Stored Procedures sind eben einfach eine _weitere_ Schicht - die aber auf dem DB-Server läuft. Wenn du Webanwendungen mit 500-600 Hits pro Minute hast, dann denkst du über sowas nach (das Gesamtsystem hat zeitweilig über 2000 Hits pro Minute abzuwickeln - davon aber ein guter Teil statischer Inhalt). Denn ohne entsprechende Optimierungen wirds dann schnell ekelig. Und Stored Procedures sind da ein ganz wichtiges Werkzeug (beileibe nicht das einzige natürlich).

Stored Procedures sind ja auch der Grundmechanismus erweiterter Triggerprogrammierung - und die ist essentiell um zum Beispiel Schattentabellen mit kumulierten Werten zu führen. Sowas ist wirklich sehr wertvoll wenn man z.B. wie ich häufiger mit Datenmodellen ausserhalb des normalen Content-Bereiches zu tun hat (obwohl auch bei Content-Systemen zum Beispiel die Kalenderansicht bei genügend vielen Einträgen in der DB durchaus von Schattentabellen profitiert).

Gerade die Schattentabellen aber wiederum harmonieren sehr gut mit ORMs - es sind halt weitere Tabellen die angesprochen werden können, nur das sie eben automatisch gefüllt werden und nicht über den ORM vom Programm. Gerade sowas von der Anwendung aus zu machen wäre saublöd, denn die dafür nötigen mehrfachen SQL-Kommandos reissen dann die Performance durch den mehrfachen Turnaround App-Server zu DB-Server wieder runter.

Es gibt halt durchaus sehr gute Gründe warum es sowas wie Stored Procedures gibt. Das hat nix mit "Oracle will die Welt kontrollieren und die Applikation gleich mit" wie es von einigen Paranoikern formuliert wird (und wie es auch in dem oben verlinkten Beitrag durchklingt), sondern eben schlicht und einfach damit, das mancher Code schneller läuft, wenn er lokal in der Nähe der Daten abläuft, anstelle über eine Netzverbindung transportiert zu werden ...

Und zu Oracle: sorry, aber trau keiner Datenbank die Leerstrings als NULL speichert ;-)

(und danke: wegen deines PS hab ich mich gerade bei meinem Vornamen vertippt ;-) )

Gerd Riesselmann Sept. 28, 2005, 11:56 a.m.

Das ist natürlich alles richtig. :-)

PS: Ich traue Oracle nicht, weil die mit SQL+ immer noch ein Tool als Standard SQL-Client ausliefern, das nicht einmal die Grund-Features einer Shell draufhat. Das Ding ist doch dümmer als die DOS-Box!