2008-12-06 10 views

Antwort

47

Die Dinge, die vor allem für mich durchhalten sind „code smells“.

Meistens bin ich empfindlich gegenüber Dingen, die gegen "gute Praxis" stehen.

Dinge wie:

  • Methoden, die Dinge tun, andere als das, was man aus dem Namen denken würde (zB: FileExists(), die Null-Byte-Dateien leise löscht)

  • Ein paar extrem lange Verfahren (Zeichen eines Objekts Wrapper um eine Prozedur)

  • Wiederholte Verwendung von Schalter/case-Anweisungen auf dem gleichen Aufzählungsglied (Zeichen der Unterklassen, um Extraktion)

  • Viele Mitgliedsvariablen, die für die Verarbeitung verwendet werden, nicht Zustand zu erfassen (könnte darauf hindeuten, müssen ein Verfahren Objekt extrahieren)

  • Eine Klasse, die viele Aufgaben (Verletzung von Einzel repsonsibility Prinzip)

  • hat

    Lange Ketten von Member-Zugriff (this.that in Ordnung, this.thatOthe ist gut, aber my.very.long.chain.of.member.Accesses.for.a.Ergebnis ist spröde)

  • Schlechte Benennung von Klassen

  • Die Verwendung von zu vielen Design-Muster in einem kleinen Raum

  • Arbeiten zu hart (Funktionen bereits im Rahmen Umschreiben oder an anderer Stelle in der gleichen Projekt)

  • Schlechte Rechtschreibung (überall) und Grammatik (in den Kommentaren) oder Kommentare, die einfach sind

irreführend 210
+0

Schöne Liste, +1. Ich bin jedoch neugierig auf die übermäßige Designmusterdichte. Hast du das wirklich erlebt? Ich würde sagen, es ist mehr, wenn Muster missbraucht und missbraucht werden. – philant

3

Eine Sache, die ich hasse, zu sehen, ist eine Basisklasse, die sich auf eine abgeleitete Klasse herunterwirft. Wenn Sie das sehen, wissen Sie, dass Sie Probleme haben.

Andere Beispiele könnten sein:

  • Der übermäßige Gebrauch von switch-Anweisungen
  • Abgeleitete Klassen, die alles
+0

„eine Basisklasse nach unten Guss selbst zu einer abgeleiteten Klasse "- wie immer gibt es eine Ausnahme, die bei der Verwendung von CRTP implementiert wird nicht simulierte dynamische Bindung in C++. Die abgeleitete Klasse wird an die Basisklasse als Vorlageparameter übergeben, sodass Sie absolut sicher wissen, dass der Cast gültig ist. –

+0

Das ist sehr anders als das, worüber ich spreche. Ich spreche darüber, wenn eine Fahrzeugklasse weiß, dass die Fahrzeugklasse existiert. In Ihrem Fall hat die Basisklasse immer noch keine Kenntnis von der abgeleiteten Klasse. Wie du schon sagtest, Ausnahmen von Regeln. Ich würde sie nicht einmal Regeln nennen ... Warngerüche vielleicht? –

+0

Nun, die Basis * Klasse * hat spezifische Kenntnisse der abgeleiteten Klasse, es ist nur so, dass der Programmierer nur direkt mit der Basis * Klassenvorlage * beschäftigt ist, was nicht der Fall ist. C++ ist reines Gold für Pedanten ;-) –

1

hier ein paar außer Kraft setzen:

  • Kreis Abhängigkeiten
  • Sie mit Eigenschaft XYZ von ab ase-Klasse wurde nicht geschützt/private
  • Sie möchten Ihre Sprache Mehrfachvererbung unterstützt
+0

Ich muss dem dritten nicht zustimmen. Manchmal kann MI eine gute Sache sein, wenn es richtig verwendet wird. –

2

Meiner Ansicht nach degeneriert der gesamte OOP-Code über eine ausreichend lange Zeitspanne zum prozeduralen Code.

Zugegeben, wenn Sie meine letzte Frage lesen, könnten Sie verstehen, warum ich ein wenig abgestumpft bin.

Das Hauptproblem bei OOP ist, dass es nicht offensichtlich macht, dass Ihr Objektkonstruktionsdiagramm unabhängig von Ihrem Aufrufdiagramm sein sollte.

Sobald Sie dieses Problem beheben, beginnt OOP tatsächlich Sinn zu machen. Das Problem ist, dass nur sehr wenige Teams dieses Designmuster kennen.

+0

Hallo, ich verstehe nicht. Könnten Sie bitte ein Beispiel angeben? Vielen Dank. – user712092

0

Wenn Sie alle Objekte geerbt haben, übernehmen Sie einige Basis-Dienstprogrammklassen, damit Sie Ihre Hilfsmethoden aufrufen können, ohne so viel Code eingeben zu müssen.

15

Einheitstest nicht möglich.

+1

Bingo! Siehe meinen Kommentar. Der schlimmste Teil ist, dass mindestens 90% des Codes, den Sie jemals sehen werden, nicht korrekt zu testen ist. –

+0

Ich glaube, das ist dasselbe wie "hohe Kopplung" zu sagen. –

17

Überprüfen Sie dies. Es ist toll.

Bad Smells: http://c2.com/xp/CodeSmell.html

Es ist nicht spezifisch orientierte Programmierung Objekt, aber es hat eine Menge von Bits umfasst. Prost.

+0

Gern geschehen, Jason. –

+1

Server scheint down zu sein, müssen wir es "Stackoverflown" -Effekt nennen (zusätzlich zu "slashdotted")? – dhiller

+0

@Dhiller: Ja, es scheint nach unten. Wie auch immer, an einem anderen Ort gefunden. –

18

würde ich die Nummer eins der Regel schlechter OO-Design sagen (und ja, ich habe schon viele Male davon zu zuschulden kommen!) Ist:

  • Klassen, die die Einzel Prinzip Verantwortung brechen (SRP) und führen zu viele Aktionen

Gefolgt von:

  • Too m uch Vererbung Zusammensetzung, d. h. Klassen, die von einem Untertyp rein abgeleitet werden so sie erhalten Funktionalität kostenlos. Bevorzugung Zusammensetzung über die Vererbung.
+0

Wahr. Möchte ein paar mehr hinzufügen, Programmierung zu einer Schnittstelle und Trennung von Bedenken. –

6

Diese Frage lässt die Annahme zu, dass objektorientiert gutes Design bedeutet. Es gibt Fälle, in denen ein anderer Ansatz viel geeigneter ist.

+0

+1, obwohl ich "einen anderen Ansatz" als "funktionalen Ansatz" sagen würde. Es gibt sehr wenige Entwurfsansätze, die nicht mindestens eine kleine Klasse von Problemen aufweisen, für die sie am besten geeignet sind. –

5

Ein Geruch ist Objekte mit harten Abhängigkeiten/Referenzen zu anderen Objekten, die nicht Teil ihrer natürlichen Objekthierarchie oder domänenbezogene Zusammensetzung sind.

Beispiel: Angenommen, Sie haben eine Stadtsimulation.Wenn das Objekt "Person" über eine NearestPostOffice-Eigenschaft verfügt, liegt wahrscheinlich ein Problem vor.

1

Suchen Sie einen Programmierer, der Erfahrung mit der Codebasis hat. Bitten Sie sie, zu erklären, wie etwas funktioniert.

Wenn sie sagen "diese Funktion ruft diese Funktion auf", ist ihr Code prozedural.

Wenn sie sagen "diese Klasse interagiert mit dieser Klasse", ist ihr Code OO.

+0

Was ist, wenn beide Klassen Singletons =) – FlySwat

+0

Ich meine "wenn sie ihren Code als die Beziehungen zwischen Klassen beschreiben, ist es OO; als die Beziehungen zwischen Methoden, es ist prozeduralen; wie die Beziehungen zwischen Aussagen, es ist Spagetti" –

2

Innerhalb einer langen Methode, Abschnitte mit # Region/# Endregion umgeben - in fast jedem Fall, den ich gesehen habe, könnte dieser Code leicht in eine neue Methode extrahiert werden ODER in irgendeiner Weise refaktoriert werden musste.

Übermäßig komplizierte Vererbungsbäume, in denen die Unterklassen sehr unterschiedliche Dinge tun und nur tangential miteinander verwandt sind.

Verletzung von DRY - Unterklassen, die jeweils eine Basismethode auf fast genau die gleiche Weise überschreiben, mit nur einer geringen Abweichung. Ein Beispiel: Ich habe kürzlich an Code gearbeitet, bei dem die Unterklassen jeweils eine Basismethode übertrafen und der einzige Unterschied ein Typtest war ("x ist ThisType" gegenüber "x ist ThatType"). Ich implementierte eine Methode in der Basis, die einen generischen Typ T annahm, den sie dann im Test verwendete. Jedes Kind könnte dann die Basisimplementierung aufrufen und den Typ übergeben, für den es getestet werden soll. Dadurch wurden etwa 30 Codezeilen von jeder der 8 verschiedenen untergeordneten Klassen abgeschnitten.

10

Anti-patterns

Software Design anti-Muster

  • Abstraktion Inversion: Nicht implementiert Funktionalität von Nutzern erforderlich aussetzt, so dass sie wieder umzusetzen höheren Funktionen
  • Mehrdeutige Sicht mit: Präsentieren eines Modells (normalerweise OOAD) ohne Angabe seines Standpunkts
  • Große Schlammkugel: Ein System ohne erkennbare Struktur
  • Blob: Generalisierung von Gott Objekt von objektorientierten Design
  • Gas Fabrik: ein unnötig komplexes Design
  • Eingang Flickschusterei: Failing Umgang mit möglicherweise ungültige Eingabe aufblasen
  • Schnittstelle zu spezifizieren und implementieren: eine Schnittstelle zu machen, so mächtig, dass es extrem schwierig zu implementieren ist
  • Magic Pushbutton: Codierung der Implementierungslogik direkt innerhalb des Schnittstellencodes, ohne Verwendung von Abstraktion.
  • Rennen Gefahr: Falls Sie die Folge der verschiedenen Ordnungen der Ereignisse
  • Railroaded Lösung zu finden: Eine vorgeschlagene Lösung, die während der arme, das einzige wegen der schlechten Voraussicht und Inflexibilität in anderen Bereichen des Design
  • Re verfügbar -Kupplung: Einführung unnötiger Beziehungs
  • Stovepipe System: Ein kaum wartbar Ansammlung von schlecht bezogenen Komponenten
  • Staralised Schema: Ein Datenbankschema doppelten Zweck Tabellen für normalisierte und Data Mart Verwendung enthält

Objektorientiertes Design anti-Muster

  • Anemic Domain Model: Die Verwendung von Domain-Modell ohne Business-Logik, die OOP ist nicht, weil jedes Objekt beiden Attribute haben sollte und Verhaltensweisen
  • BaseBean: Vererben Funktionalität von einer Utility-Klasse statt
  • Anruf super es zu delegieren: Erfordern Subklassen eine Oberklasse der überschriebene Methode
  • Kreis-Ellipse Problem zu nennen: Subtypisierung variabler Typen auf Basis von Value-Subtypen
  • Leere Unterklasse failure: Erstellen einer Klasse, die die „Empty-Subklassen-Test“ durch anders verhalten aus einer Klasse von ihm ohne Modifikationen
  • Gott Objekt abgeleitet versagt: Concentrating zu viele Funktionen in einem Teil des Entwurfs (Klasse)
  • Objekt Senkgrube: Wiederverwenden von Objekten, deren Zustand in den (möglicherweise implizit) Vertrag nicht
  • Objekt Orgie für den Wiedereinsatz entsprechen: Failing ermöglicht uneingeschränkten Zugang zu ihren Einbauten
  • Poltergeists richtig Objekte kapseln Objekte, deren einziger Zweck es ist, Informationen an ein anderes Objekt weiterleiten
  • Sequential Kopplungs: Hinzufügen von unnötigen Schichten zu einem Programm, Bibliothek oder Rahmen:
  • Noch eine Unbrauchbar Schicht Der Überbeanspruchung des Singletonmuster: Eine Klasse, die die Methoden erfordert in einer bestimmten Reihenfolge
  • Singletonitis genannt werden. Dies wurde nach dem ersten Buch über Programmierungsmuster populär.
  • Yo-yo Problem: Eine Struktur (zB der Vererbung), die aufgrund eines übermäßigen Zersplitterung
+0

Was ist das Besondere Problem mit einem Poltergeist? Die Gewinnung von Informationen in einer bestimmten Form scheint nicht Aufgabe des Zugangs, sondern des Inhabers dieser Informationen zu sein. –

+0

@ThomasE Initialisieren und Freigeben von kurzlebigen Objekten ist eine Verschwendung von Ressourcen und ein Zeichen für ein schlechtes OO-Design, siehe https://en.wikipedia.org/wiki/Poltergeist_(computer_programming) – philant

1

doppelte Code =-Code schwer zu verstehen ist, dass die gleiche Sache tut ... Ich denke, in meiner Erfahrung ist der größte Fehler, der beim OO-Design auftreten kann.

+0

Duplicate-Code ist nicht schlecht, wenn er es tut das gleiche aber aus anderen gründen. Eine übereifrige Anwendung von DRY kann zu einer unnötigen Kopplung von Funktionalität über Klassen- oder Domänengrenzen hinweg führen. Nur weil A f und B f tut und Af und Bf dasselbe tun, bedeutet das nicht, dass du ein Ff erstellen musst, das ein A oder ein B braucht, nur damit du Code nicht duplizierst ... besonders später Sie fügen Df hinzu und wenn Bf refaktoriert werden muss. –

0

Objekte sind gut schaffen eine gazillion von ihnen ist ein schlechtes OO Design.

Verwandte Themen