Mailinglisten-Archive |
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