Wie überwinde ich eine Lähmung durch Analyse beim Codieren?


37

Wenn ich ein neues Projekt beginne, denke ich oft sofort über die Details der Implementierung nach. "Wo soll ich den DataBaseHandler ablegen? Wie soll ich ihn verwenden? Sollten Klassen, die ihn verwenden möchten, von einer abstrakten Superklasse ausgehen? Soll ich eine Schnittstelle verwenden? Welche Abstraktionsebene soll ich in meiner Klasse verwenden, die enthält? Methoden zum Senden von Anfragen und zum Parsen von Daten? "

Ich bleibe lange stehen, weil ich aus Gründen der Erweiterbarkeit und Wiederverwendbarkeit programmieren möchte. Aber ich finde es fast unmöglich, darüber nachzudenken, wie man es perfekt umsetzt.

Und wenn ich dann versuche, nur zu sagen "Schrauben Sie es, machen Sie es einfach!", Stoße ich ziemlich schnell auf eine Mauer, weil mein Code nicht organisiert ist, ich Abstraktionsebenen gemischt habe usw.

Mit welchen Techniken / Methoden können Sie ein neues Projekt starten und gleichzeitig eine logische / modulare Struktur aufbauen, die sich gut skalieren lässt?

- - BEARBEITEN - -

Nun, dies ist bereits die Art von Frage, auf die es schwierig ist, eine Antwort zu akzeptieren, die aber noch mehr Rückmeldungen erfordert, um festzustellen, ob es einen Konsens gibt. TDD klingt wirklich cool und ehrlich gesagt wollte ich mich mit JUnit usw. vertraut machen. Was denken die TDD-Fans darüber, dass ein legitimer Punkt in Bezug auf TDD meine Probleme löst? Ein besonderes Problem ist, dass TDD die Frage des Designs nicht wirklich zu beantworten scheint. Sicher, ich bin damit einverstanden, dass TDD mir dabei helfen wird, zu definieren, was ich tun möchte, und dann kann ich nach und nach das Wie durcharbeiten, aber es gibt viele verschiedene allgemeine Entwurfsmuster / -strukturen, die alle Unit-Tests bestehen könnten. Das war's auch schon: Es testet einzelne UNITS. Ich glaube, ich bin ein bisschen verwirrt ... ich weiß nicht. Vielleicht habe ich

Vielen Dank!


2
Treten Sie zurück, schnappen Sie sich einen Stift und Papier und zeichnen Sie das größere Bild. Auf diese Weise können Sie die Implementierung strukturierter gestalten, anstatt sich im Detail zu verlieren ...
Darknight,

Das ist eine gute Frage. Dies ist eine Falle, in die ich mich schuldig gemacht habe.
Corv1nus

Antworten:


16

Ich empfehle die Verwendung von Test-Driven-Development , es ist gewöhnungsbedürftig, besonders wenn man mit einer guten IDE wie Eclipse arbeitet, aber die Vorteile sind groß.

Im Grunde schreiben Sie die Tests in Ihren Code, bevor Sie den Code selbst schreiben. Sie müssen also Ihren Code unter dem Gesichtspunkt seiner Verwendung betrachten, was bedeutet, dass sich Ihre Schnittstellen mit den von Ihnen implementierten Szenarien weiterentwickeln.

Ein weiteres Merkmal besteht darin, dass Sie sehr kleine Chunks implementieren (diese werden umso größer, je erfahrener Sie mit der Technik und der Programmierung sind), sodass Sie sich jedes Mal auf ein sehr kleines und genau definiertes Problem konzentrieren müssen.

Und da Sie zuerst einen Test schreiben und erst dann implementieren, haben Sie einen fehlerhaften Test vor sich. Wenn Sie also wie die meisten Programmierer sind, werden Sie sich nicht von verrückten Analysen hinreißen lassen, denn Sie werden denken: "Ich muss dafür sorgen, dass dieser Test funktioniert".

Ein kurzes Java-Beispiel:
Angenommen, ich möchte ein Programm entwickeln, das eine Nachricht aus einer Datenbank liest und schreibt.

Also fange ich mit der ersten genau definierten Aktion an, ich brauche einen DB:

@Test
public void testDB() {
  DB db = DbConnector.getDB(address);
  assertNotNull(db);
}

ok, hier sehe ich also, dass ich die DbConnector.getDB-Klasse implementieren muss, damit sie die DB zurückgibt, bis dieser Test fehlschlägt. Ich gehe und mache das ...

Wenn ich das nächste, was ich tun möchte, nicht hinzufüge, lade ich die Nachricht aus der DB:

@Test
public void testDB() {
  DB db = DbConnector.getDB(address);
  assertNotNull(db);
  String message = db.fetchMessage(key);
  assertEquals("hello world", message);
}

Jetzt habe ich der Datenbank eine weitere kleine Funktion hinzugefügt, die darin besteht, eine Nachricht abzurufen. Nachdem ich fertig bin, setze ich diese Funktion nacheinander fort, bis ich Folgendes erreiche:

@Test
public void testDB() {
  DB db = DbConnector.getDB(address);
  assertNotNull(db);
  String message = db.fetchMessage(key);
  assertEquals("hello world", message);
  message = "foo bar";
  db.storeMessage(message);
  message = db.fetchMessage();
  assertEquals("foo bar", message);
}

Es mag wie ein sehr einfaches Beispiel erscheinen, aber dies funktioniert auch für komplexere Aufgaben. Ich weiß, dass es anfangs sehr zeitaufwändig ist, aber wenn man sich daran gewöhnt, stellt man fest, dass es tatsächlich viel effizienter ist. Zum einen vermeiden Sie die Lähmung durch Analyse und zum anderen erhalten Sie viel robusteren Code, der normalerweise weniger Fehler aufweist und weniger Iterationen durchläuft.


4
Und TDD zwingt Sie zu vielen Umgestaltungen, sodass Sie in einen Arbeitsmodus des kontinuierlichen Umgestaltens geraten, der Ihnen hilft, die Mauer des durcheinandergebrachten Codes zu durchbrechen, wie beispielsweise programmers.stackexchange.com/questions/86364/… said.
Cringe

Ich finde den Test-First-Aspekt von TDD tatsächlich ein Hindernis für diese Art von Umständen. Wenn ich genug Probleme beim Entwerfen der Benutzeroberfläche habe, wie wird das Entwerfen der Tests einfacher oder offensichtlicher? Das und die Refactor-Bürde am Anfang, etwas zu entwerfen, ist viel zu hoch. Ich frage mich, wie andere damit umgehen.
Steven Evers

1
@ SnOrfus, richtig. TDD funktioniert gut, wenn Sie Ihre Module haben und sich darauf konzentrieren möchten, was und wie. Diese Module können jedoch auf verschiedene Arten organisiert werden. Wie sie gruppiert sind, welche Art von Struktur Sie verwenden werden, wird durch TDD nicht wirklich geklärt.
LuxuryMode

5
Hmmmm, das klingt wie ein TDD-Fan. Was ist jemals passiert, als ich mit Stift und Papier eine Architektur entworfen habe? oder bin ich altmodisch und nicht "hip" genug ...
Darknight

1
Stift und Papier (oder Whiteboard) sind gut. Skizzieren Sie den Gesamtplan, das Gesamtbild. Wenn es nicht auf ein Stück Papier passt, ist es zu kompliziert. Sobald Sie den Gesamtüberblick haben, können Sie sich mit BDD, Spott usw. beschäftigen.
Donal Fellows

10

Das passiert mir, also habe ich mir angewöhnt, eine Denkweise der kontinuierlichen Umgestaltung zu akzeptieren (und zu akzeptieren). Ich mache das Einfachste, was funktionieren könnte, dann räum ich auf, organisiere es, entkopple es, teste es und mache weiter.

Das soll nicht heißen, dass nicht viel geplant wird, aber es geschieht sehr schnell und öfter als Kritzeleien auf Schrott oder in meinem Kopf. Alles in allem nenne ich diese kleinen Prozess-Mikro-Iterationen manchmal, weil sie jeweils 5-20 Minuten dauern und erfahrungsgemäß 2-3 Minuten dauern, bis ich fertig bin (je nachdem, was ich gerade mache, offensichtlich).

Als Randnotiz: Ich habe eine Reihe von Leuten in verschiedenen Schreibweisen unterrichtet (Berichte, Aufsätze und technisches Schreiben im Allgemeinen), und auf diese Weise bringe ich sie dazu, Dinge zu schreiben, um die Blockade der Schriftsteller zu überwinden. "Platzieren Sie einfach alles, was Ihnen zu Ihrem Thema einfällt, auf der Seite. Dann machen wir einen Sinn daraus und teilen alles in Absätze auf und überprüfen den Ablauf. Wenn nötig, schreiben wir ihn sogar neu."


1
+1 für das Erwähnen des Schreibens. Ich habe kürzlich den Ansatz des häufigen Umgestaltens aus dem Programmieren übernommen und auf das Schreiben angewendet. funktioniert sehr gut für mich.
Zsolt Török,

2

Ein paar Dinge, die funktionieren könnten:

  • Identifizieren Sie das Kernproblem, das Sie zu lösen versuchen - was ist das Herzstück der Sache, die Sie tun möchten? Implementieren Sie genau das und das Minimum an Support-Code, damit es ausgeführt wird. Sobald es zu Ihrer Zufriedenheit funktioniert, können Sie es iterativ aufbauen und bei jedem Schritt ohne Gnade umgestalten.
  • Sehen Sie, ob andere Programmierparadigmen für Sie funktionieren. Trotz aller Vorzüge ist objektorientiertes Programmieren nicht die Antwort auf alle Probleme, und nicht alle Programmierer arbeiten auf diese Weise. Nimm eine (reine) funktionale Sprache auf; Schreiben Sie einen Verfahrenscode. Tauchen Sie auf die Hardware-Ebene und machen Sie ein C oder vielleicht sogar Assembler; usw. Ein paar Sprachen, die Ihren Geist aufrütteln könnten (vorausgesetzt, Sie verwenden gerade etwas wie C ++ / Java / C # / VB / ...): Haskell, ML, Lisp (verschiedene Dialekte zur Auswahl), Erlang, Prolog, Smalltalk, Javascript (wenn Sie loslassen und versuchen, es sich wie Java verhalten zu lassen und stattdessen seine schließende Natur zu akzeptieren), C, Pascal, awk und wahrscheinlich ein Dutzend mehr. Das Hauptmerkmal ist, dass sie sich stark von dem unterscheiden müssen, was Sie jetzt verwenden. Dies ist nicht etwas, was Sie bei einem großen Projekt mit viel auf dem Spiel haben wollen,
  • Verwenden Sie eine radikal andere Entwurfsmethode. Prüfen Sie, ob Sie das Motiv aus einem anderen Blickwinkel aufnehmen können. Ich gehe davon aus, dass Sie normalerweise mit dem Entwerfen beginnen, indem Sie Ihre Klassen auslegen. Wie wäre es, wenn Sie zur Abwechslung mit Datenstrukturen beginnen? Oder wie wäre es, wenn Sie zuerst die Benutzeroberfläche entwerfen und Eingabemasken buchstäblich zeichnen, bevor Sie Funktionen entwerfen?

1

Bei vielen Entwurfsentscheidungen kann es hilfreich sein, einen "Spike" zu erstellen, bei dem es sich um einen kurzen, zeitlich begrenzten Forschungsaufwand handelt, bei dem Sie einige Architektur- oder Entwurfsoptionen untersuchen können, indem Sie einen wegwerfbaren Prototypen codieren. Sie könnten beispielsweise die Verwendung einer Open-Source-Bibliothek oder die Organisation Ihrer Klassen und Schnittstellen untersuchen. Der Schlüssel ist, es kurz zu halten, damit Sie einen anderen Ansatz ausprobieren können, wenn der erste nicht zufriedenstellend ist, und Sie hoffentlich genug Wissen in der Übung erlangen, um die architektonischen Entscheidungen besser zu treffen oder das Konzept zu beweisen. Die Übung selbst beinhaltet eine sofortige Codierung, die dabei hilft, aus dem "Schreibblock" herauszukommen, ohne sich notwendigerweise zu früh auf das "Getan" festzulegen.

Danach ist es von Vorteil, den von Asaf erwähnten TDD- oder BDD-Ansatz zu verwenden, um die Umsetzung des Projekts voranzutreiben.


+1 Ich stimme zu. Planen Sie, den ersten Versuch zu verwerfen. Behandle es als eine Lernerfahrung. Ich habe bis zu sechs weggeworfen, bevor ich denke, ich möchte beim siebten bleiben.
Mike Dunlavey

1

Du wirst es nicht brauchen , also denke am Anfang nicht zu viel nach.

Investieren Sie mehr Zeit, um das Ziel und das Problem zu definieren und zu verstehen.

"Erweiterbarkeit und Wiederverwendbarkeit" ist das natürliche Ergebnis des Lebenszyklus gut geschriebener Softwareprogramme.


0

Ich gehe davon aus, dass wir uns um ein mittelgroßes Projekt kümmern.
Ich würde anfangen, indem ich auf das Zeichenbrett gehe. Bevor Sie dies tun, sollten Sie Ihre funktionalen und nicht funktionalen Anforderungen bereithalten. Zuerst würden Sie sich die Software-Architektur ausdenken, dh alle Architekturmuster ansehen, die Ihren Anforderungen entsprechen.
Sobald Sie sich für das Aussehen Ihrer Architektur entschieden haben, sollten Sie sich mit dem einfachen Design befassen, dh alle Entitäten, Klassen und Funktionen ansehen . Hier versuchen Sie erneut, Entwurfsmuster zu identifizieren, die passen. Dabei kennen Sie Ihre Basisklassen und die Schnittstellen, die Sie benötigen würden.
Anschließend können Sie das Framework erstellen und einige schnelle Tests durchführen, um festzustellen, ob dies der Fall ist erfüllt alle Ihre nicht funktionalen Anforderungen
Ich würde dann mit Test Driven Development gehen, wie @Asaf vorgeschlagen hat.

Denken Sie daran: Obwohl Sie viel Zeit mit Design und Architektur verbringen, sollten Sie immer bereit sein, die Architektur zu überdenken, wenn dies erforderlich ist.


0

Ich denke, das ist eine großartige Frage, und nichts wird für alle funktionieren. Ich denke, dass eine solche Lähmung ein natürliches Nebenprodukt ist, wenn man auf Ihrem Gebiet immer kompetenter wird. Das heißt, hier sind ein paar Dinge, die mir helfen, aber das Problem nicht lösen:

  • Legen Sie Ihr unberührtes Projekt beiseite und arbeiten Sie an der flüchtigen Version. In dieser Version sagst du dir: a. Der Code soll nicht schön sein. Sagen Sie sich, dass umfangreiche Umgestaltungen und Neuformatierungen nicht zulässig sind. Lassen Sie es absolut unorganisiert sein und befreien Sie sich von den Bindungen guter Codierung. b. Es muss einfach funktionieren. c. Es ist für mich immer wieder überraschend, was ich über den Problemraum erfahre, wenn ich alle anderen Bedenken rauswerfe. Ich habe auch kleine Leckerbissen, die mir oft helfen, das richtige Design auf eine aufschlussreichere Art und Weise zu finden.

  • Planen Sie einen angemessenen Zeitraum ein, in dem Sie am Projekt arbeiten, nur ohne Computer. Versuchen Sie, sich vorzustellen, was Sie wirklich erreichen wollen, und suchen Sie nach dem magischen Zen, der den Wahnsinn von OO / Design Pattern überwindet.


0

Geben Sie Ihren Gedanken einen konkreten Ausdruck: Schreiben Sie sie auf, zeichnen Sie sie auf oder was auch immer. Dies wird Ihnen helfen, Ihre Gedanken bei Bedarf zu überdenken. Es wird dich davon abhalten, im Kreis zu fahren. hilft Ihnen, klarer zu denken.

Immer wenn ich sehe, dass ich nirgendwo hin gehe und überall über etwas nachdenke, schreibe ich sie ein und es hilft mir, klar zu denken.


0

Normalerweise beginne ich von Grund auf, erstelle den einfachsten Prototyp und bringe etwas zum Laufen. Verwenden Sie den Prototyp, um die Happy Path-Testfälle rückzuentwickeln, die Testfälle, um die Schnittstellen anzusteuern, und überlegen Sie sich dann Pre / Post-Verträge, um die Testabdeckung zu verbessern.

Sorgen Sie sich nicht um Abstraktion, Optimierung oder Verifizierung, bis das Problem vollständig verstanden ist.

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.