Moin!
Ich lese hier immer wieder ein paar Threads durch und stoße häufig auf Hinweise wie "foo ist ein CodeSmell, mach lieber bar" oder so ähnlich. Ich hab mir vorhin nochmal PEP8 durchgelesen und darin stand nichts von solchen "CodeSmells". Daher wollte ich hier mal kurz fragen: Warum sind das "CodeSmell"s, wenn es in anderen Programmiersprachen anscheinend durchaus legitime Prozeduren sind, und wo sind alle aufgelistet damit man sich das anschauen und zukünftig auch vermeiden kann?
Lg HH
"Code-Smell"?
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Also nummerieren von Variablen ist in keiner Sprache die ich kenne eine legitime Prozedur. Oder worauf spielst du genau an?
Mir ist eine Auflistung nicht bekannt, für mich sind das Erfahrungswerte. Du kannst natürlich einen passenden Artikel im Wiki starten.
Mir ist eine Auflistung nicht bekannt, für mich sind das Erfahrungswerte. Du kannst natürlich einen passenden Artikel im Wiki starten.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
- cofi
- Python-Forum Veteran
- Beiträge: 4432
- Registriert: Sonntag 30. März 2008, 04:16
- Wohnort: RGFybXN0YWR0
http://docs.python.org/howto/doanddont.html ist ein ganz guter Anfang.
Michael Markert ❖ PEP 8 Übersetzung ❖ Tutorial Übersetzung (3.x) ⇒ Online-Version (Python 3.3) ❖ Deutscher Python-Insider ❖ Projekte
Mir wurde von BlackJack pylint und pyflakes ans Herz gelegt, um unschönen und so auch oft inperformanten Code mittels Tools in Programmcode aufzuspüren.
CodeSmells, ohne jetzt auf Wikipedia zurück zu greifen, sind Codeteile, Programmabschnitte welche zwar durch
den Compiler übersetzt werden könnten (alternativ Interpreter bei anderen Sprachen) aber schlichtweg eine
schlechte Lösung darstellen.
Beispiel gibt es hier unendlich viele
z.B.
- würdest du ja auch nie auf die Idee kommen die Fakultät über eine Schleife zu berechen
- In C objekte nicht zu "zerstören" wenn sie nicht mehr benötigt werden
- auf Classevariablen direkt, anstatt mit Getter/Setter zuzugreifen
- Mehrfach iterative Schleifen anstatt Rekursion zu nutzen
- Variablenbezeichnung mit a, b , c wählen
Im groben und ganzen läuft das für mich unter Codingstyle und Softwaredesign. Sowas fängt wie gesagt schon darin an
die variablen mit vernünftigen Namen zu versehen und endet darin das man anstatt "bla" + "Bla" einen StringBuffer verwenden. Ebenfalls gehört es für mich dazu definierte Design Patterns zu verwenden und nicht jedesmal das Rad neu zu erfinden (z.b. Observer Pattern).
Dies sorgt schlussendlich für einen performanten, wartbaren und auch durch andere Personen lesbaren Code
Grüße
p.s. ja ich gebs zu, bisl weit ausgeholt
CodeSmells, ohne jetzt auf Wikipedia zurück zu greifen, sind Codeteile, Programmabschnitte welche zwar durch
den Compiler übersetzt werden könnten (alternativ Interpreter bei anderen Sprachen) aber schlichtweg eine
schlechte Lösung darstellen.
Beispiel gibt es hier unendlich viele
z.B.
- würdest du ja auch nie auf die Idee kommen die Fakultät über eine Schleife zu berechen
- In C objekte nicht zu "zerstören" wenn sie nicht mehr benötigt werden
- auf Classevariablen direkt, anstatt mit Getter/Setter zuzugreifen
- Mehrfach iterative Schleifen anstatt Rekursion zu nutzen
- Variablenbezeichnung mit a, b , c wählen
Im groben und ganzen läuft das für mich unter Codingstyle und Softwaredesign. Sowas fängt wie gesagt schon darin an
die variablen mit vernünftigen Namen zu versehen und endet darin das man anstatt "bla" + "Bla" einen StringBuffer verwenden. Ebenfalls gehört es für mich dazu definierte Design Patterns zu verwenden und nicht jedesmal das Rad neu zu erfinden (z.b. Observer Pattern).
Dies sorgt schlussendlich für einen performanten, wartbaren und auch durch andere Personen lesbaren Code
Grüße
p.s. ja ich gebs zu, bisl weit ausgeholt
Konkret:Leonidas hat geschrieben:Also nummerieren von Variablen ist in keiner Sprache die ich kenne eine legitime Prozedur. Oder worauf spielst du genau an?
Mir ist eine Auflistung nicht bekannt, für mich sind das Erfahrungswerte. Du kannst natürlich einen passenden Artikel im Wiki starten.
http://www.python-forum.de/viewtopic.ph ... 19#p170519
Es gibt doch sicherlich Programmiersprachen, in denen sowasa Gang und Gäbe ist, oder?
@cofi: Danke, aber der Hinweis von BlackJack den ich oben verlinkt habe wird da ja auch nicht aufgeführt - also ist das eher so etwas inoffizielles wie "jeder weiß es aber es steht nirgends geschrieben" oder kocht da jeder sein eigenes Süppchen?
@rads: Fakultät mit einer Schleife wäre ja dann die iterative Version oder? Also bei Python bin ich schon aufdie Idee gekommen, nachdem es da ein recursion-limit gibt.
pylint und pyflakes werde ich trotzdem mal googlen, danke dir!
Ein recursions-limit gibt es quasi in jeder Sprache, man könnte sie anpassen bei bedarf. Aber für Fakultät würde ich math.factorial() verwenden. Ich behaupte besser als diese Standardfunktion kann ich es auch nicht. Ansonsten sehe ich als Software Entwicklung Tutor i den Erstsemestlern oft Programmteile, in welchen Mathematischen Ergebnisse manuell errechnet werden (Summe von 1 bis 10.000) anstatt die mathematische Formel dafür zu verwenden. Wie gesagt, war nur eines von vielen Beispielen.@rads: Fakultät mit einer Schleife wäre ja dann die iterative Version oder? Also bei Python bin ich schon aufdie Idee gekommen, nachdem es da ein recursion-limit gibt.
- cofi
- Python-Forum Veteran
- Beiträge: 4432
- Registriert: Sonntag 30. März 2008, 04:16
- Wohnort: RGFybXN0YWR0
Nunja, es sind Bestandteil der offiziellen Doku, also wuerde ich es nicht unbedingt "inoffiziell" nennen, aber die Aufzaehlungen hatte keinen Anspruch auf Vollstaendigkeit und beschaeftigt sich auch eher mit Python-spezifischen Sachen.heiliga horsd hat geschrieben:@cofi: Danke, aber der Hinweis von BlackJack den ich oben verlinkt habe wird da ja auch nicht aufgeführt - also ist das eher so etwas inoffizielles wie "jeder weiß es aber es steht nirgends geschrieben" oder kocht da jeder sein eigenes Süppchen?
Es gibt aber auch Sachen, die generell schlecht sind (durchnummerierte Variablen), schlecht in OO-Stil/Funktionaler Programmierung/etc.
Zu dem konkreten Problem: Das ist IMO schon ein OO-Codesmell, aber man muss das auch pragmatisch sehen, da es sich nicht unbedingt lohnt die Typhierarchie aufzublasen. Bzw in Python kommt man um Typtests nicht herum (wenn man das _so_ machen will), da es kein typbasiertes Dispatching gibt, aber Ducktyping und EAFP sind sowieso gelaeufiger.
Michael Markert ❖ PEP 8 Übersetzung ❖ Tutorial Übersetzung (3.x) ⇒ Online-Version (Python 3.3) ❖ Deutscher Python-Insider ❖ Projekte
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Das ist jetzt aber tatsächlich recht Java-spezifisch. Natürlich würde ich in Python auf Instanzvariablen direkt zugreifen und natürlich würde ich Iteration der Rekursion vorziehen wenn ich mit großen Daten arbeite die das Rekursionslimit überschreiten (in Java eigentlich auch, fwiw).rads hat geschrieben:z.B.
- würdest du ja auch nie auf die Idee kommen die Fakultät über eine Schleife zu berechen
- In C objekte nicht zu "zerstören" wenn sie nicht mehr benötigt werden
- auf Classevariablen direkt, anstatt mit Getter/Setter zuzugreifen
- Mehrfach iterative Schleifen anstatt Rekursion zu nutzen
- Variablenbezeichnung mit a, b , c wählen
Im groben und ganzen läuft das für mich unter Codingstyle und Softwaredesign. Sowas fängt wie gesagt schon darin an
die variablen mit vernünftigen Namen zu versehen und endet darin das man anstatt "bla" + "Bla" einen StringBuffer verwenden.
Ich weiß gar nicht ob ich das Codesmell nennen würde...
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
@rads: Ich denke das Zusammenzählen (dein Beispiel mit der Summe) würde ich auch machen, da ich keine solche Formel/Funktion kenne.
@cofi: Den letzten Abschnitt habe ich nicht wirklich verstanden.
Solche Code-Smells haben ja anscheinend durchaus Hand und Fuß wenn ich mir die Erläuterungen so ansehe, aber allzuviel davon verstehe ich wiederum auch nicht, da ich einfach noch wenig Erfahrung habe. Hat sich denn noch niemand auf dieser Welt die Arbeit gemacht, diese Dinge mal fragmentartig zusammen zu suchen und auch für noch nicht so erfahrene Programmierer aufzuarbeiten?
@cofi: Den letzten Abschnitt habe ich nicht wirklich verstanden.
Solche Code-Smells haben ja anscheinend durchaus Hand und Fuß wenn ich mir die Erläuterungen so ansehe, aber allzuviel davon verstehe ich wiederum auch nicht, da ich einfach noch wenig Erfahrung habe. Hat sich denn noch niemand auf dieser Welt die Arbeit gemacht, diese Dinge mal fragmentartig zusammen zu suchen und auch für noch nicht so erfahrene Programmierer aufzuarbeiten?
Die Summenformel gabs vom kleinen Gauß aus seiner Schulzeit Summe von 0 bis N ist die Formel n(n+1)/2.
Sind dann nur noch 2 mul 1 invert 1 sum und nicht n add befehle.
An sich gibt gibt es wohl kaum ein Dokument welch alle möglichen Fehler festhällt. gut wird das wie gesagt durch die genannten Tools festgehalten.
Es sind schlichtweg zu viele Regeln. Man lässt sich ein solches Tool drüberlaufen, dann wertet man den Report aus und überlegt was sinnvoll sein könnte und was nicht. Hierfür ist an sich aber schon etwas Erfahrung notwendig um wichtige Codesmells von unwichtigen zu unterscheiden.
Am besten empfehle ich als echter Beginner ein klassisches Einführungsbuch. die Starter-Bücher gehen typischerweise auf verwendete Notationen und dos an nots ein.
Leonidas kann dir hier sicherlich ein gutes Python Buch empfehlen, welches genau das beschreibt. Ich fand das Galileo Python OpenBook ganz gut, vielleicht zu umfangreich. http://openbook.galileocomputing.de/python/
Sind dann nur noch 2 mul 1 invert 1 sum und nicht n add befehle.
An sich gibt gibt es wohl kaum ein Dokument welch alle möglichen Fehler festhällt. gut wird das wie gesagt durch die genannten Tools festgehalten.
Es sind schlichtweg zu viele Regeln. Man lässt sich ein solches Tool drüberlaufen, dann wertet man den Report aus und überlegt was sinnvoll sein könnte und was nicht. Hierfür ist an sich aber schon etwas Erfahrung notwendig um wichtige Codesmells von unwichtigen zu unterscheiden.
Am besten empfehle ich als echter Beginner ein klassisches Einführungsbuch. die Starter-Bücher gehen typischerweise auf verwendete Notationen und dos an nots ein.
Leonidas kann dir hier sicherlich ein gutes Python Buch empfehlen, welches genau das beschreibt. Ich fand das Galileo Python OpenBook ganz gut, vielleicht zu umfangreich. http://openbook.galileocomputing.de/python/
Was ich gerade gesehen habe,
falls Pep auf englisch jemandem zu anstrengend ist, ich unterstelle das natürlich jetzt niemanden, gibts das auch mehr oder wenig gut übersetzt unter:
http://wiki.python.de/PEP%208%20%28%C3%9Cbersetzung%29
falls Pep auf englisch jemandem zu anstrengend ist, ich unterstelle das natürlich jetzt niemanden, gibts das auch mehr oder wenig gut übersetzt unter:
http://wiki.python.de/PEP%208%20%28%C3%9Cbersetzung%29
Ein Einsteigerbuch hab ich schon durchgearbeitet und inzwischen hab ich mich auch schon bei Python 3 eingefunden, aber wenn das Buch gegen die PEP8 verstößt habe ich nicht wirklich hohe Erwartungen außer als dass es mich einführt und mir etwas Gespühr verleiht.
(Einstieg in Python 3, auch von Galileo Computing)
Da es hier wohl nicht viel zu lernen, sondern nur zu erfahren gibt, werd ich damit wohl weiter machen: erfahrungen sammeln. Vielen Dank an alle die sich gemeldet haben und die hilfreichen Tipps.
Zu deinem Hinweis: PEP 8 habe ich inzwischen ca. 10x durchgearbeitet, das letzte Mal heute weil ich nochmal auf Nummer sicher gehen wollte bevor ich den thread eröffne. Aber trotzdem Danke
(Einstieg in Python 3, auch von Galileo Computing)
Da es hier wohl nicht viel zu lernen, sondern nur zu erfahren gibt, werd ich damit wohl weiter machen: erfahrungen sammeln. Vielen Dank an alle die sich gemeldet haben und die hilfreichen Tipps.
Zu deinem Hinweis: PEP 8 habe ich inzwischen ca. 10x durchgearbeitet, das letzte Mal heute weil ich nochmal auf Nummer sicher gehen wollte bevor ich den thread eröffne. Aber trotzdem Danke
@heiliga horsd: Wichtig bei "code smells" ist, dass der Code erst einmal nur unschön "riecht". Das heisst es kann durchaus legitim sein so etwas in seinem Programm zu haben, solange man begründen kann warum man das so gemacht hat. Beispiel Typtests und darauf basierende Entscheidungen mit `instanceof()` oder `type()`: Man sollte die vermeiden, weil man damit das "duck typing" aushebelt und es dem OOP-Paradigma zuwiederlaufen kann. Letzteres ist der Grund warum ``instanceof``-Tests auch in Java ein "code smell" sind. Aber manchmal muss man halt doch darauf zurückgreifen weil die Alternative nicht sauber möglich oder *wesentlich* aufwändiger ist.
Dass nicht alle "code smells" universell für alle Sprachen gelten, sieht man hier an dem Beispiel mit Attributzugriffen über Getter/Setter ganz gut. In Sprachen die berechnete Attributzugriffe a.k.a. Properties kennen, sind Getter/Setter nicht notwendig um für Clientcode eine unveränderte API zu bieten wenn man irgendwann aus normalen Attributen berechnete machen möchte. Bei Sprachen die keine Properties kennen müsste man ohne Getter/Setter nicht nur die veränderte Klasse, sondern auch allen Code der die jetzt veränderte API verwendet, anpassen.
Und auch Rekursion vs. Iteration: Python ist eher auf Iteration ausgelegt, mit einem relativ niedrigen Rekursionslimit und ohne garantierte "tail call optimization". Zusätzlich ist der Funktionsaufruf von der Laufzeit her verhältnismässig teuer. Bei funktionalen Programmiersprachen sieht das anders aus.
Dass nicht alle "code smells" universell für alle Sprachen gelten, sieht man hier an dem Beispiel mit Attributzugriffen über Getter/Setter ganz gut. In Sprachen die berechnete Attributzugriffe a.k.a. Properties kennen, sind Getter/Setter nicht notwendig um für Clientcode eine unveränderte API zu bieten wenn man irgendwann aus normalen Attributen berechnete machen möchte. Bei Sprachen die keine Properties kennen müsste man ohne Getter/Setter nicht nur die veränderte Klasse, sondern auch allen Code der die jetzt veränderte API verwendet, anpassen.
Und auch Rekursion vs. Iteration: Python ist eher auf Iteration ausgelegt, mit einem relativ niedrigen Rekursionslimit und ohne garantierte "tail call optimization". Zusätzlich ist der Funktionsaufruf von der Laufzeit her verhältnismässig teuer. Bei funktionalen Programmiersprachen sieht das anders aus.
Noch ein Beispiel wäre vielleicht jemand, der nicht weiß, dass man bei Python direkt über die Elemente eine Sequenz (a.k.a. Array) iterieren kann und Code wie diesen schreibt:
Das klappt zwar, aber ist halt total kompliziert und unpythonisch. Wenn ich persönlich irgendwelche Python-Projekte angucke und relativ schnell stark riechenden Code entdecke, ist das ein guter Grund für mich, die Finger davon zu lassen.
Code: Alles auswählen
>>> mystring = 'code smell'
>>> for i in range(len(mystring)): print mystring[i]
...
c
o
d
e
s
m
e
l
l
- cofi
- Python-Forum Veteran
- Beiträge: 4432
- Registriert: Sonntag 30. März 2008, 04:16
- Wohnort: RGFybXN0YWR0
Der Rest des Forums hat sich recht einstimmig auf das Buch eingeschossen, BlackJack hat sogar eine (sehr negative) Kritik verfasst, ich bin mir da auch sehr sicher, dass es nicht empfehlenswert ist.rads hat geschrieben:Leonidas kann dir hier sicherlich ein gutes Python Buch empfehlen, welches genau das beschreibt. Ich fand das Galileo Python OpenBook ganz gut, vielleicht zu umfangreich. http://openbook.galileocomputing.de/python/
Wie Leonidas schon gesagt hat, ist der direkte Zugriff auf Instanzvariablen kein Problem, schliesslich kann man Aenderungen an der Implementierung mit Properties fuer den Anwender abstrahieren.
@heiliga horsd: In C++/Java kann man eine Methode ueberladen, sodass je nach Typ der Argumente etwas anderes ausgefuehrt wird. Das ist typbasiertes Dispatching.
Ducktyping heisst, dass man Objekte, die sich gleich verhalten (lingua python: diesselben Protokolle implementieren) auch gleich behandelt.
EAFP: "it's Easier to Ask Forgiveness than Permission", im Allgeinen ein auf Exceptions ausgerichteter Programmierstil.
Michael Markert ❖ PEP 8 Übersetzung ❖ Tutorial Übersetzung (3.x) ⇒ Online-Version (Python 3.3) ❖ Deutscher Python-Insider ❖ Projekte
Oder anders gesagt: Man guckt nicht so sehr auf den Typ sondern versucht, die-und-die Methode auszuführen. Existiert die Methode nicht, gibt es einen Fehler und es wird wohl das falsche Objekt übergeben worden sein. Den Fehler hätte man ja bei expliziter Typprüfung genau so, nur dass man sich a) die Zeilen dafür sparen kann und b) eben auch alternative Typen behandeln kann.cofi hat geschrieben:Ducktyping heisst, dass man Objekte, die sich gleich verhalten (lingua python: diesselben Protokolle implementieren) auch gleich behandelt.
@heiliga horsd: Schau dir zum Beispiel mal den Code vom Modul StringIO an. Damit kann man Funktionen, die eine Datei erwarten, einfach eine solche vorgaukeln. Die `.read()`-Methode wird sich genau so verhalten, wie die Funktion es erwartet - außer natürlich, sie testet es vorher explizit und merkt, dass sie nichts vom Typ `file` bekommen hat...
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Wie cofi schrieb führt eben dieses Buch zu "code smells" da die Autoren versuchen Konzepte aus Java nach Python bringen die in Pyhton eben keine gute Idee sind. Wenns um idiomatischen Code geht ist "Expert Python Programming" besser geeignet - auch wenn nicht direkt für Einsteiger.rads hat geschrieben:Leonidas kann dir hier sicherlich ein gutes Python Buch empfehlen, welches genau das beschreibt. Ich fand das Galileo Python OpenBook ganz gut, vielleicht zu umfangreich. http://openbook.galileocomputing.de/python/
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Also, ich versuch das jetzt mal in eigenen Worten zusammenzufassen:
Als CodeSmell ist in Python Code gemeint, der entweder gegen "pythonische Philosophie" verstößt, wie Beispielsweise Typprüfungen beim in Python verwendeten Duck Typing, oder eben Dinge unnötig verkompliziert, wie zum Beispiel das ermitteln der Länge einer Liste um dann darüber zu iterieren anstatt gleich über die Liste zu iterieren. CodeSmell ist jedoch durchaus legitim, wenn sich eine äquivalente Funktion nur mit deutlichem Mehraufwand entwickeln ließe.
Kann man das so stehen lassen?
Als CodeSmell ist in Python Code gemeint, der entweder gegen "pythonische Philosophie" verstößt, wie Beispielsweise Typprüfungen beim in Python verwendeten Duck Typing, oder eben Dinge unnötig verkompliziert, wie zum Beispiel das ermitteln der Länge einer Liste um dann darüber zu iterieren anstatt gleich über die Liste zu iterieren. CodeSmell ist jedoch durchaus legitim, wenn sich eine äquivalente Funktion nur mit deutlichem Mehraufwand entwickeln ließe.
Kann man das so stehen lassen?
Zuletzt geändert von heiliga horsd am Donnerstag 27. Mai 2010, 20:26, insgesamt 1-mal geändert.
derdon hat geschrieben:Ja. Aber ich muss hinzufügen, dass ich die Formulierung "… nicht ohne …" hasse; macht den Satz nur unnötig kompliziert!
Besser?Als CodeSmell ist in Python Code gemeint, der entweder gegen "pythonische Philosophie" verstößt, wie Beispielsweise Typprüfungen beim in Python verwendeten Duck Typing, oder eben Dinge unnötig verkompliziert, wie zum Beispiel das ermitteln der Länge einer Liste um dann darüber zu iterieren anstatt gleich über die Liste zu iterieren. CodeSmell ist jedoch durchaus legitim, wenn sich eine äquivalente Funktion nur mit deutlichem Mehraufwand entwickeln ließe.