Was ist ein einfacher Prozess zum Entwerfen eines OOP-Systems vor dem Codieren?


10

Wann immer ich ein Projekt erstellen musste, gelang es mir immer, es zu erstellen, nicht bevor ich einen Plan oder Entwurf entwarf, sondern nachdem ich zuerst eine Klasse geschrieben hatte, die benötigt wurde, das gesamte Projekt ausgearbeitet und von unten nach oben aufgebaut hatte. Jetzt weiß ich, dass dies nicht der richtige Weg ist, um Software zu erstellen, aber es fällt mir nicht leicht, mich mit dem zu befassen, was als objektorientierte Analyse und Design bezeichnet wird. Ich kann das prozedurale Design von oben nach unten leichter verstehen, da es darin besteht, Aufgaben lediglich in Unteraufgaben zu zerlegen, Dinge, die ihr Gegenstück im Code haben, Funktionen. Aber objektorientierte Analyse und Design kann ich nicht leicht verstehen, denn ich verstehe nicht, wie man wissen kann, welche Klassen sie benötigen und wie sie interagieren, es sei denn, sie wissen, wie sie sie codieren.

Wenn wir einmal das Konzept von Klassen und Objekten in den Entwurfsprozess einführen, können wir nicht mehr von oben nach unten entwerfen, da wir unsere Probleme nicht mehr in die Dinge aufteilen, die als Prozeduren implementiert werden können. Stattdessen müssen wir gemäß dem, was ich zu diesem Thema gelesen habe, bestimmen, welche Klassen benötigt werden, und verschiedene Artefakte in Unified Modeling Language erstellen, die wir dann bei der Implementierung der Software verwenden können. Aber diese Art von Designprozess verstehe ich nicht. Denn woher weiß man, welche Klassen sie brauchen und wie sie interagieren werden, es sei denn, sie haben bereits das gesamte System konzipiert?

Das ist dann mein Problem. Ich verstehe nicht, wie man ein objektorientiertes System entwirft, obwohl ich die Konzepte der objektorientierten Programmierung verstehe und diese Konzepte in jeder mir bekannten objektorientierten Programmiersprache verwenden kann. Daher muss mir jemand erklären, mit welchem ​​einfachen Prozess ich objektorientierte Systeme so gestalten kann, dass sie für mich sinnvoll sind.


8
"Jetzt weiß ich, dass dies nicht der richtige Weg ist, um Software zu erstellen" - wer hat Ihnen das gesagt? Es scheint, als ob Sie in die beliebte Falle geraten, zu glauben, "Design ist etwas, was Sie vor dem Codieren tun, vielleicht indem Sie ausgefallene UML-Diagramme zeichnen". Um Sie von diesem Missverständnis zu befreien, empfehle ich, mit "Code as Design" von Jack Reeves zu beginnen.
Doc Brown


@ DocBrown. Denken Sie nicht, dass Design beim Codieren unseren Job so handwerklich macht? Ich kann mir nicht vorstellen, dass andere Maschinen gleich funktionieren. Stellen Sie sich einen Architekten vor, der Ziegel und Mörtel pillt und unterwegs das Gebäude / die Brücke entwirft.
Laiv

5
@Laiv: „Codierung“ ist Teil von dem, was in anderen Ingenieur - Disziplinen wird Design genannt. Im Hausbau erfolgt der Schritt vom Entwurf zum Endprodukt mit Pilling-Ziegeln und Mörtel. Bei der Programmierung wird dieser Schritt vom Compiler ausgeführt, wenn das Design (= Programm) in das Endprodukt (= ausführbare Binärdatei) übersetzt wird. Und das ist keine neue Weisheit. Reeves Essays sind 25 Jahre alt.
Doc Brown

@DocBrown, ist Entwickler. * Nicht mehr kuratiert? Die Schaltfläche zum Abonnieren ist beispielsweise defekt.
Radarbob

Antworten:


20

OOAD im Top-Down-Wasserfallstil stellt nicht sicher, dass der von Ihnen geschriebene Code überhaupt objektorientiert ist. Ich habe Berge von streng OOAD produziertem Code gesehen, der dies beweist. Wenn OO Sie verwirrt, suchen Sie hier nicht nach Hilfe. Du wirst es nicht finden. OO erfordert NICHT, dass Sie von oben nach unten entwerfen.

Wenn Sie gerne in eine Klasse eintauchen, ist das auch so. Lassen Sie mich Ihnen einen Hinweis geben. Zögern.

Es ist erstaunlich, wie einfach es ist, Klassen zu entwerfen, indem Code geschrieben wird, der sie verwendet, auch wenn sie noch nicht existieren. Prozedur vergessen. Struktur vergessen. Holen Sie sich einfach eine schöne, konsistente Abstraktionsebene und bleiben Sie dabei. Geben Sie nicht der Versuchung nach und mischen Sie zusätzliche Details hinein. Alles, was Sie aus der aktuellen Abstraktion herausholt, kann mit einer Methode ausgeführt werden, die sich möglicherweise auf einem anderen Objekt befindet, das irgendwie weiß, was es wissen muss. Bauen Sie nichts, was Sie nur verlangen können, um Ihnen übergeben zu werden.

Wenn Sie lernen, so zu schreiben, werden Sie feststellen, dass Sie OO machen, ohne sich auch nur sehr anzustrengen. Dies zwingt Sie dazu, Ihre Objekte unter dem Gesichtspunkt zu betrachten, wie sie verwendet werden (ihre Schnittstelle) und welche Objekte über welche anderen Objekte Bescheid wissen. Ratet mal, was sind die beiden Hauptpunkte eines UML-Diagramms?

Wenn Sie in diese Denkweise einsteigen können, bleibt nur noch Architektur übrig. Wir alle finden das immer noch heraus. Von MVC über saubere Architektur bis hin zu domänengesteuertem Design. Studiere sie und spiele. Verwenden Sie, was funktioniert. Wenn Sie etwas 100% Zuverlässiges finden, kommen Sie zurück und lassen Sie es mich wissen. Ich mache das schon seit Jahrzehnten und suche immer noch.


2
Oder du machst OO nicht und trotzdem funktioniert alles "irgendwie" gut ...
Derek Elkins verließ SE am

2
"Es ist erstaunlich, wie einfach es ist, Klassen zu entwerfen, indem Code geschrieben wird, der sie verwendet, auch wenn sie noch nicht existieren" - ich nenne dieses Top-Down-Design, aber es scheint, dass ich falsch liege. Was ist Top-Down-Design und wie habe ich das genannt? Programmiert es auf eine Schnittstelle?
Piovezan

Es ist nicht einfach von oben nach unten. Sie müssen auch bereit sein, keine Dinge zu erstellen, nach denen Sie nur fragen können, indem Sie Parameter akzeptieren.
candied_orange

@Piovezan Sie können dies auch tun, wenn die Schnittstelle noch nicht existiert. Ignorieren Sie einfach Ihren Compiler für ein bisschen. Später werden Sie es existieren lassen.
candied_orange

@CandiedOrange "Sie müssen auch bereit sein, keine Dinge zu erstellen, nach denen Sie nur fragen können, indem Sie Parameter akzeptieren." - Ich bin mir nicht sicher, ob ich das verstehe. Könnten Sie bitte ein kurzes Beispiel (oder ein Gegenbeispiel für diese Angelegenheit) klarstellen?
Piovezan

4

Sie behaupten, in Ihrem Code objektorientierte Techniken verwenden zu können. Da Sie also bereits wissen, wie man ein objektorientiertes System entwirft , ist Ihr Problem meines Erachtens eher eine Frage des Zeitpunkts , nicht der Frage, ob Sie dies können oder nicht. Sie scheinen mit objektorientiertem Design auf kurzfristige iterative Weise vertraut zu sein, anstatt auf langfristige Planungsweise.

Bei der ersten Entwicklung eines Projekts kann es sehr schwierig sein, zu planen und zu entwerfen. In diesem Fall wird die agile Entwicklung der Entwicklung von Wasserfällen vorgezogen , da der große Umfang eines Wasserfallplans häufig nicht alle Komplexitäten eines Softwareprojekts erfasst.

Sie behaupten, dass die spontane Entwicklung ohne "anfänglichen Plan" Folgendes ist:

"... nicht der richtige Weg, um Software zu erstellen ..."

Wenn Ihr Problem darin besteht, dass Ihr ursprünglicher Plan nicht detailliert genug ist, nehmen Sie sich etwas mehr Zeit, um Ihre ersten Gedanken zu erklären. Was ist der erste Teil des Programms, den Sie schreiben möchten? Was wird es brauchen ? Denken Sie vielleicht nicht einmal an die Objekte, mit denen Sie beginnen möchten, sondern an die Funktionen und den Plan von dort aus.

Wenn Ihr Problem darin besteht, dass Sie mit Ihren Dokumentations- / Design- / UML-Kenntnissen nicht vertraut sind , üben Sie, indem Sie ein vorhandenes Projekt dokumentieren.

Persönlich würde ich empfehlen, sich keine Sorgen darüber zu machen, dass Ihre Entwürfe perfekt objektorientiert sind. Die meisten Systeme sind nicht zu 100% objektorientiert. Ziel ist es, ein besseres Verständnis und eine bessere Visualisierung des Systems zu schaffen, nicht eine perfekte Abstraktion. Objektorientierung ist nicht die Silberkugel, sondern nur ein weiteres Werkzeug am Gürtel.


Ich wollte auch erwähnen, wenn auch etwas abseits des Themas für die Antwort ... Ihre Pläne müssen nicht sehr groß sein! Manchmal ist ein Plan nur eine Frage von "Ich möchte ihn ausführen und er macht eine Sache." Das ist gut genug, wenn das wirklich alles ist, was es tun wird.
Erdrik Ironrose

2

OOAD ist eine Utopie. Damit meine ich nicht, dass es der beste Ansatz ist, ich meine, dass er meiner bescheidenen Meinung nach niemals wirklich erreichbar ist. Nach meiner Erfahrung ändert sich immer etwas, sei es Anforderungen oder Besonderheiten oder sogar ein Abhängigkeitskonflikt, der Sie dazu zwingt, eine Abhängigkeit vollständig zu ersetzen. Ob es nun darum geht, dass ich auf diese Weise gelernt habe oder weil es für mich am natürlichsten ist, meine Ideen für Design kommen am schnellsten, wenn ich Code schreibe. Wenn ich im Begriff bin zu codieren und keine klare Vorstellung davon habe, wie ich den Code strukturieren werde, werde ich darauf achten, zuerst Zeit zu investieren, um das Problem wirklich zu verstehen, obwohl ich meistens das sehe Notwendigkeit für eine Klasse und ich werde es schaffen.

Mein Rat wäre, dass das Beste, was Sie für sich tun können, Code mithilfe von Fassaden ist , der eine einfache Schnittstelle für Eingabe und Ausgabe bietet, und hoffen, dass sich die Ein- und Ausgaben nicht oft ändern. Selbst wenn dies der Fall ist, sollten Sie wissen, dass es sich nicht um ein Designproblem handelt, sondern vielmehr um ein Spezifikationsproblem (Änderung der Notwendigkeit / des Betriebs / der Funktionalität). Dies macht Ihr Programm etwas widerstandsfähig gegen Probleme, die innerhalb Ihres Programms bei denen auftreten, die Ihr Programm oder Ihren Codeabschnitt aufrufen, und umgekehrt.

Was das Entwerfen eines objektorientierten Systems betrifft, sollte etwas gesagt werden, um zu versuchen, alles objektorientiert zu machen, wenn es nicht sein sollte. Dies ist ein häufiger Fehler bei OOP-Programmiersprachen wie C # und Java, wenn versucht wird, alles als Objekt zu behandeln. Dies führt häufig dazu, dass eine einzelne Instanz einer Klasse erstellt wird, um ansonsten statische Methoden auszuführen, die den Status überhaupt nicht ändern. Das heißt, natürlich sollten Sie gegebenenfalls das OOP-Design verwenden, obwohl Sie nicht das Gefühl haben, dass Sie es falsch machen, wenn es sich natürlicher anfühlt, eine statische Methode zu schreiben. Es ist nicht immer der falsche Instinkt.

Sie sollten die Verwendung einer Klasse in Betracht ziehen, wenn Sie eine der folgenden Fragen mit Ja beantworten:

  • Verfüge ich über eine Gruppe von Informationen, die sich auf dasselbe Konzept beziehen (z. B. Vorname, Nachname, Adresse)?
  • Muss ich eine Operation ausführen, für die mehrere Informationen erforderlich sind (z. B. calculatePrice(basePrice, quantity, tax))?
  • Habe ich ein anderes, wenn mit großen Codeblöcken leicht unterschiedliche Operationen mit den gleichen oder ähnlichen Informationen ausgeführt werden (dh if(type == "cat") { meow(name); } else if (type == "dog") { bark(name); }==> animal.speak()) ?
  • Verfüge ich über eine vorhandene Klasse, die mehr als eine bestimmte Aufgabe ausführt und etwas zu groß wird?

Nach einer Weile wird es zur zweiten Natur, Klassen zu erstellen. Haben Sie keine Angst, sie zu verwenden, wenn Ihr Code in einen der oben genannten Fälle fällt. Ich hoffe das hilft!


2

Ich denke, dass die Punkte, die Doc Brown in den Kommentaren gemacht hat, viel mehr Sichtbarkeit verdienen als ein Kommentar, da er absolut Recht hat:

" Jetzt weiß ich, dass dies nicht der richtige Weg ist, um Software zu erstellen " - wer hat Ihnen das gesagt? Es scheint, als ob Sie in die beliebte Falle geraten, zu glauben, "Design ist etwas, was Sie vor dem Codieren tun, vielleicht indem Sie ausgefallene UML-Diagramme zeichnen". Um Sie von diesem Missverständnis zu befreien, empfehle ich, mit "Code as Design" von Jack Reeves zu beginnen. - Doc Brown 21. Juni um 5:27 Uhr

@Laiv: "Codierung" ist Teil dessen, was in anderen Ingenieurdisziplinen Design genannt wird. Im Hausbau erfolgt der Schritt vom Entwurf zum Endprodukt mit Pilling-Ziegeln und Mörtel. Bei der Programmierung wird dieser Schritt vom Compiler ausgeführt, wenn das Design (= Programm) in das Endprodukt (= ausführbare Binärdatei) übersetzt wird. Und das ist keine neue Weisheit. Reeves Essays sind 25 Jahre alt. - Doc Brown 21. Juni um 6:39 Uhr

Das gleiche Gefühl wird auch an anderen Orten wiederholt. Betrachten Sie Glenn Vanderburgs Vorträge über "Real Software Engineering" und in gewissem Maße seine Vorträge "Craft, Engineering und die Essenz der Programmierung" und "Craft and Software Engineering". Sehen Sie sich auch die WhatIsSoftwareDesign und TheSourceCodeIsTheDesign Seiten / Diskussionen über die C2 - Wiki.

Das Konzept, dass der Code das Design ist, ist für kein Paradigma spezifisch. Es kann gleichermaßen auf objektorientierte, funktionale, prozedurale, logische oder andere Dinge angewendet werden. Die zugrunde liegende Idee ist dieselbe - das Design ist der Quellcode selbst. Der Konstruktionsakt ist der Prozess, durch den der Quellcode (das Design) von einem Interpreter oder Compiler in eine verwendbare Sache verwandelt wird.

In einem komplexen System gibt es wahrscheinlich ein höheres Architekturdesign, bei dem Subsysteme, Komponenten, Module, Dienste identifiziert und Anforderungen zugewiesen werden, bevor Sie mit dem Schreiben von Code beginnen. Sie können UML verwenden, um Diskussionen rund um dieses Architekturdesign zu erstellen, zu dokumentieren und zu unterstützen. Betrachten wir die Idee von UML - Modi , dass Martin Fowler diskutiert , insbesondere UML als Skizze und UML als Hinweise . Berücksichtigen Sie auch einige Ideen aus Agile Modeling - Initial Architecture Modeling , Iteration Modeling und Just Barely Good Enough Models .

All dies bedeutet, dass der richtige Weg zum Erstellen von Software nicht darin besteht, das gesamte Projekt zu konkretisieren. Es geht darum, gerade genug Zeit damit zu verbringen, die wichtigsten (zum aktuellen Zeitpunkt) Anforderungen zu verstehen, technische Abhängigkeiten und Kompromisse zwischen den Anforderungen zu identifizieren und dann die Tatsache auszunutzen, dass Software weich ist. Beachten Sie auch, dass die Kosten für die Übernahme Ihres Designs und die Herstellung von Gegenständen unglaublich niedrig sind (insbesondere im Vergleich zur Übernahme eines Entwurfs und der Herstellung von Gegenständen in vielen anderen technischen Disziplinen). Wiederholen Sie also Ihre Design- (Codierungs-) Aktivitäten und profitieren Sie davon, wie einfach und kostengünstig es ist, Ihre Aktivitäten schrittweise zu erstellen oder zu ändern.


1

Bei OOAD geht es darum, Entitäten zu identifizieren und reale Objekte oder Konzepte bis zu einem gewissen Grad an Abstraktion zu modellieren. Sie werden es als einfacher empfinden, wenn Sie anstelle des Schreibens von Klassen zunächst Schnittstellen schreiben, da Sie diese noch nicht wirklich implementieren müssen, der Code jedoch kompiliert wird.

OOAD schließt nicht die Möglichkeit aus, im System als große Module zu denken. Das kannst du immer noch. Jedes Modul ist vorhanden, um eine Reihe von User Stories (Anwendungsfälle) zu erfüllen. Solche User Stories benötigen Klassen, die zusammenarbeiten, um sie zu erfüllen.

Ein wesentlicher Unterschied zwischen prozeduralen und OO-Ansätzen besteht darin, dass prozedurales Denken normalerweise Anforderungen auf Bildschirme abbildet, während OOD dazu neigt, darüber nachzudenken, was unter der Haube geschieht, sodass das Front-End von einer anderen Person oder auf Nicht-OO-Weise erstellt werden kann.

In der extremen Programmierung gibt es eine Technik namens CRC-Karten . CRC steht für "Class-Responsibility-Collaborators".

Grundsätzlich identifizieren Sie offensichtliche Klassen und weisen jeder eine Karte zu. Angenommen, die Klasse Invoicehat eine eigene Karte.

Für jede Klasse, die Karten hält, schreiben Sie, wie die Verantwortlichkeiten dieser Klasse aussehen würden, zum Beispiel "berechnet eine Gesamtsumme" .

Außerdem schreiben Sie für jede Kartenklasse, nach welchen anderen Klassen diese Klasse etwas fragen muss, um ihre eigenen Aufgaben zu erfüllen. Hier können Sie feststellen, dass Invoicedie Zusammenarbeit von InvoiceDetailoder sogar erforderlich ist, dass eine solche Klasse überhaupt benötigt wird.

Möglicherweise stellen Sie fest, dass einige Verantwortlichkeiten, von denen Sie dachten Invoce, dass sie zu einem ihrer Mitarbeiter gehören.

Nach der Übung wird jede Karte zu einer Klasse, jede Verantwortung zu einer Methode und jede Zusammenarbeitsbeziehung kann zu einer Komposition, einer Agregation oder einem bloßen Aufruf werden.

Diese Übung kann (und sollte) in einer Gruppe durchgeführt werden, an der auch Geschäftsleute teilnehmen.

Weitere Informationen zu dieser Technik finden Sie unter folgenden Links:

http://en.wikipedia.org/wiki/Class-responsibility-collaboration_card

http://www.extremeprogramming.org/rules/crccards.html

Beispiele für CRC-Karten:

Geben Sie hier die Bildbeschreibung ein

Geben Sie hier die Bildbeschreibung ein

Geben Sie hier die Bildbeschreibung ein


0

Die größte Herausforderung für uns als Community von Software-Praktikern; Insbesondere objektorientierte Designpraktiker sind alle unsere Probleme / Aufgaben in einem Programmier-Couterpart zu materialisieren. Sei es Aufgaben - dargestellt als Funktionen oder Akteure der Aufgaben - dargestellt als Schnittstellen / Klassen [Richtung OOAD]. Während wir unsere Gewohnheiten beim Software-Design weiterentwickeln, gewinnen wir kontinuierlich Wissen über verschiedene Methoden / Frameworks. Unsere Sichtweise wird immer verfeinert, um die Objekte klar voneinander zu trennen und welches Objekt welche Funktion erfüllen würde.

Wenn Sie Ihre Probleme in Unterprobleme mit dem Vorhandensein von Objekten in der Umgebung aufteilen möchten, können Sie dies dennoch bequem tun, da SIE die vollständige Kontrolle darüber haben, welche Objekte Sie präsentieren möchten. Sie haben auch die Bequemlichkeit, Ihren Objekten und Schnittstellen Natur und Zweck zu verleihen. Alles, was Sie tun müssen, ist, die Problemstellung zu visualisieren und zu überlegen, welcher Zweck / welche Funktionalität auf welches Objekt übertragen werden kann.

Ich werde versuchen, anhand eines Beispiels für die Palette der Automobile weiter zu erklären, und ich werde zwei verschiedene Arten der Visualisierung desselben Objektmodells hervorheben.

Nehmen Sie ein Beispiel des Automobilherstellers, der sich über verschiedene Kategorien von Automobilen erstreckt: Nutzfahrzeuge, Konsumgüter (Limousinen, Schrägheck, Kombis) usw.

Damit der Hersteller eine klare Trennung von Kategorie und Zweck hat, gibt es mehrere Möglichkeiten, mit denen er Klassen erstellen kann.

Fahrzeughersteller OOAD

  1. Basierend auf der Fahrzeugkategorie (Marktsektor): Schweres Fahrzeug, Konsumfahrzeug [Limousine, Schrägheck, Kombi usw.]

  2. Basierend auf Motorleistung und Fahrweise: 800-1500 CC,> 1500 CC usw.

Auf die beste Art und Weise, wie der Hersteller Objekten, die zu jeder dieser Klassifikationen gehören, individuell Funktionen zuweisen kann, kann er ein geeignetes zugrunde liegendes Objektdesign auswählen und darauf ein Modell aufbauen.


Du fängst gut an, aber dann sieht das letzte bisschen wie der Irrtum aus, dass es bei OOD darum geht, Dinge zu kategorisieren, anstatt ähnliche Verhaltensweisen zu gruppieren.
Pete Kirkham
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.