2010-03-26 5 views
11

Vielleicht liegt es daran, dass ich jetzt ungefähr zwei Semester programmiert habe, aber der größte Stolperstein, den ich an diesem Punkt habe, ist die Umwandlung der Projektbeschreibung und der Anforderungen des Professors in tatsächlichen Code. Da ich mich derzeit in Algorithmen 101 befinde, mache ich grundsätzlich einen Bottom-up-Prozess, indem ich mit einem leeren Whiteboard anfange und die Interaktionen zwischen Objekt und Methode herausziehe und dann in Klassen und Code übersetze.Wie gehst du von einer abstrakten Projektbeschreibung zu tatsächlichem Code?

Aber jetzt hat der Prof Interfaces und abstrakte Klassen in den Mix geworfen. Intellektuell kann ich erkennen, wie sie funktionieren, aber ich stoße mir die Zehen aus und finde heraus, wie man diese neuen Werkzeuge mit dem aktuellen Projekt verwendet (Simulation eines Webservers).

In den Worten meiner Professoren ist die Zuordnung der abstrakten Beschreibung zu Java-Code der eigentliche Trick. Welche Schritte werden am besten verwendet, um von Englisch (oder was auch immer Ihre Sprache ist) zu Computer-Code zu gehen? Wie entscheiden Sie, wo und wann Sie eine Schnittstelle erstellen oder eine abstrakte Klasse verwenden?

Antwort

6

Welche Schritte werden am besten verwendet, um von Englisch (oder welcher Sprache auch immer) zum Computercode zu wechseln?

Erfahrung lehrt uns, wie man das macht. Wenn es nicht natürlich noch kommen (! Und fühle mich nicht schlecht, wenn es nicht der Fall ist, weil es eine lange Zeit in Anspruch nimmt), gibt es einige Fragen, die Sie sich stellen können:

  • Was sind die wichtigsten Konzepte von das System? Wie sind sie miteinander verwandt? Wenn ich dies jemand anderem beschreiben würde, welche Wörter und Sätze würde ich verwenden? Diese Gedanken werden Ihnen helfen zu entscheiden, über welche Klassen Sie nachdenken können.

  • Welche Art von Verhalten haben diese Dinge? Gibt es natürliche Abhängigkeiten zwischen ihnen? (Zum Beispiel ist LineItem nicht relevant oder sinnvoll ohne den Kontext einer Order, noch ist eine Engine viel zu verwenden ohne Car.) Wie beeinflussen die Verhaltensweisen den Zustand der anderen Objekte? Kommunizieren sie miteinander, und wenn ja, auf welche Weise? Diese Gedanken helfen Ihnen, die öffentlichen Schnittstellen Ihrer Klassen zu entwickeln.

Das ist natürlich nur die Spitze des Eisbergs. Mehr über diesen Gedankenprozess im Allgemeinen finden Sie in Eric Evans exzellentem Buch, Domain-Driven Design.

Wie entscheiden Sie, wo und wann Sie eine Schnittstelle erstellen oder eine abstrakte Klasse verwenden?

Es gibt keine festen Rezepte; Wiederum ist Erfahrung der beste Wegweiser. Das heißt, es gibt sicherlich einige Faustregeln Sie folgen können:

  • Wenn mehrere unabhängige oder signifikant unterschiedliche Objekttypen alle die gleiche Art von Funktionalität, eine Schnittstelle verwenden. Zum Beispiel, wenn die Steerable Schnittstelle eine Steer(Vector bearing) Methode hat, kann es viele verschiedene Dinge geben, die gesteuert werden können: Boat s, Airplane s, CargoShip s, Car s, und so weiter. Dies sind völlig voneinander unabhängige Dinge. Aber sie alle teilen die gemeinsame Schnittstelle, gesteuert werden zu können.

  • Versuchen Sie im Allgemeinen, eine Schnittstelle anstelle einer abstrakten Basisklasse zu bevorzugen. Auf diese Weise können Sie eine einzelne Implementierung definieren, die N Schnittstellen implementiert. Im Fall von Java können Sie nur eine abstrakte Basisklasse haben. Sie sind also an eine bestimmte Vererbungshierarchie gebunden, sobald Sie sagen, dass eine Klasse von einer anderen vererbt wird.

  • Wenn Sie keine Implementierung von einer Basisklasse benötigen, bevorzugen Sie definitiv eine Schnittstelle über eine abstrakte Basisklasse. Dies wäre auch praktisch, wenn Sie in einer Sprache arbeiten, in der die Vererbung nicht gilt. In C# können Sie beispielsweise nicht struct von einer Basisklasse erben.

+0

Ich weiß, dass es keine perfekte Antwort auf diese Frage gibt, aber danke, dass Sie mir das meiste zum Nachdenken gegeben haben. – Jason

3

Im Allgemeinen ...

  1. eine Menge anderer Leute Code lesen. Open-Source-Projekte sind dafür hervorragend geeignet. Respektieren Sie jedoch ihre Lizenzen.
  2. Sie werden es nie perfekt bekommen. Es ist ein iterativer Prozess. Sei nicht entmutigt, wenn du es nicht richtig machst.
  3. Praxis. Trainieren. Trainieren.
  4. Forschung oft. Nehmen Sie immer anspruchsvollere Projekte/Designs in Angriff. Auch wenn es leichte gibt.

Es gibt keine magische Kugel oder Algorithmus für gutes Design.

Heutzutage spring ich mit einem Entwurf herein, den ich glaube, ist anständig und Arbeit von diesem.

Wenn die Zeit richtig ist, werde ich implementieren Verständnis, dass das Ergebnis eher früher als später refaktoriert (neu geschrieben) werden muss.

Geben Sie diesem Projekt das Beste, halten Sie Ausschau nach Ihren Fehlern und wie die Dinge nach Ihrer Rückkehr aussehen sollten.

Tun Sie dies weiter, und es wird Ihnen gut gehen.

3

Was Sie wirklich tun sollten, ist code from the top-down, not from the bottom-up. Schreiben Sie Ihre Hauptfunktion so klar und prägnant wie möglich, indem Sie APIs verwenden, die Sie noch nicht erstellt haben, als wären sie bereits vorhanden. Dann können Sie diese APIs auf ähnliche Weise implementieren, bis Sie Funktionen haben, die nur wenige Zeilen lang sind. Wenn Sie von unten nach oben codieren, werden Sie wahrscheinlich eine Menge Dinge erstellen, die Sie eigentlich nicht benötigen.

In Bezug auf wann eine Schnittstelle zu erstellen ... so ziemlich alles sollte eine Schnittstelle sein. Wenn Sie APIs verwenden, die noch nicht existieren, nehmen Sie an, dass jede konkrete Klasse eine Implementierung einer Schnittstelle ist, und verwenden Sie einen deklarierten Typ, der auf diese Schnittstelle hinweist. Ihre Vererbung sollte ausschließlich mit Schnittstellen erfolgen. Erstellen Sie nur ganz unten konkrete Klassen, wenn Sie eine Implementierung bereitstellen. Ich würde vorschlagen, abstrakte Klassen zu vermeiden und Delegierung nur zu verwenden, obwohl abstrakte Klassen auch dann sinnvoll sind, wenn sich zwei verschiedene Implementierungen nur geringfügig unterscheiden und mehrere Funktionen haben, die eine gemeinsame Implementierung haben. Wenn Ihre Schnittstelle zum Beispiel die Möglichkeit bietet, über Elemente zu iterieren und auch eine Summenfunktion zur Verfügung stellt, ist die Summenfunktion trivial in Bezug auf die Iterationsfunktion zu implementieren, so dass eine sinnvolle Verwendung einer abstrakten Klasse möglich wäre. Eine Alternative wäre, das Dekorationsmuster in diesem Fall zu verwenden.

Vielleicht finden Sie auch die Google Techtalk "How to Design a Good API and Why it Matters" hilfreich in dieser Hinsicht. Sie könnten auch daran interessiert sein, einige meiner eigenen software design observations zu lesen.

0

Auch für die kommende Zukunft können Sie in der Pipeline bleiben, um die Grundlagen auf domain driven design zu lesen, um sich auf die realen Szenarien auszurichten - es gibt eine solide Grundlage für die Zuordnung der Anforderungen zu den realen Klassen.

Verwandte Themen