Was ist OOP eigentlich?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Servus,

in diesem Thread stelle ich keine Frage sondern ein Thema zur Diskussion - was ist OOP?

Für mich ist OOP nicht nur die Sprache. Die Sprache, in unseren Fall Python bietet syntaktischen Zucker und einige angenehme Erleichterungen. Jedoch ist nicht jedes Programm welches Klassen etc. nutzt in meinen Augen objektorientiert. Um das zu veranschaulichen führe ich einen weiteren Begriff ein, objektnutzend. Objektnutzend ist ein Programm, welches Klassen und Instanzen nutzt (im Sinne von selbst definiert, nicht im sinne dass es Built-in Datentypen verwendet). Solch ein Programm zu schreiben ist recht trivial, denn man kann ganz normale Prozedurale Programme in Objektnutzende Programme umwandeln indem man einfach alle Funktionen in Klassen packt. Dadurch werden die Klassen zu ihrer Art Namensräumen, aber das Programm an sich nicht Objektorientiert. Man kann es auch in die andere Richtung drehen indem man Objektorientierte Programme schreibt in einer Programmiersprache die dafür keine zusätzliche Syntax bietet. Diesen Weg haben etwa die GTK+-Entwickler genommen.

Objektorientierung besteht nämlich aus zwei Worten: Objekt (diese werden in Objektnutzenden Programmen verwendet) und Orientierung. Letzteres ist kein sprachlicher Aspekt sondern ein gedanklicher. Er beschreibt, dass sich der Autor Gedanken darüber gemacht hat, die Dinge die er schreibt zu abstrahieren. D.h. eine Klasse macht genau das, was sie machen soll und kümmert sich um nichts anderes.

Nehmen wir mal ein eine Abwandlung eines Codes ich heute gesehen habe. Ein klassisches Beispiel ist die Klasse `Shape` mit ihren Kindklassen `Circle`, `Rectangle` und `Triangle`. Jede dieser Klassen hat ein `draw()` - ganz logisch, Formen sollen sich zeichnen können. Das ist OOP. Nun fügt der Autor der Klasse noch ein `react_on_network_interrupt()` hinzu, weil es dort gerade passt. Damit ist es in meinen Augen eigentlich kein Objektorientierter Entwurf mehr da `react_on_internet_interrupt()` teil der Programmlogik ist und nicht der Objektlogik (das setzt natürlich vorraus, das `react_on_network_interrupt` nicht tatsächlich sinnvoll ist, etwa das Objekt grün färbt, wenn Daten über das Netzwerk kommen). Wenn aber `react_on_network_interrupt` etwa da ist, das Programm zu beenden dann hat es im Objekt nichts verloren - dann gehört es raus.

Das ist nun vergleichsweise schwer zu erklären, denn es ist eben eine Gedankliche Sache, keine die wenn man es falsch macht Exceptions wirft. Es geht eben darum, dass man Instanzen als Daten eines Programmes verwendet und nicht als Funktionen die den Programmfluss bestimmen. Das ist nicht ganz einfach zu verstehen und Programmiersprachen wie Java führen meiner Meinung nach dazu, dass Objektorientiertes Design vernachlässigt wird - alles muss Klassen sein, also kann man Klassen dazu einspannen prozedural zu Programmieren.

Insgesamt ist Objektorientierte Programmierung ähnlich weit von Prozeduraler Programmierung entfernt wie Funktionale Programmierung nur gibt Objektnutzende Programmierung einem den Anschein, dass man die Konzepte von OOP verstanden hat - es funktioniert doch alles. Dies ist aber manchmal ein Trugschluss, da man dann manchmal solche Objekte konstruiert, dass sie einem mehr im Weg stehen als dass sie einem Helfem. Daher bin ich auch kein Fan des Übertragens von Prozeduralen Programmen nach "OOP", weil nicht alle prozeduralen Probleme Objektorientiert einfacher werden. Objektorientierung ist ein Werkzeug, kein Zwang. Wenn etwas Objektorientiert keinen Sinn ergibt, dann muss man das Problem da auch nicht reinzwingen.
OOP zu kennen ist jedoch eine gute Sache, auch wenn man es nicht unbedingt einsetzen muss - das ist wiederrum ähnlich wie grundlegende funktionale Konzepte zu kennen. Dieses Wissen bringt einem auf den ersten Blick nicht viel, aber langfristig kann es einem Helfen ein besserer Programmierer zu werden, indem man weiß, wie man an ein Problem rangehen kann.

Manchmal ist es aber auch sinnvoll oder notwendig Klassen zu schreiben die nicht Objektorientierten Design genügen, nur heißt das nicht dass das Programm dadurch OOP ist.

Das ist meiner Meinung nach das was in vielen Büchern zu kurz kommt und es ist auch verständlich, denn dass ist eben die Theorie und viele Bücher wollen Praxis vermitteln. Es ist auch gar nicht so einfach zu vermitteln, denn das Gefühl was OOP ist und was nicht kommt vermutlich auch erst nach einiger Praxis. Wobei, da warne ich gleich davor, man kann nicht immer genau sagen "Das ist OOP, weil..." und "Das ist kein OOP, weil...". Die Übergänge sind fließend und es kann auch sein dass eine Mischung von beiden an einer gegebenen Stelle optimal ist.

Das wären meine Gedanken zu OOP, würde mich freuen wenn noch jemand was zu ergänzen hätte oder seine Meinung darstellen will. Beispiele wären aber auch super :)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Costi
User
Beiträge: 545
Registriert: Donnerstag 17. August 2006, 14:21

fuer mich ist ein object nur ein namespace. Inklusive methoden, die mit diesen namespace arbeiten.

so ist es moeglich ein dictionary als namespace zu benutzen, funktionen koennen dan diesen namespace als argument uebergeben kriegen.
dieser kann dan als this/self fungieren.
und schon hat man OOP.

und wenn die funktionen im erwaehnten dictionary gebunden sind, hat man schon 3/4 der miete
cp != mv
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

Hi Leonidas

Wir haben in der Schule verschieden Fächer zum Thema programmieren besucht.
  • OOP (Objekt Orientiertes Programmieren) war eigentlich mehr Programmieren mit Java. Auch prozedurales Programmieren in Klasse ;)
  • Dann kam OOD (Objekt Orientiertes Design), da ging es um Vererbung, Polymorphismus etc.
  • Im 3. Semester kam ADS (Algorithmen und Datestrukturen), da kamen verschiedene Datenstrukturen (Hashmaps, Bäume, Graphen,...) und verschiedene Algorithmen die mit diesen Strukturen arbeiten.
  • Weiter geht es mit Software Entwicklung, da durften wir einem sehr langweiligen Dozenten über verschiedene Patterns(Observer,MVC,...), einige Programmierarten (XP, Wasserfall, Unified Process) zuhören.
  • Zurzeit ist JFF (Java Für Fortgeschrittene) an der Reihe, das mit Abstand schlimmste Fach :). Der erste Teil war sozusagen vorbereitung für den SCJP (Sun Zertifikat) Test, was aber gar nichts mit Programmieren selber zutun hat sondern mehr mit der EBNF von Java und der API selbst. Der zweite Teil ist ein wenig besser, da werden einzelne Teile der API durchgenommen (Networking, Security, ...).
Im Ganzen sehr viel Java :), was jedoch nicht heisst ich hätte ne klare Vorstellung was OOP ist. Für mich ist ein Code OOP wenn:
  • man die Klassenhierarchie braucht (Vererbung,...) und nicht nur die Klassen als Container für Methoden und Members braucht (was nicht heisst das ich es an gewissen Stellen nicht gut finde).
  • Design Patterns an passenden! Stellen gebraucht werden
  • im Klassendesing auch Dinge wie z.B. "low coupling" beachtet werden
Eine Unterscheidung zwischen OOP und anderen Programmierkonzepten kann man nicht eindeutig machen. Es sind gewisse Techniken die man im richtigen Mass (Wichtig!) einsetzen kann um Objekte sinnvoll und effizient zu gebrauchen.

Bis man OOP gut einsetzen kann, muss man glaub ich auch ein paar Mal so richtig auf die Fresse fallen beim programmieren. Da man meistens erst im Nachhinein die Vorteile und den Einsatzort so richtig sieht.


Gruss

PS: Seit ich das Fach JFF habe finde ich Java immer schlechter, da lernt man Dinge, die in Java syntaktisch gehen aber nie jemand so schreiben würde. So z.B. int[] test[]; einen zweidimensionalen Array erstellt oder das ganze Handling mit den Wrapperklassen (Stichwort widening/boxing).
nemomuk
User
Beiträge: 862
Registriert: Dienstag 6. November 2007, 21:49

Für mich als Programmieranfänger ist sowieso noch überhaupt kein Vorteil in der OOP ersichtlich...
Habe bisher nur mit JavaScript gearbeitet und dort auch ausschließlich funktional programmiert.

Bisher kann ich keine Vorteile im OOP sehen - vllt. ändert sich das ja auch noch. Mir helfen auch unzählige Tutorials nicht weiter den Vorteil genau zu erkennen... Entweder ich "denke anders" oder aber ich habe noch nicht ausreichen mit Python programmiert...
Vingdoloras
User
Beiträge: 53
Registriert: Sonntag 2. Dezember 2007, 18:25

Ich hab n paar Fragen...
rayo hat geschrieben:Dann kam OOD (Objekt Orientiertes Design), da ging es um Vererbung, Polymorphismus etc.
Kannst du (falls das möglich ist :D ) kurz erklären, was Polymorphismus ist? Darüber habe ich zwar auch etwas in einem Buch geselen
(warum "auch" ? Darum: Klickmich! ) , aber da wurde es halt nur kurz erwähnt... und schon der Begriff hörte sich interessant an, so wie die Beschreibung ebenjenes...
Nur leider war das im Buch halt nicht so genau...
Zuletzt geändert von Vingdoloras am Dienstag 4. Dezember 2007, 15:19, insgesamt 1-mal geändert.
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

Hi

Also zuerstmal den englischen Wikieintrag dazu: http://en.wikipedia.org/wiki/Polymorphi ... in_Python:
Hat sogar Beispiele in Python.

Polymorphismus ist (glaub ich mal) wenn verschiedene Objekte gleiche Methoden haben aber in diesen Methoden andere Sachen machen (überschriebene oder überladene Methoden)

Wie auf der Wikiseite beschrieben macht Python davon regen Gebrauch, da z.B. eine Liste und ein String gleich angesprochen wird (str[x], list[x])

Ein beliebtes Beispiel (auch im Wiki) ist auch Animals als Oberklasse und verschiedene Tiere als Unterklassen (Vererbt, überschriebene Methoden). Jedes Tier kann z.B. laut_geben(), jedoch macht das jedes Tier anders, wenn man aber jetzt ein_animal.laut_geben() macht, muss man sich nicht darum kümmern ob es nun eine Katze oder ein Hund ist.

War das irgendwie Verständlich?

Gruss
Costi
User
Beiträge: 545
Registriert: Donnerstag 17. August 2006, 14:21

eine rudimentaere oop implementation:
zeigt aber wie simple es sein kann:

Code: Alles auswählen


#oop iplementation
def oop_new(toinit, *args, **kw):
	oop_getmethod(toinit, "initialize")(*args, **kw)
	return toinit
def oop_getmethod(obj, attr):
	def tmp(*args, **kw):
		return obj[attr](obj, *args, **kw)
	return tmp
def oop_setattr(obj, attr, val):
	obj[attr] = val
def oop_getattr(obj, attr):
	return obj[attr]
def oop_mk_class(*methods):
	retval = {}
	for i in methods:
		#del vars()[i.__name__] #programmierer kommentieren ihre probleme einfach aus und gut is! (-;
		retval[i.__name__] = i
	return retval




#class Car
def initialize(me, name):
	oop_setattr(me, 'name', name)
	oop_setattr(me, 'speed', 0)
def faster(me):
	oop_setattr(me, "speed", oop_getattr(me, "speed") + 5)
def stop(me):
	oop_setattr(me, "speed", 0)
def to_str(me):
	return oop_getattr(me, "name") + ": " + str(oop_getattr(me, 'speed'))
Car = oop_mk_class(initialize, faster, stop, to_str)





#test
car1 = oop_new(Car, "hosday")
print oop_getmethod(car1, 'to_str')()

car2 = oop_new(Car, 'humaditzy')
for i in xrange(5):
	oop_getmethod(car2, "faster")()
print oop_getmethod(car2, 'to_str')()


cp != mv
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

Hi Costi

Das ist für mich eine rudimentäre Objekt Implementation und das hat nichts zu tun mit OOP.

Das konnte man auch in C mit Structs machen (Container für Daten und Methoden).

Gruss
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Da ich mich gerade mit libpurple rumschlage muss ich da gleich mal OOP in C einwerfen. Denn die Alternative zu OOP oder dem, was ich drunter verstehe sind GOTO und globale Variablen :-)
Drupal nutzt GoF Patterns bis zum Abwinken, hat aber keine einzige Klasse. Schaut sich aus wie ein glib Programm, halt in PHP. Gleiches gilt für so ziemlich alle glib Libraries/Programme.

Selbst bei funktionaler Programmierung musst du deine Daten wo ablegen. Und ob man da jetzt Closures für verwendet, oder Dicts, oder Objekte ist einerlei. Das was Java/C++ aus OOP gemacht haben muss sich halt ausblenden.

Also von meiner Sichtweise: OOP lässt sich gar nicht vermeiden :-)
TUFKAB – the user formerly known as blackbird
Jona
User
Beiträge: 94
Registriert: Sonntag 23. September 2007, 23:25

das schöne an OOP oder genauer OODesign ist für mich, dass ich die wirklichkeit so schön intuitiv abbilden kann:
durch vererbung, aggregation, komposition.
und natürlich haben die einzelnen objekte eigenschaften und fähigkeiten.
lässt man die einzelnen objekte wirklich nur die eigenschaften, fähigkeiten und relationen haben, die sie im zugrundeliegenden problem/aufgabe haben (und benennt man diese treffend - schwerer als man meint), wird das programm sehr schlüssig und leicht nachvollziehbar.

hier finde ich deine anmerkung ganz wichtig:
Nehmen wir mal ein eine Abwandlung eines Codes ich heute gesehen habe. Ein klassisches Beispiel ist die Klasse `Shape` mit ihren Kindklassen `Circle`, `Rectangle` und `Triangle`. Jede dieser Klassen hat ein `draw()` - ganz logisch, Formen sollen sich zeichnen können. Das ist OOP. Nun fügt der Autor der Klasse noch ein `react_on_network_interrupt()` hinzu, weil es dort gerade passt. Damit ist es in meinen Augen eigentlich kein Objektorientierter Entwurf mehr da `react_on_internet_interrupt()` teil der Programmlogik ist und nicht der Objektlogik (das setzt natürlich vorraus, das `react_on_network_interrupt` nicht tatsächlich sinnvoll ist, etwa das Objekt grün färbt, wenn Daten über das Netzwerk kommen). Wenn aber `react_on_network_interrupt` etwa da ist, das Programm zu beenden dann hat es im Objekt nichts verloren - dann gehört es raus
genau!

das gehört so eigentlich in jedes lehrbuch, habe ich aber noch nie gesehen. muss man anscheinend auf die harte tour lernen!
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Zum Thema Polymorphismus ist der QListView Container imho ein super Beispiel imho: Kann eben jede Art von Items aufnehmen - nicht nur die Basis-Items. Dadurch kann man so ziemlich alles darin realisieren, vom optischen Schmankerl, bis hin zu Funktionalitäten im Backendbereich der Objekte.
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Hoi Leonidas,

vorweg: Ich bin weder Mathematiker noch Informatiker und doch weiß ich einen schönen Beweis und eleganten Code zu schätzen. Aber Vertreter beider Disziplinen übertreiben manchmal etwas (was innerhalb der Disziplin völlig ok ist) und so werden sie außerhalb oft mißverstanden und die schönsten ihrer Leistungen werden gar nicht gesehen. (Im Alltag schreibe ich bei beiden Anwendungen lieber ein paar Zeilen mehr - was durchaus dem Zen von Python entspricht ;-) .)
Und so möchte ich - was ich als Naturwissenschaftler eher selten machen - ein eher emphatisches Argument einwerfen:

Um es etwas weniger abstrakt zu machen nehmen wir mal eine Klasse "Auto" und eine Instanz "wagen". Da ist es nur natürlich den Wagen so zu bedienen: wagen.links_abbiegen(). Bei wagen.färben() fangen die Probleme schon an. Der Wagen färbt sich ja nicht selbst, oder? Also: färben(wagen).
Jetzt soll unser Auto aber kein alltägliches, stinkendes Blechmonster sein, sondern ein knuffiges Auto mit Kulleraugen in einem Kinderspiel. Da wird wagen.färben() oder .pinseln() schon eingängiger, nicht wahr? Es ist aber im Zweifel dieselbe Methode. (Das Argument läßt sich immer weiter treiben, je mehr man sich vom Abstraktem zum Intentionellem bewegt, es ist also eingentlich ein furchtbares auf Regression fußendes Argument, was ich gerne zugebe.)

In der Praxis entscheide ich nach "Bauchgefühl" (was ich in meiner Disziplin sonst eher nicht wage!): Was ist eher Verständlich aus Anwenderperspektive? Was werde ich in einem halben Jahr noch verstehen? In meinem aktuellen Projekt hätte ein Informatiker wahrscheinlich grid_search(model_instance) anstelle von model_instance.grid_search() geschrieben. Aber ich fühle mich sehr wohl mit *meiner* Lösung. (Dennoch: Gerne auch mehr konzeptionelle Kritik - ich bin da durchaus offen.)

Durchbreche ich damit Paradigmen? Ja, und?

Gruß,
Christian
Benutzeravatar
keppla
User
Beiträge: 483
Registriert: Montag 31. Oktober 2005, 00:12

Leonidas hat geschrieben:Um das zu veranschaulichen führe ich einen weiteren Begriff ein, objektnutzend.
Das halte ich für eine gute Unterscheidung, die sich echt mal in einigen Büchern wiederfinden sollte.
Es geht eben darum, dass man Instanzen als Daten eines Programmes verwendet und nicht als Funktionen die den Programmfluss bestimmen.
Zustimmung. In einem Blog oder so hab ich mal folgendes gefunden: "Wenn du deinen Klassen Namen wie Manager, Handler, etc gibst, denke erstmal nach. Objekte sollen Dinge, sein keine Tätigkeiten sein. Wenn Klassennamen dauernd substantivierte Verben sind, ist das ein Warnhinweis".
Ist natürlich nicht 100% gültig, ich wette, jeder von uns kennt einen Manager, der seine Berechtigung hat, aber als Anhaltspunkt imho echt gut.
Jan-Peer
User
Beiträge: 166
Registriert: Dienstag 2. Oktober 2007, 10:55

Ich glaube, einer der wichtigsten Vorteile von OOP ist die Skalierbarkeit.

(Blödes Beispiel):
Ein Autorennspiel mit drei Wagen lässt sich natürlich auch mit funktionaler Programmierung schön realisieren. Nun ist der Code fertig, und irgendwer will plötzlich x Wagen mehr auf der Strecke sehen. Wenn du dein Programm mit OOP sorgfältig designt hast, muß du jetzt nur irgendwo eine einzige Zahl ändern. Beim funktionalen Ansatz dürfte es ein wenig aufwendiger werden ...
BlackJack

@keppla: Unser "Algorithmen und Programmieren" Prof hat "objektbasiert" zu Programmen gesagt, die zwar Objekte benutzt haben, aber nicht wirklich objektorientiert waren. Ist IMHO eine recht treffende Bezeichnung. Die auch auf Python super passt, denn selbst wenn man nur klassisch prozedural arbeitet, wobei ich Klassen als `struct`/`RECORD`/`Type`-Ersatz noch zu "prozedural" zähle, so basiert trotzdem alles auf Objekten.

@Jan-Peer: Das Beispiel ist wirklich nicht so glücklich, denn wenn ich das in Haskell oder C programmiere, brauche ich auch nur irgendwo eine Zahl für die Wagen ändern.

Aber mit der Skalierbarkeit stimme ich Dir zu. Das ist IMHO auch der Grund warum es so schwer ist einfache Beispiele für Anfänger zu finden, weil die Vorteile von OOP erst so richtig zum tragen kommen, wenn man ein grösseres System vor sich hat. Was nicht heisst, dass man OOP deshalb nicht im "Kleinen" einsetzen sollte, weil Programme, wenn sie nützlich sind, die Eigenschaft haben, solange zu wachsen bis sie komplex genug sind um aus OOP Vorteile zu ziehen. Und wenn man an dem Punkt angekommen ist, möchte man ungern alles nochmal neu programmieren. :-)

Ein gutes und vor allem *praktisches* Beispiel ─ ich hasse diese albernen, konstriuerten Tier-, Geometrische-Figuren und Bankkonto-Beispiele ─ sind GUIs. Da hat man sinnvolle Beispiele für Vererbung (alles genmeinsame in eine Widget-Klasse packen) und Polymorphie (in ein Container-Widget kann man beliebige andere Widgets stecken).
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

SchneiderWeisse hat geschrieben:Für mich als Programmieranfänger ist sowieso noch überhaupt kein Vorteil in der OOP ersichtlich...
Habe bisher nur mit JavaScript gearbeitet und dort auch ausschließlich funktional programmiert.
Ich denke du meintest prozedural, oder? Funktionale Programmierung ist noch einmal etwas anderes, es beschriebt quasi das Gegenteil von Imperativer Programmierung und geht von einem eher mathematischen Ansatz aus - eine Funktion hat einen Eingabewert und einen Ausgabewert und wenn du das gleiche eingibst dann kommt das gleiche wieder raus. Klingt jetzt nicht spannend, aber es heißt dass die Funktionen von einem Aufruf zum anderen Aufruf keinen Zustand speichern. Ist also das Gegenteil von Objekten, die eben genau dazu da sind den Zustand der durch sie abgebildeten Muster darzustellen.
Mit JavaScript kann man natürlich auch, zumindest zu einem gewissen Teil funktional arbeiten, aber spätestens wenn du etwas an HTML ändern willst, ändert die bearbeitete Seite den Zustand. Sowas ist dann ein Seiteneffekt. Imperative Programmierung beschäftigt sich eben mit den Seiteneffekten.

Das Beispiel eine Datei zu speichern demonstriert das ganz gut: wenn ich in Python write() auf einem Dateiobjekt aufrufe, dann gebe ich in die Funktion Daten ein und bekomme None zurück. Aber die Funktion hatte eben den Seiteneffekt, dass sie die eingegebenen Daten in die Datei geschrieben hat. Funktionale Programmierung möchte möglichst ohne Seiteneffekte auskommen. So eine rein funktionale Sprache wäre Haskell, wo du Seiteneffekte nur über ein Konstrukt namens "Monade" bekommst. Dieses jetzt auszuführen wäre aber arg komplex und ich glaube nicht dass ich es gescheit erklären könnte. Soviel nur, dass viele funktionale Sprachen hybride sind, d.h. sowohl funktionale als auch imperative Konzepte erlauben. Vertreter hierfür wären O'Caml (das O steht sogar für Objekte) und die Lisp-Familie (Common Lisp hat auch ein recht bekanntes Objektsystem, das CLOS).
CM hat geschrieben:Um es etwas weniger abstrakt zu machen nehmen wir mal eine Klasse "Auto" und eine Instanz "wagen". Da ist es nur natürlich den Wagen so zu bedienen: wagen.links_abbiegen(). Bei wagen.färben() fangen die Probleme schon an. Der Wagen färbt sich ja nicht selbst, oder? Also: färben(wagen).
Jetzt soll unser Auto aber kein alltägliches, stinkendes Blechmonster sein, sondern ein knuffiges Auto mit Kulleraugen in einem Kinderspiel. Da wird wagen.färben() oder .pinseln() schon eingängiger, nicht wahr? Es ist aber im Zweifel dieselbe Methode. (Das Argument läßt sich immer weiter treiben, je mehr man sich vom Abstraktem zum Intentionellem bewegt, es ist also eingentlich ein furchtbares auf Regression fußendes Argument, was ich gerne zugebe.)
Nein, färben muss gar keine externe Funktion sein, eigentlich sollte sie das wenn man es genau ansieht sogar eine Methode des Objektes sein. Denn sie verändert den Zustand - die Farbe - des Objektes. Diese Dualität hast du im Grunde in Python auch. `len()` nimmt ein Objekt und gibt dessen Länge zurück. Dabei muss es auch auf Interna des Objektes zugreifen, auf `__len__()`, d.h. also es erwartet ein bestimmtes Interface, ein bestimmtes Verhalten von dem Objekt. Im Falle von `len()` wird die Arbeit hauptsächlich auf das Objekt verlagert, in anderen Sprachen wie Ruby oder Java ist das auch ganz normal so - oft als Attribut `length`. Und `pingseln()` auf die gleiche Methode zeigen zu lassen wie `färben()` ist ebenso durchaus denkbar, möglich und in Ruby sogar gängig. Dort findest du oft Aliasnamen für bestimmte Funktionen - in Python ist der Zen dagegen, aber machen kannst du es natürlich.
CM hat geschrieben:Durchbreche ich damit Paradigmen? Ja, und?
Auch wenn, dann ist es immer noch kein Problem. Man muss eben bedenken dass Objektorientierung ein Mittel ist dem Programmierer zu helfen, sein Programm klar zu strukturieren. Nicht dazu, ihn wochenlang überlegen zu lassen, wie man ein bestimmtes Vorhaben objektorientiert umsetzt. OOP ist ein Werkzeug, kein Selbstzweck und daher ist es an einigen Stellen, wie rayo treffend gemeint hat, auch nötig und sinnvoll einige Dinge eben anders zu lösen.

Das Beispiel kennen wir alle, aber es kommt eben oft vor: es schreibt jemand ein Programm, schön prozedural. Es funktioniert auch, tut seinen Dienst gut. Nun denkt sicher der Autor "ja, das schreibe ich mal in OOP im, das ist ja Schwierigkeitsstufe zwei" (alternativ auch Programmierung 2.0) und da beginnen dann die Probleme weil bestimmte Variablen nicht zugänglich sin innerhalb einer Struktur von mehreren Klassen, so dass man letztendlich entweder alles in eine Klasse packt oder globale Klassen nutzt. Der Vorteil ist nun..ja, es gibt eigentlich keinen Vorteil. Das Programm ist objektnutzend, das Problem aber komplizierter gelöst wird als vorher.
JWZ, adaptiert hat geschrieben:Some people, when confronted with a problem, think “I know, I'll use classes.” Now they have two problems.
Zu den Design Patterns: als ich das Buch der GoF durchgeblättert habe, und einige Patterns näher angesehen habe bin ich zu dem Schluss gekommen, dass zumindest die Patterns die ich mir angesehen haben in mir in Python so nichts bringen. Man hat sie entweder anders implementiert (Visitor-Pattern etwa, sogar eleganter als in Java) oder gar nicht benötigt, weil die Sprache eine elegantere Lösung bereits bereitstellt. Daher muss man da auch vorsichtig sein und die Patterns gegenchecken ob so etwas in Python überhaupt sinnvoll ist.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

@Leonidas: Die `IO`-Monade ganz grob erklärt: Da wird in der IO-Datenstruktur der Zustand der "Welt" vermerkt, auf den der Programmierer allerdings keinen direkten Zugriff bekommt. Es gibt also den Zustand vor dem schreiben in die Datei und einen veränderten danach. Und schon gibt's keinen Seiteneffekt mehr. Ist das nicht toll. Allerdings muss man den Zustand der Welt immer mit herumreichen, das heisst sämtlicher IO-Code muss dann mit Typen der IO-Monade arbeiten.

Bei dem `faerben()` ist die Frage, ob das überhaupt eine Methode sein muss und nicht einfach nur ein Attribut `farbe` reicht.

OOP als Werkzeug sehe ich genau so. Darum mag ich Sprachen, die mehrere Paradigmen unterstützen. Es gibt eben Einsatzgebiete wo jeweils prozedural, funktional oder OOP eine schönere, lesbarere, und wartbarere Lösung bieten als die jeweils anderen Paradigmen. Bzw. auch eine Mischung davon. Deklarative Programmierung fehlt in Python irgendwie noch. :-)

Das GoF-Buch enthält einiges was in statisch typisierten Sprachen so "schwer"/umfangreich ist, dass so viele Klassen involviert sind, dass man von einem Muster sprechen kann. Einiges davon ist in dynamischen Sprachen viel einfacher und direkter zu lösen, so dass es dort höchstens ein Idiom gibt.

@keppla: Das mit den Klassennamen ist teilweise auch Schuld von klassenfixierten Sprachen wie Java. Wo man in Python eine einfache "handle_foo"-Funktion schreibt, *muss* man in Java in der Regel eine Klasse haben, die ein `FooHandler`-Interface implementiert und die man oft mangels besseren Einfalls oder Zeit dann `FooHandlerImpl` nennt.
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Leonidas hat geschrieben:Nein, färben muss gar keine externe Funktion sein, eigentlich sollte sie das wenn man es genau ansieht sogar eine Methode des Objektes sein. Denn sie verändert den Zustand - die Farbe - des Objektes.
Point taken.
Benutzeravatar
keppla
User
Beiträge: 483
Registriert: Montag 31. Oktober 2005, 00:12

BlackJack hat geschrieben:Deklarative Programmierung fehlt in Python irgendwie noch.
Ist nicht das, was (teilweise mit Metaklassen) in den ganzen ORM gemacht wird, schon irgendwie deklarativ?
Ich meine sowas wie

Code: Alles auswählen

class UserTable(Table):
  id = type.Int(primary_key=True)
  name = types.Varchar(length=50, nullable=False)
Klar, im Endeffekt sind in Python auch Klassen irgendwie Anweisungen, aber ich finde, das geht schon in richtung deklarativ (im Sinne von: ich sag nicht, wie es gemacht wird, sondern was ich haben will)
Das GoF-Buch enthält einiges was in statisch typisierten Sprachen so "schwer"/umfangreich ist, dass so viele Klassen involviert sind, dass man von einem Muster sprechen kann. Einiges davon ist in dynamischen Sprachen viel einfacher und direkter zu lösen, so dass es dort höchstens ein Idiom gibt.
Jo, das finde ich auch sehr auffällig. Einige Pattern sind schlicht Sinnlos in dynamischen Sprachen (typesafe enum z.B.), andere sozusagen "first level patterns".
Packages sind Singletons, Klassen sind factories, Funktionen "delegates", "callbacks", was-auch-immer...
@keppla: Das mit den Klassennamen ist teilweise auch Schuld von klassenfixierten Sprachen wie Java. Wo man in Python eine einfache "handle_foo"-Funktion schreibt, *muss* man in Java in der Regel eine Klasse haben, die ein `FooHandler`-Interface implementiert und die man oft mangels besseren Einfalls oder Zeit dann `FooHandlerImpl` nennt.
Ja, ich kenne Java. Früher (=vor python) hielt ich das sogar für ne gute Idee...
Auch ich hab schon den ein oder anderen Handler oder Manager geschrieben. In vielen Fällen ist das ja auch ok (man soll laut tipp ja nur "nachdenken"), das Ding hat ja exakt diesen einen Zweck.
Aber gerade Objekte, die nicht sonderlich spezifisch sind, haben imho die Tendenz zu "god-objects" zu Eskalieren, weil man bei keiner Erweiterung wirklich sagen kann "dafür ist das Objekt nicht zuständig".
BlackJack

Ja ORMs gehen in die deklarative Richtung. Ich dachte aber mehr an allgemeinere Werkzeuge a la Prolog, also eine Menge von Fakten und Regeln und das Ziel angeben und dann sagen "Mach mal".
Antworten