phpbar.de logo

Mailinglisten-Archive

[php] DB-Zugriff bei OO in php4

[php] DB-Zugriff bei OO in php4

Lutz Zetzsche Lutz.Zetzsche at sea-rescue.de
Sam Dez 10 14:09:01 CET 2005


Hi Henning,

Am Freitag, 9. Dezember 2005 16:53 schrieb Henning Heil:
> Meinereiner hat sich bisher immer prozedural durch seine Projekte
> geschlagen, auf meine alten Tage dachte ich aber, ich lerne nochmal was
> dazu und versuche mich mal an Objekten ;-). Naja, von den ER-Modellen
> beherrscht man das ja im Grunde ohnehin schon ganz gut, man muss es
> eigentlich nur noch in entsprechenden code umsetzen.
>
> Konkret: http://nopaste.php-q.net/177340
>
> Ich will nun mein neues Objekt in die DB haben, es geht mir also um die
> Methode saveWishlist(): gehe ich da vor "wie bisher" oder gibt's irgend
> was neues zu beachten?

ja, schon. Objektorientierte Programmierung zwingt dazu, sich mehr über die 
Strukturierung und die Logik Gedanken zu machen. Damit meine ich nicht nur 
die Entwicklung einer sinnvollen Klassenstruktur, sondern auch um die 
sinnvolle Konzeption der Klassen selbst.

Den Fehler, den man am Anfang gerne macht, wenn man von der prozeduralen auf 
die objektorientierte Programmierung umsteigt, ist der Ansatz, den 
prozeduralen Code einfach in objektorientierte Form umzugießen. Das greift 
aber zu kurz. Man muß die Logik ein Bißchen umkehren und vom Objekt her 
denken.

Was bedeutet das jetzt konkret?

In Deiner Klasse WishList verwendest Du drei Eigenschaften: Name, Zeitstempel 
und Status.

Wenn man mit Deiner Klasse ein Objekt anlegt, kann man einen Namen übergeben. 
In dem Augenblick scheint der Name also quasi der eindeutige Schlüssel zu 
sein, der die WishList eindeutig identifizierbar macht. Nehmen wir an, das 
wäre so, dann macht es aber aus meiner Sicht keinen Sinn, mit einer 
set-Methode die Änderung dieses eindeutigen Schlüssels zu erlauben. Außerdem 
müßte im Konstruktur dann auch der Fall abgefangen werden, daß kein Name 
übergeben wird.

Jetzt kommt aber die Funktion saveWishList() ins Spiel. Hier (ge-)brauchst Du 
plötzlich eine eindeutige ID für die WishList. Also ist der Name nicht der 
eindeutige Bezeichner der WishList, sondern eigentlich diese ID. Folglich 
müßte die ID also auch eine Eigenschaft des Objekts werden. Dann hättest Du 
ID, Name, Zeitstempel und Status.

Dann wiederum stellt sich aber die Frage, wo Du die ID beim Anlegen des 
Objekts herholst, und ob es dann Sinn macht, den Konstruktur mit dem 
Parameter "Neuer Name" zu versehen. Bzw. wenn Du dem Konstruktor schon was 
übergeben möchtest, solltest Du dann nicht gleich einen Array übergeben 
können, mit dem Du in einem Abwasch direkt alle Objekteigenschaften, die man 
selbst von außen intialisieren darf, entsprechend füllen kannst? Hier spielt 
dann wiederum die Frage hinein, welche Objekteigenschaften beim Anlegen des 
Objekts von außen gesetzt werden können dürfen. Wieviel set und get darf bzw. 
muß sein?

Eine weitere interessante Frage ist, welche der Objekteigenschaften später, 
also nachträglich über set-Methoden änderbar sein dürfen, ohne Konsistenz der 
Daten eines Objekts zu gefährden. Für eine eindeutige ID, die intern 
generiert wird, dürfte das z.B. nicht der Fall sein.

Naja, usw. Es wird sicherlich klar, was ich mit meinen ersten beiden Absätzen 
meinte. :-)


> Ich benutze bisher kein abstraction layer, man lernt ja bekanntlich
> nicht alles an einem Tag - schreibe also dirket nach mysql.

Gut, ok. :-) Trotzdem würde ich den Code so anlegen, daß Du später eine 
verwenden bzw. leicht die Datenbank austauschen kannst. Ich würde also nicht 
datenbankspezifische PHP-Funktionen und SQL über normale Klassen verteilt 
einbauen, sondern würde dafür jetzt schon eine separate Schicht einziehen. 
Allerdings muß man das richtig machen, sonst kann man es auch lassen. :-)

Wenn Du kleine Projekte hast, kannst Du natürlich alles ein Bißchen mischen, 
weil der Anpassungsaufwand im Fall des Falles sehr gering ist. Auch hinter 
meiner Website stehen nur eine Handvoll SQL-Befehle. Das kann ich schnell 
ändern. Für große Projekte, wo vielleicht auch noch im Team dran gewerkelt 
wird, ist das aber nicht ratsam.

Und dann gibt es noch einen Anknüpfungspunkt mit den vorherigen Punkten:

Deine WishList-Klasse wirft für mich ja die oben beschriebenen logischen 
Probleme auf, die für mich, ohne die Anwendung zu der Klasse zu kennen, 
darauf hindeuten, daß Du hier versuchst, Dinge in einer Klasse zu 
kombinieren, die eigentlich in zwei Klassen gehören, nämlich eine "WishList 
in der Anwendung"-Klasse und eine "WishList in der Datenbank"-Klasse, wobei 
letztere dann auf der Datenbankabstraktionsschicht aufsetzt.


> Gibt's 
> ansonsten Anmerkungen zum Code, abgesehen davon

Da ist mir auch noch ein Bißchen aufgefallen. :-) Hauptsächlich geht es um die 
Notationskonventionen.

1. Wenn alle Variablennamen in Englisch sind, solltest Du dabei bleiben und 
nicht plötzlich eine Variable $S_neuerName verwenden.

2. Nur die Konstruktorfunktion wird am Anfang groß geschrieben, alle anderen 
Funktionen am Anfang klein. Also nicht GetTimeStamp(), sondern getTimeStamp() 
schreiben. :-)

3. Du mußt Dich entscheiden, ob eine Funktion get_name() oder getName() nennen 
möchtest, aber nicht einmal Getname(), dann GetTimeStamp() usw. :-) In diesem 
Zusammenhang solltest Du dann auch eine einheitliche Schreibweise für 
Wishlist definieren, also entweder Wishlist oder WishList, aber nicht mal so 
und mal so. :-)

4. Variablen und Funktionen, die von der Logik her "private" sein sollen, 
sollten mit einem Unterstrich beginnen, damit man sie als solche erkennen 
kann, also z.B. wären nach der reinen OOP-Lehre alle Eigenschaften "private", 
damit sie, wenn überhaupt, nur über get- und set-Methoden gelesen und 
geschrieben werden. :-)


Das sind so meine allgemeinen Gedanken aus eigener Erfahrung. Mein Einstieg in 
OOP ist auch noch nicht so lange her - gerade mal drei Jahre. :-)


Und gerade muß ich wieder an diese Diskussion denken: "Why getter and setter 
methods are evil"... Mal schnell gegoogelt - und hier ist ein Artikel dazu:

	http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html

Der Artikel stützt meine Eingangsaussagen und sagt noch viel mehr. Da finden 
sich so nette Sätze wie:

"The most difficult problem in teaching object-oriented programming is getting 
the learner to give up the global knowledge of control that is possible with 
procedural programs, and rely on the local knowledge of objects to accomplish 
their tasks. Novice designs are littered with regressions to global thinking: 
gratuitous global variables, unnecessary pointers, and inappropriate reliance 
on the implementation of other objects."

Oder:

"Getter/setter methods often make their way in code because the coder was 
thinking procedurally."

Objekte verwenden und objektorientiert programmieren, ist also nicht dasselbe. 
Ersteres ist leicht, letzteres das Ziel. Und dazwischen lauert immer die 
Gefahr, in prozedurales Denken zurückzufallen, nur eben in Objekten... :-) 
Ich komme auch nicht immer ganz bis zum Ziel. :-)))


Viele Grüße
Lutz

php::bar PHP Wiki   -   Listenarchive