Weniger Klassen, mehr Funktionen.

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.
Antworten
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Hallo,

beim Stöbern bin ich über einen Vortrag gestolpert, dessen Link ich jetzt blöder weise nicht mehr präsent habe, ging es darum, dass in Python weniger mit Klassen und mehr mit Funktionen arbeiten soll. Der Vortrag war komplett auf Englisch, und soweit ich "mitschneiden" konnte, ging es zunächst darum, dass Funktionen besser lesbar sind als Klassen. Sprich, ein Modul, die nur aus Funktionen besteht ist leserlicher - also der Code. Was ich noch weiterhin aufschnappen konnte, ist es die Philosophie Pythons, weniger mit Klassen zu arbeiten. Aber allgemein gefragt, ist es unschön, unsauber und nicht gerne gesehen, wenn jemand ausschließlich mit Klassen arbeiten? Was mich auch interessieren würde, wie sieht es hinsichtlich der Performance aus? Ich meine, wenn ich ein Objekt instanziere (Ist das eine richtige Schreibweise? Oder heißt es eher "instantiieren" oder doch "instanziieren"), wie sieht die Geschwindigkeit des Programms aus? Fragen über Fragen. Und sicherlich steht es wieder irgendwo in Dokumenten, aber ich hätte gerne eure erfahrene Meinung.

Sophus
BlackJack

Ich würde sagen: Keine Klassen solange das nicht tatsächlich nötig ist. Selbst bei Programmiersprachen wo man syntaktisch zu Klassen gezwungen wird, gibt es immer auch Möglichkeiten ”statische Methoden”, also letztendlich Funktionen zu definieren. Beispielsweise in Java. Notfalls schreibt man Methoden die das Objekt nicht verwenden.

Andererseits bieten sich Klassen in fast jedem nicht-trivialen Programm in einer objektorientierten Programmiersprache an um mindestens Verbunddatentypen zu definieren. Und von da zu sinnvollen Operationen auf diesen Typen in Form von Methoden ist es nur ein kleiner Schritt.

Was die Performance angeht: Wer in einer Sprache wie Python aus Performancegründen auf Klassen verzichtet hat die falsche Sprache gewählt.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Vielen dank für deine ausführliche Antwort. Wie du sicherlich mitkommst, bin ich gerade dabei in die OOP einzusteigen, indem ich mit Klassen arbeite, um somit zum Beispiel Menu und Toolbar zu erzeugen. Und ich will nachher nicht die Gefahr laufen, mich auf die "Klassen" einzuschießen, und am Ende eher Python-Unlike programmiere. Und man kennt es ja, hat man erstmal "falsch" gelernt, dann wird es schnell zur Gewohnheit, und nachher mag man die Funktionen nur noch weniger :-) Deswegen war ich leicht irritiert, weil ich merkte, dass ich in meiner kleinen Übung mit den Menu und Toolbar vollkommen auf Klassen konzentriere.
Schorlem
User
Beiträge: 40
Registriert: Dienstag 3. Juni 2014, 16:37

War's zufällig dieses Video?
http://www.youtube.com/watch?v=o9pEzgHorH0

Ich hatte zuerst auch meistens nur Funktionssammlungen auf Modulebene verwendet, bin davon mittlerweile aber abgekommen und außer den vielen "self."s finde ich es auch nicht wirklich schwer zu lesen (solange die Klasse nicht unnötig verschachtelt ist).
Diese Nachricht wurde maschinell erstellt und ist daher ohne Unterschrift gültig.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Schorlem hat geschrieben:War's zufällig dieses Video?
http://www.youtube.com/watch?v=o9pEzgHorH0

Ich hatte zuerst auch meistens nur Funktionssammlungen auf Modulebene verwendet, bin davon mittlerweile aber abgekommen und außer den vielen "self."s finde ich es auch nicht wirklich schwer zu lesen (solange die Klasse nicht unnötig verschachtelt ist).
Yeah, das war das Video. Danke :-)
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Was mir noch einfällt. Wie sieht es speichertechnisch aus? Sind da Funktionen vorteilhafter als Klassen? Gut, ich könnte ja auch argumentieren, dass man solche Fragen an heutigen Rechnern nicht mehr stellen braucht - es sei denn man programmiert ein monströses Programm, wo selbst Microsoft blass wird :-) Oder greift mein Argument hier nicht?
BlackJack

@Sophus: Äpfel und Birnen würde ich sagen. Klassen sind für Daten und Funktionen. Zu den Funktionen braucht man dann noch die Daten mit denen sie etwas machen. Auch hier würde ich sagen, das sollte keine Rolle spielen.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Wenn eine Klasse eine sinnvolle logische Einheit in einem Programm bilden kann, dann spricht meistens nichts dagegen, dies auch als Klasse zu programmieren. IMHO können Menschen gut komplexere Programmabläufe nachvollziehen, wenn verschiedene "Protagonisten" im Zusammenspiel ihre Arbeit verrichten. Großer Mist ist es hingegen, wenn die Klasse viel mehr können soll, als man eigentlich zur Erledigung der spezifischen Aufgabe des Programms benötigt. Damit meine ich übertrieben umfangreiche APIs, von denen der Großteil nicht genutzt wird und wo man selbst kaum noch durchsteigt - einfach nur für den Fall, dass das ja möglicherweise irgendwann mal irgendwer gebrauchen könnte. Und das sind auch die Dinge, auf die sich das Video bezieht: Nämlich der Hang zur schon fast krampfhaften Nutzung von Klassen, um Code zu modellieren.

Wenn ich Code in Python schreibe, dann sind das oftmals zunächst Funktionen. Ich denke anfangs bewusst nicht in Klassen. Wenn das Programm dann komplexer wird und ich bemerke, dass viele gleiche Daten herumgereicht werden oder dass ich relativ viel Code in einer Funktion habe, den ich in Unterfunktionen aufteilen möchte (und dann viele gleiche Parameter durchreichen würde) dann mache ich Refactoring und baue mir eine entsprechende Klasse. So ist auch sichergestellt, dass meine Klassen die tatsächlichen Probleme lösen und nicht "viel Blabla um Nichts" machen (Vgl. die im Video gezeigte Greeting-Klasse).
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Ich bin nochmal in mich gegangen, und habe ich gefragt, was ich machen würden, wenn ich einen Zugriff-Code auf MySQL schreiben würde. Hier würde ich ganz klar ein Modul anlegen, und zwei Funktionen schreiben, einmal def Connection und einmal def Disconnection. Hier würde ich ganz klar auf Klassen verzichten. Genauso wenn es dann zum Manipulieren der Datensätze kommt (Löschen, Bearbeiten und Hinzufügen). Auch hier würde ich auf Funktionen zurückgreifen. Das wäre so mein erster Gedanke.
BlackJack

@Sophus: Was dann aber eine furchtbare API wäre, denn man hätte globalen Zustand. Oder Du schreibst Funktionen die letztendlich dann doch wieder objektorientiert sind, nur ohne die Syntax die für Klassen zur Verfügung steht und das ganze *einfacher* macht. Das Verbinden kann man in eine Funktion packen, aber die Verbindung selbst sind Daten die einen Zustand darstellen.

Und wenn man in Python Zugriff auf eine relationale Datenbank schreibt, dann wird man hoffentlich die DB-API 2.0 implementieren, damit man eine Standard-API hat. Beziehungsweise schaut man erst einmal ob es ein solches Modul nicht schon gibt.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@Sophus: Ich befürchte, du hast das Anliegen des Vortragenden missverstanden. Es geht ihm - unterstelle ich zumindest mal - um die Vermeidung von unnötigem "Rauschen", wenn Klassen in Fällen verwendet werden, wo sie ein Problem nicht vereinfacht darstellen, sondern eine zusätzliche Komplexität hineinbringen, die man bei einer Verwendung von Funktionen *in diesen spezifischen Fällen* nicht hätte.

Und wie schon zuvor geschrieben: Wenn Code komplexer wird, dann kommt man auch mal zu dem Punkt, wo zusätzliches Rauschen in Ordnung geht, weil es zur besseren Strukturierung beiträgt. Es geht keinesfalls darum, Klassen als eine Art Feind anzusehen und Funktionen *immer* zu bevorzugen.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Sophus: gerade bei Datenbanken wird gerne objektorientiert Programmiert, weil Datensätze schon ziemlich nahe an Objekten sind. Bei SQLAlchemy, das in diesem Zusammenhang gerne genommen wird, wird jede Tabelle als eine Klasse modeliert und Zeilen einer Tabelle sind dementsprechend Instanzen der Klasse.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Ich werfe noch mal einen Beitrag von Armin rein: http://lucumr.pocoo.org/2013/2/13/moar-classes/
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

Ich denke der Vortrag von Diederich hat zu viele Extreme. Wenn man die Funktionalität mehrerer Module mit 20 Klassen auf eine Funktion in einem Modul reduzieren kann das 15 Zeilen lang ist, dann stimmt entweder mit dem ursprünglichen Quelltext etwas ganz gewaltig nicht, oder Diederich ”lügt”. Denn was er da eigentlich die ganze Zeit erzählt, ist das er fremden Code in seine Projekte *direkt* einbaut, und dann alles raus wirft was *er* in *seinem* Projekt nicht braucht. Das ist nicht die übliche Art wie man Bibliotheken verwendet. Wenn ich aus SQLAlchemy alles rauswerfe was *ich* in *einem* konkreten Projekt nicht brauche, kann ich mich hinterher auch hinstellen und sagen: „SQLAlchemy ist doof, da sind >60% Code drin der völlig unnützer Ballast ist.” Und alle würden mich, zurecht, für einen Trottel halten.

Das `Storage`-Beispiel ist keines gegen Klassen. Klar ist die gezeigte abstrakte `Storage`-Klasse unsinnig, aber wenn man das pythonisch schreibt hat man weiterhin konkrete *Klassen*, die `__getitem__()` und `__setitem__()` implementieren statt `get()` und `put()`. Man würde das nicht durch Funktionen ersetzen.

Insgesamt hat er da anscheinend Beispiele rausgesucht die nicht primär gegen Klassen sprechen, sondern dagegen APIs oder Idiome von anderen Programmiersprachen 1:1 nach Python zu portieren.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Hyperion hat geschrieben:Ich werfe noch mal einen Beitrag von Armin rein: http://lucumr.pocoo.org/2013/2/13/moar-classes/
Das Beispiel mit der ``io``-API in Python 3.x ist schön gewählt: Komposition von Klassen (ggf mit sinnvollen Default-Werten in der ``__init__()``) und eine Helper-Funktion, die mir die Exemplare für diese Komposition zusammenstellt. Dann hat der User, der einfach nur die Kernfunktionalität der Lib verwenden möchte, etwas davon und genau so auch derjenige, der umfangreiche Modifikationen vornehmen möchte bzw muss.

Was ich allerdings kritisch anmerken möchte, ist dass performante Python-Funktionalität bekanntlich oft auf umfangreiche Algorithmen in C angewiesen ist. Es ist daher nicht immer trivial, sowas wirklich transparent auch für die Python-Schicht zugänglich zu machen. Ein JSON-Parser mit Tokenizing und allem drum und dran, dessen nahezu komplette Funktionalität in Teilen ohne weiteres innerhalb von Python überschrieben werden kann und der dabei trotzdem noch schön schnell ist, müsste mir erst noch gezeigt werden. Ich bin da eher pessimistisch eingestellt. Klar kann man das Ganze vielleicht in 2-3 Teile aufspalten (um auf die Sache mit den Streams Bezug zu nehmen), aber wenn man dann als Gegenentwurf ein Beispiel aus dem Flask-Projekt heranzieht, wo wirklich sehr viele Entry-Points für's Customizing vorgesehen sind, dann hat das für mich schon ein bißchen was davon, Äpfel mit Birnen zu vergleichen.
BlackJack

Nach dem Video hatte ich das Bedürfnis diese 8 Jahre alte Implementierung mit einer weiteren Klasse zu versehen: Conway's Game of Life. :-)
Piet Lotus
User
Beiträge: 80
Registriert: Dienstag 14. November 2006, 10:40

Hallo zusammen,
ich bin mal wieder recht spät mit meinen Anmerkungen zu einem interessanten Thema. Interessant als "Alternative" zur Objektorientierung ist sicherlich auch mal sich mit Flow Design zu beschäftigen. Hier nur ein Link FlowDesign-Artikel von einigen im Internet.
Nur so als Denkanstoß vorm Wochenende :)
Viele Grüße
Piet
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Super, jemand ein ein neues Wort für den top-down Entwicklungsprozess gefunden.
BlackJack

@Darii: Nicht wirklich, es geht ja darum den Datenfluss und die Transformationen in den Mittelpunkt zu rücken, statt das Problem primär als Zerlegung in Klassen in einer objektorientierten Analyse zu betrachten. Also nicht als erstes Klassen identifizieren, sondern Datenquellen, Transformationen, und Datensenken. Allerdings sind diese drei Sachen oft dann doch wieder Kandidaten für Klassen, und das scheint der Artikel IMHO so ein bisschen verneinen zu wollen.

Mal praktisch auf Python angewendet würde man sich beim FD Gedanken um eben diese Datenquellen, Tranformationen, Aggregationen, und Datensenken machen, also wie man (Daten-)Objekte baut die man mit `itertools`, `reduce()` & Co verarbeiten kann. Ob das jetzt unbedingt einen neuen Namen braucht und Leute die diesen alten Hut anpreisen als wenn es der Heilsbringer und die Lösung aller Probleme ist, sei jetzt mal dahingestellt.

Ich praktiziere beides, gerade auch weil Python's Iteratoren, Generatorausdrücke, ``yield``, und `itertools` & Co das so gut unterstützen, und ich die „lazy” Verarbeitung bei Haskell kennen und lieben gelernt habe. Aber das ist halt *ein* Werkzeug im Werkzeugkasten was man berücksichtigen sollte, aber keines worum man jetzt einen Kult aufbauen sollte.
Antworten