Ich habe gerade den Artikel-Link gelesen, den Sie gepostet haben. Ich muss sagen, Fowler hat einige sehr gute Punkte gemacht und viele Dinge, die er gesagt hat, habe ich seit Jahren mit unserem Team befürwortet.
IMO, wenn Sie ein anständiges Design machen, sollten Sie nicht in eine Sackgasse geraten. Ich habe Software immer als aus Bausteinen zusammengesetzt angesehen . Ich glaube immer noch an ein Vorab-Design, aber das Hauptziel ist nicht, das gesamte Produkt zu entwerfen, sondern die Gesamtarchitektur / -richtung bereitzustellen, damit Ihr Team ein gemeinsames Bild visualisieren kann, auf das wir alle hinarbeiten. Wenn Sie ein paar Würfel- und Dreiecksstücke haben, ist es hilfreich zu skizzieren, wie ein Schloss zusammengesetzt werden würde, bevor Sie einfach anfangen, Teile zusammenzuschlagen.
Da ich aus OO-Land komme, ist für mich jeder Block eine Klasse und die Oberfläche dieses Blocks ist die öffentliche Schnittstelle (was für externe oder abgeleitete Klassen sichtbar ist). Wenn Sie guten SOLID-Prinzipien folgen, stellen Sie sicher, dass jeder Block äußerst einfach ist und über eine intuitive öffentliche Oberfläche verfügt. Zurück zu meiner Analogie: Sie möchten sicherstellen, dass Ihr Code nur einfache Formen erstellt. Wenn Sie zu komplexe Klassen erstellen (viele Funktionen, viele Variablen), erstellen Sie Formen, die bei Änderungen der Anforderungen nur schwer wiederverwendet werden können.
Ich stimme Fowler darin zu, dass das größte Risiko / die größte Herausforderung für das evolutionäre Design darin besteht, dass Sie Designentscheidungen der Codierungszeit überlassen und von jedem einzelnen Entwickler erwarten, dass er diese Entscheidungen trifft. Hier kann das System ausfallen, wenn Sie nicht über die richtigen Feedback-Mechanismen verfügen. Wenn nach einer neuen Funktion gefragt wird, ist es äußerst verlockend, einfach die Funktion zu finden, die erweitert werden muss, eine Bedingung in sie zu setzen und einfach eine ganze Reihe von Code direkt in diese Funktion einzufügen. Und manchmal ist dies vielleicht alles, was benötigt wird, aber dies ist auch (IMO) die häufigste Praxis, die zu Sackgassenkomponenten führt. Dies hat nichts mit evolutionärem Design zu tun. Dies nennt man "kein Design".
Solange Sie sich die Zeit nehmen, einen Schritt zurückzutreten und zu sagen, warten Sie eine Minute, diese Klasse hat bereits 15 Mitgliedsvariablen. Lassen Sie mich 6 davon extrahieren und in eine eigenständige Klasse einfügen. Ihre Software besteht aus sehr leichtem Material -gewichtige, flexible und wiederverwendbare Bausteine. Sicher, wenn PMs kommen und die Hälfte der Produktanforderungen an Sie ändern, müssen Sie möglicherweise einige Ihrer Blöcke herausnehmen, sie wieder in das Regal stellen und einige neue erstellen (genau wie beim Bau eines Schlosses können Sie möglicherweise nicht alle verwenden Ihre Zylinder). Aber zu diesem Zeitpunkt ist das nur ein Teil des Geschäfts. Die Anforderungen haben sich geändert. Wenn Sie Ihren Code flexibel und modular halten, sollten Sie in der Lage sein, Ihr Produkt so zu ändern, dass es sich an Ihre neue Geschäftsrichtung anpasst.
Ich glaube, dass dieser evolutionäre Designansatz mit allen Fähigkeiten des Ingenieurs funktioniert. Persönlich habe ich sehr lange Software gemacht und bevor unser Team zu einer agilen Methodik überging, war ich dafür verantwortlich, mehrere wichtige Komponenten von meinem Entwicklungs-PC fast direkt mit kaum einer Qualitätssicherung an den Kunden zu liefern. Gleichzeitig sind diese Komponenten immer flexibel und wartbar geblieben.
Ich versuche nur zu sagen, dass ich mich beim Entwerfen von Software für relativ anständig halte. Wenn Sie mich gebeten haben, ein 100-seitiges Designdokument zu verfassen, es einem Codierer zu geben und zu erwarten, dass es funktioniert, könnte ich mich wahrscheinlich nicht aus einer Papiertüte heraus entwerfen. Wenn ich mit der Arbeit anfing, skizzierte ich manchmal einige UML-ähnliche (sehr vereinfachte, nicht vollständige) Diagramme, aber wenn ich mit dem Codieren anfing, überarbeitete ich sie nach Bedarf und mein endgültiger Code sah nie so aus, wie ich ihn ursprünglich gezeichnet hatte. Selbst wenn ich ein oder zwei Monate lang über jedes Detail nachdenke, kann ich mir nicht vorstellen, dass jemand anderes meine Diagramme aufnehmen und eine solide Software entwickeln kann, ohne das Design während der Codierung zu ändern.
Am anderen Ende des Spektrums, derzeit in meinem Team (jetzt agil und ich unterstütze das voll und ganz), haben wir ein paar Leute, die aus dem eingebetteten Land zu uns gekommen sind, wo sie in den letzten 15 Jahren nur C gemacht haben. Ich habe natürlich bei der anfänglichen Planung und Gestaltung von Kursen geholfen, aber ich habe auch darauf geachtet, regelmäßige Codeüberprüfungen und Brainstorming-Sitzungen durchzuführen, in denen wir Anwendungen von SOLID und Designprinzipien diskutieren. Sie haben einen Spaghetti-Code produziert, der mich ein wenig zusammenzucken ließ, aber mit nur einem kleinen Schubs von mir haben sie angefangen, das zu überarbeiten, was bereits produziert wurde, und der lustige Teil ist, dass einer von ihnen einige Tage später zu mir zurückkam und sagte, ich hasse um es zu sagen, aber nachdem dieser Code entfernt wurde, sieht dies viel lesbarer und verständlicher aus. Sackgasse abgewendet. Punkt I ' Ich versuche zu machen, dass selbst jemand, der für OO völlig neu ist, etwas anständigen Code produzieren kann, solange er einen Mentor mit mehr Erfahrung hat, um ihn daran zu erinnern, dass "evolutionäres Design" nicht dasselbe ist wie "kein Design". Und selbst einige seiner "komplexeren" Klassen sind nicht so beängstigend, weil jede Klasse nicht so viel Verantwortung hat (dh nicht so viel Code), also wird es schlimmer, wenn diese eine Klasse "Sackgassen" hat, wir Schmeißen Sie es und schreiben Sie eine Ersatzklasse mit derselben öffentlichen Schnittstelle (bisher habe ich in nichts, was wir geschrieben haben, eine Notwendigkeit für diese Kontingenz gesehen, und ich habe zweimal pro Woche Codeüberprüfungen durchgeführt).
Abschließend möchte ich auch fest an Designdokumente glauben (zumindest für die Geschäftsbedingungen meines aktuellen Teams), aber das Hauptziel für unsere Designdokumente ist das organisatorische Gedächtnis , sodass die tatsächlichen Dokumente geschrieben werden, nachdem der Code erstellt wurde und überarbeitet. Vor dem Codieren haben wir im Allgemeinen eine schnelle (manchmal nicht so schnelle) Entwurfsphase, in der wir Klassen für Servietten / mspaint / visio skizzieren, und ich erinnere die Leute immer daran, dass diese Phase einen Pfad erzeugt, dem sie folgen müssen, keine Blaupause, und wenn sie mit dem Codieren beginnen, Alles, was keinen Sinn ergibt, sollte geändert werden. Selbst mit diesen Erinnerungen neigen neuere Leute dazu, Code wieder in das ursprüngliche Design zu integrieren, egal wie unnatürlich es sich für sie anfühlt. Dies tritt normalerweise in Codeüberprüfungen auf.
Dang, ich habe viel geschrieben. Das tut mir leid.
Ich würde sagen, dass das Phänomen der "Design-Sackgasse" orthogonal zu agilen Methoden ist. Was ich meine ist, dass es möglich ist, Wasserfälle zu machen und viel Zeit im Voraus mit einem (schlechten) Design zu verbringen. Dann verbringen Sie viel Zeit damit, es zu implementieren, nur um sich in einer Sackgasse zu befinden.
Wenn überhaupt, agile Methoden sollten helfen Ihnen früher feststellen , dass Sie schlechte Design - Entscheidungen gemacht. Der Grund dafür ist, dass in Ihrem Backlog zuerst die Artikel mit dem höchsten Kundennutzen ausgeführt werden sollten und Sie sich darauf konzentrieren sollten, nützliche Schritte der Software bereitzustellen. Wenn Ihr Design es Ihnen ermöglicht, einen hohen Wert und Nutzen zu liefern, ist es bereits gut für etwas :-) Im Gegensatz dazu könnten Sie ein schlechtes Design in einer wasserfallartigen Situation haben, in der Sie möglicherweise jahrelang nicht herausfinden, dass dieses Design nicht liefern kann Jeder Wert und jede Nützlichkeit - alles, was Sie haben, ist die Illusion, dass es ein gutes Design ist. Wie sie sagen, ist der Beweis im Pudding.
Die Kehrseite ist, dass es selbst bei agilen Methoden wichtig ist, eine tragfähige Vision für das Systemdesign zu haben, die Entscheidungen von Iteration zu Iteration antreibt. Ich denke, Ken Schwabber sagte so etwas wie, wenn Sie ein Team von schrecklichen Entwicklern haben, die schlechte Software konsequent Iteration für Iteration produzieren. Agil bedeutet einfach, dass Sie nicht viel Zeit im Voraus verbringen, da Sie nur begrenzt lernen oder sich vorstellen können, bevor Sie mit der Implementierung beginnen ( und sich auch die Anforderungen ändern). Es gibt jedoch Situationen, in denen Sie im Voraus arbeiten müssen (z. B. Forschung), und dann müssen Sie das tun.
Wie vermeidet man Sackgassen?
Ich würde sagen, hauptsächlich durch Vorwegnahme zukünftiger Anforderungen. Dies erhalten Sie mit Erfahrung und Vertrautheit mit ähnlichen Projekten / Produkten. Diese Vorfreude hilft Ihnen teilweise dabei, ein gutes Design zu erstellen, da Sie sich viele "Was wäre wenn" -Fragen zu Ihrem aktuellen System stellen. Für mich ist dies die kritische Komponente. Techniken wie OO helfen Ihnen einfach, wenn Sie bereits wissen, was Sie tun.
Was machst du, wenn du eine Sackgasse hast?
Ein „dead-end“ ist nicht anders als jeder anderer technischer Block Sie werden bei der Entwicklung von etwas getroffen , die neu ist. Das erste, was zu erkennen ist, ist, dass es wirklich keine echten "Sackgassen" gibt, die Sie dazu zwingen, sich vollständig zurückzuziehen. Zumindest ermöglicht Ihnen Ihr Lernen bis zu diesem Punkt, vorwärts zu kommen, damit der Aufwand nicht verschwendet wird. Wenn Sie in eine Sackgasse geraten, haben Sie ein Problem . Das Problem ist, was geändert werden muss, um eine neue (oder alte) Anforderung zu erfüllen, und wie diese Änderung optimiert werden kann. Jetzt müssen Sie nur noch dieses Problem lösen. Seien Sie dankbar, dass dies Software ist und nicht, z. B. ein Flugzeugdesign, da Änderungen viel einfacher sind. Identifizieren Sie die Probleme, beheben Sie sie == refactor == Software-Engineering. Manchmal ist viel Arbeit damit verbunden ...
Wenn Sie Scrum verwenden, sollte diese Änderung natürlich von User Stories abhängen (was erhält der Benutzer von dieser Änderung?). Der Prozess würde von einer Geschichte ausgehen, die vom aktuellen Design nicht einfach berücksichtigt werden kann (oops), und es würde eine Diskussion mit dem Produktbesitzer darüber stattfinden, wie diese Geschichte aufgeschlüsselt werden kann. Durch diese Änderung wenden Sie weiterhin agile Prinzipien an.
Ein paar berühmte große Anforderungsänderungen aus der OS-Welt, die mir in den Sinn kommen:
Wie auch immer Sie diese betrachten, sie sind eine Menge Arbeit. Das ursprüngliche Design berücksichtigte mit ziemlicher Sicherheit nicht die Möglichkeit, dass dies geschah (dh Portaility war keine große Anforderung). Ob das Design OO war oder nicht, ist wahrscheinlich auch kein großer Faktor. Bei einem guten Design wären die plattformspezifischen Teile etwas isoliert und die Arbeit wäre einfacher.
quelle
Ich überarbeite meine Projekte dauerhaft und verwende auch UML-Klassendiagramme. Ich meine, ich erstelle ein oder mehrere Klassendiagramme nach Paketen. Jedes Diagramm wird im Stammverzeichnis des Pakets gespeichert. Jeder UML-Klassifizierer hat eine eigene ID, die der zugehörigen Java-ID zugeordnet ist. Dies bedeutet, dass mein Diagramm beim Öffnen automatisch auf die neuesten Code-Refactoring-Änderungen aktualisiert wird. Ich kann meine Klassendiagramme auch direkt auf grafischer Ebene ändern und mein gesamtes Projekt wird sofort überarbeitet. Es funktioniert ziemlich gut, aber es wird niemals den Menschen ersetzen. Mein UML-Klassendiagramm ist auch nur eine grafische Ansicht meines Codes. Es ist sehr wichtig, Code und Modell nicht wie bei EMF Eclipse zu mischen, da bei der Umgestaltung auch Modellinformationen verloren gehen. Ich verwende niemals den Model Driven Development Code Generator, da dies nutzlos ist. Ich nicht
Trotzdem ist es sehr hilfreich, über 100 Klassendiagramme zu haben, die alle Details meiner Projektstruktur darstellen und überall voller Notizen sind. Ich erstelle nur Klassendiagramme für Projekte, da Entwickler normalerweise keine Zeit haben, andere Diagramme zu lernen oder zu verwenden. Klassendiagramme sind auch so gut, weil sie automatisch aktualisiert werden. Klassendiagramme können nach dem Code erstellt werden, indem einfach ein Paket umgekehrt und Notizen hinzugefügt werden. Es ist schnell und immer genau und 100% iterativ.
Bitte verwechseln Sie nicht die modellgetriebene Entwicklung, bei der es sich um einen modellgenerierenden Code handelt, und verwenden Sie normalerweise UML als grafische Darstellung mit aus dem Code aktualisierten UML-Klassendiagrammen. Nur UML-synchronisierter Code hat bei mehreren Iterationen einen echten Wert für mich.
Es tut mir leid, dass wir so lange brauchen, aber ich denke, wir sollten UML-Klassendiagrammen eine zweite Chance geben, wenn sie nur als grafische Ansicht unseres Projekts verwendet werden. Dies bedeutet, dass UML das gesamte Projekt abdeckt und ein einziges Modell hat, das aus großen Klassendiagrammen besteht, die das gesamte Projekt darstellen. Es wäre lächerlich, Hunderte kleiner Ansichten und ein Modell für jede Ansicht innerhalb eines Projekts mit Hunderten von Ansichten zu haben :-)
quelle
Ich habe die Sackgasse meines Codes und des Codes anderer aufgrund eines schlechten Designs, einer Richtungsänderung usw. erreicht. Ich habe auch viele andere gesehen, die auf dieses Problem gestoßen sind. Der große Fehler (zumindest scheint es mir ein Fehler zu sein) ist der unmittelbare Wunsch, Arbeitscode wegzuwerfen und alles von Grund auf neu zu implementieren.
Ich ging jeden Fall auf die gleiche Weise an, was gut zu funktionieren schien:
Kosten:
Leistungen:
quelle
Vor ungefähr ein oder zwei Monaten blieb unser aktuelles Projekt aufgrund einiger schlechter Designentscheidungen (und des Mangels an viel Design an einem Ort) mit dem SCRUM-Entwicklungsstil etwas hängen.
Unsere Lösung (und was meiner Meinung nach die Standardlösung für SCRUM ist) bestand darin, einen ganzen Sprint (~ 2 Wochen) nur dem Refactoring zu widmen. Während dieser Zeit wurden keine neuen Funktionen hinzugefügt, aber wir konnten über die aktuelle Codebasis nachdenken und ein viel besseres System für das, was wir taten, entwerfen.
Wir haben diese Hürde nun überwunden und neue Funktionen hinzugefügt.
quelle
Der Schlüssel zur Begrenzung der Kosten für Designänderungen besteht darin, den Code so trocken wie möglich zu halten. Dadurch wird der größte Teil des Anwendungscodes auf ein sehr hohes Niveau gebracht, wobei der größte Teil des Codes direkt die Absicht ausdrückt und relativ wenig Mechanismen spezifiziert. Wenn Sie dies tun, haben Entwurfsentscheidungen den kleinstmöglichen Ausdruck im Code, und Entwurfsänderungen haben die geringstmöglichen Kosten.
quelle
Der Schlüssel zur Vermeidung von Design-Sackgassen besteht darin, so früh wie möglich zu erkennen, wann sich Ihr Design ändern muss, und es dann zu ändern. Die größten Probleme entstehen nicht dadurch, dass Sie Ihr Design ständig weiterentwickeln, sondern dass Sie sich weigern , Ihr Design weiterzuentwickeln, bis es ein großes Problem darstellt.
Beispielsweise verfügt Netflix über eine Profilfunktion, mit der verschiedene Familienmitglieder denselben Plan abrechnen können, jedoch separate Warteschlangen haben. Vor einigen Jahren kündigten sie an, dass sie diese Funktion abbrechen müssten, da nur etwa 10% ihrer Benutzer sie nutzten. Aufgrund der gehackten Implementierung wurden jedoch übermäßig viele Wartungsarbeiten durchgeführt. Nach einem Aufruhr haben sie die Kugel gebissen und eine teure Neugestaltung vorgenommen, um diese Kunden zu halten.
Ich bin sicher, dass es einige Ingenieure gab, die ein suboptimales Design erkannten, als sie diese Funktion zum ersten Mal hinzufügten. Wenn sie es damals geändert hätten, wäre es nicht annähernd so groß gewesen.
quelle
War es nicht Fred Brooks, der so etwas wie "Planen Sie, den ersten wegzuwerfen" sagte? Fühlen Sie sich nicht zu bedrückt, Sackgassen-Designs tauchen auch in Projekten auf, die versuchen, das gesamte Design auch im Voraus zu erledigen. Redesigns finden in allen Arten von Entwicklungen statt, sei es, weil es von Anfang an ein nicht praktikables Design war (die letzten 20%, die beschönigt werden - "der Teufel steckt im Detail") oder weil ein Kunde seinen Fokus ändert. Es gibt keine wirkliche Notwendigkeit für Alarmglocken, seien Sie nicht zu besorgt.
quelle