Ein Freund von mir arbeitet für eine kleine Firma an einem Projekt, das jeder Entwickler hassen würde: Er ist unter Druck gesetzt, so schnell wie möglich zu veröffentlichen, er ist der einzige, der sich anscheinend um technische Schulden kümmert, der Kunde hat keinen technischen Hintergrund usw.
Er erzählte mir eine Geschichte, die mich über die Angemessenheit von Designmustern in Projekten wie diesem nachdenken ließ. Hier ist die Geschichte.
Wir mussten Produkte an verschiedenen Stellen auf der Website anzeigen. Beispielsweise könnten Content Manager die Produkte, aber auch die Endbenutzer oder die Partner über die API anzeigen.
Manchmal fehlten Informationen in den Produkten: Beispielsweise hatten einige von ihnen keinen Preis, als das Produkt gerade erstellt wurde, aber der Preis war noch nicht festgelegt. Einige hatten keine Beschreibung (die Beschreibung ist ein komplexes Objekt mit Änderungsprotokollen, lokalisiertem Inhalt usw.). Einigen fehlten Versandinformationen.
Inspiriert von meinen jüngsten Lesungen über Entwurfsmuster, hielt ich dies für eine hervorragende Gelegenheit, das magische Null-Objekt-Muster zu verwenden . Also habe ich es geschafft und alles war glatt und sauber. Man musste nur anrufen
product.Price.ToString("c")
, um den Preis anzuzeigen oderproduct.Description.Current
die Beschreibung anzuzeigen ; Keine bedingten Dinge erforderlich. Bis der Stakeholder eines Tages bat, ihn in der API anders anzuzeigen, indem er einennull
in JSON hatte. Und auch anders für Content-Manager, indem "Preis nicht angegeben [Ändern]" angezeigt wird. Und ich musste mein geliebtes Null-Objekt-Muster ermorden, weil es nicht mehr nötig war.Auf die gleiche Weise musste ich ein paar abstrakte Fabriken und ein paar Erbauer entfernen. Schließlich ersetzte ich mein wunderschönes Fassadenmuster durch direkte und hässliche Aufrufe, da sich die zugrunde liegenden Schnittstellen drei Monate lang zweimal täglich änderten und sogar der Singleton mich verließ als die Anforderungen besagten, dass das betroffene Objekt je nach Kontext unterschiedlich sein musste.
Mehr als drei Wochen Arbeit bestanden darin, Designmuster hinzuzufügen und sie dann einen Monat später zu zerreißen, und mein Code wurde schließlich zu einer Spaghetti, die von niemandem, einschließlich mir, gepflegt werden konnte. Wäre es nicht besser, diese Muster überhaupt nicht zu verwenden?
In der Tat musste ich mich mit Projekten befassen, bei denen sich die Anforderungen ständig ändern und die von Personen vorgegeben werden, die den Zusammenhalt oder die Kohärenz des Produkts nicht wirklich berücksichtigen. In diesem Zusammenhang spielt es keine Rolle, wie agil Sie sind, Sie erhalten eine elegante Lösung für ein Problem, und wenn Sie diese schließlich implementieren, stellen Sie fest, dass sich die Anforderungen so drastisch geändert haben, dass Ihre elegante Lösung nicht mehr passt länger.
Was wäre die Lösung in diesem Fall?
Verwenden Sie keine Entwurfsmuster, hören Sie auf zu denken und schreiben Sie Code direkt?
Es wäre interessant, eine Erfahrung zu machen, bei der ein Team Code direkt schreibt, während ein anderes Team vor dem Tippen zweimal darüber nachdenkt und das Risiko eingeht, einige Tage später das ursprüngliche Design wegwerfen zu müssen: Wer weiß, vielleicht haben beide Teams das gleiche technische Schulden. Ohne solche Daten würde ich nur behaupten, dass es sich nicht richtig anfühlt , Code ohne vorherige Überlegung bei der Arbeit an einem 20-Mann-Monat-Projekt zu tippen.
Behalten Sie das Designmuster bei, das keinen Sinn mehr ergibt, und versuchen Sie, weitere Muster für die neu erstellte Situation hinzuzufügen?
Dies scheint auch nicht richtig. Muster werden verwendet, um das Verständnis des Codes zu vereinfachen. Wenn Sie zu viele Muster eingeben, wird der Code zu einem Chaos.
Überlegen Sie sich ein neues Design, das die neuen Anforderungen berücksichtigt, und überarbeiten Sie dann langsam das alte Design in das neue?
Als Theoretiker und derjenige, der Agile bevorzugt, bin ich total begeistert. In der Praxis, wenn Sie wissen, dass Sie jede Woche zum Whiteboard zurückkehren und den Großteil des vorherigen Designs wiederholen müssen und der Kunde einfach nicht genug Geld hat, um Sie dafür zu bezahlen, und auch nicht genug Zeit zum Warten Das wird wahrscheinlich nicht funktionieren.
Also irgendwelche Vorschläge?
quelle
Antworten:
Ich sehe einige falsche Annahmen in dieser Frage:
Designmuster sind kein Selbstzweck, sie sollten Ihnen dienen, nicht umgekehrt. Wenn ein Entwurfsmuster die Implementierung des Codes nicht einfacher oder zumindest besser entwickelbar macht ( dh einfacher an sich ändernde Anforderungen anzupassen ist), verfehlt das Muster seinen Zweck. Wenden Sie keine Muster an, wenn sie dem Team das "Leben" nicht erleichtern. Wenn das neue Null-Objektmuster Ihrem Freund für die Zeit diente, in der er es verwendete, war alles in Ordnung. Wenn es später beseitigt werden sollte, dann könnte dies auch in Ordnung sein. Wenn das Null-Objektmuster die (korrekte) Implementierung verlangsamt hat, war seine Verwendung falsch. Beachten Sie, dass aus diesem Teil der Geschichte noch keine Ursache für "Spaghetti-Code" abgeleitet werden kann.
Das ist weder sein Job noch seine Schuld! Ihre Aufgabe ist es, sich um Zusammenhalt und Kohärenz zu kümmern. Wenn sich die Anforderungen zweimal täglich ändern, sollte Ihre Lösung nicht darin bestehen, die Codequalität zu beeinträchtigen. Sagen Sie dem Kunden einfach, wie lange es dauert, und wenn Sie der Meinung sind, dass Sie mehr Zeit benötigen, um das Design "richtig" zu machen, fügen Sie jeder Schätzung einen ausreichend großen Sicherheitsspielraum hinzu. Verwenden Sie das "Scotty-Prinzip", besonders wenn ein Kunde versucht, Druck auf Sie auszuüben . Und wenn Sie sich mit einem nicht-technischen Kunden über den Aufwand streiten, vermeiden Sie Begriffe wie "Refactoring", "Unit-Tests", "Design Patterns" oder "Code-Dokumentation" - das sind Dinge, die er nicht versteht und die er wahrscheinlich für "unnötig" hält Unsinn ", weil er keinen Wert darin sieht. oder zumindest für den Kunden verständlich (Funktionen, Unterfunktionen, Verhaltensänderungen, Benutzerdokumente, Fehlerkorrekturen, Leistungsoptimierung usw.).
Wenn sich die zugrunde liegenden Schnittstellen drei Monate lang zweimal täglich ändern, sollte die Lösung nicht darin bestehen, den Code zweimal täglich zu ändern. Die eigentliche Lösung besteht darin, zu fragen, warum sich die Anforderungen so häufig ändern und ob es möglich ist, an diesem Teil des Prozesses Änderungen vorzunehmen. Vielleicht hilft noch eine Vorausanalyse. Möglicherweise ist die Schnittstelle zu breit, weil die Grenze zwischen den Komponenten falsch gewählt wurde. Manchmal ist es hilfreich, weitere Informationen darüber anzufordern, welcher Teil der Anforderungen stabil ist und welcher noch diskutiert wird (und tatsächlich die Implementierung für die diskutierten Dinge zu verschieben). Und manchmal müssen manche Leute einfach "in den Arsch getreten" werden, um nicht zweimal am Tag ihre Meinung zu ändern.
quelle
Meiner bescheidenen Meinung nach sollten Sie die Verwendung von Entwurfsmustern nicht vermeiden oder nicht vermeiden.
Entwurfsmuster sind einfach bekannte und vertrauenswürdige Lösungen für allgemeine Probleme, die mit Namen versehen wurden. Sie unterscheiden sich in technischer Hinsicht nicht von jeder anderen Lösung oder Konstruktion, die Sie sich vorstellen können.
Ich denke, die Wurzel des Problems könnte darin liegen, dass Ihr Freund überlegt, ein Entwurfsmuster anzuwenden oder nicht anzuwenden, anstatt darüber nachzudenken, was die beste Lösung ist, die ich mir vorstellen kann, einschließlich, aber nicht beschränkt auf die Muster Ich kenne".
Vielleicht führt dieser Ansatz dazu, dass er Muster auf teilweise künstliche oder erzwungene Weise an Orten verwendet, an denen sie nicht dazu gehören. Und das führt zu einem Durcheinander.
quelle
In Ihrem Beispiel für die Verwendung des Null-Objektmusters ist es meines Erachtens letztendlich gescheitert, weil es den Anforderungen des Programmierers und nicht den Anforderungen des Kunden entsprach. Der Kunde musste den Preis in einer dem Kontext entsprechenden Form anzeigen. Der Programmierer musste einen Teil des Anzeigecodes vereinfachen.
Wenn also ein Entwurfsmuster nicht den Anforderungen entspricht, sagen wir, dass alle Entwurfsmuster Zeitverschwendung sind, oder sagen wir, dass wir ein anderes Entwurfsmuster benötigen?
quelle
Es scheint, dass der Fehler eher darin bestand, die Musterobjekte zu entfernen, als sie zu verwenden. Im ursprünglichen Entwurf scheint das Null-Objekt eine Lösung für ein Problem geliefert zu haben. Dies war möglicherweise nicht die beste Lösung.
Wenn Sie die einzige Person sind, die an einem Projekt arbeitet, können Sie den gesamten Entwicklungsprozess miterleben. Der große Nachteil ist, dass Sie niemanden als Mentor haben. Es ist wahrscheinlich, dass sich die Zeit zum Erlernen und Anwenden der besten oder besseren Praktiken schnell auszahlt. Der Trick besteht darin, zu ermitteln, welche Übung wann gelernt werden muss.
Verkettung von Referenzen in der Form product.Price.toString ('c') verstößt gegen das Gesetz von Demeter . Ich habe alle möglichen Probleme mit dieser Praxis gesehen, von denen sich viele auf Nullen beziehen. Eine Methode wie product.displayPrice ('c') kann Nullpreise intern verarbeiten. Ebenso könnte product.Description.Current von product.displayDescription (), product.displayCurrentDescription () behandelt werden. oder product.diplay ('Current').
Der Umgang mit der neuen Anforderung an Manager und Inhaltsanbieter muss durch Reaktion auf den Kontext erfolgen. Es gibt eine Vielzahl von Ansätzen, die verwendet werden können. Die Factory-Methoden können abhängig von der Benutzerklasse, der sie angezeigt werden, unterschiedliche Produktklassen verwenden. Ein anderer Ansatz wäre, dass die Darstellungsmethoden der Produktklassen unterschiedliche Daten für unterschiedliche Benutzer erstellen.
Die gute Nachricht ist, dass Ihr Freund merkt, dass die Dinge außer Kontrolle geraten. Hoffentlich hat er den Code in der Versionskontrolle. Dies ermöglicht ihm, schlechte Entscheidungen, die er ausnahmslos treffen wird, zurückzudrängen. Ein Teil des Lernens besteht darin, verschiedene Ansätze auszuprobieren, von denen einige scheitern werden. Wenn er mit den nächsten Monaten fertig wird, könnte er Ansätze finden, die sein Leben vereinfachen und die Spaghetti aufräumen. Er könnte versuchen, jede Woche eine Sache zu reparieren.
quelle
Die Frage scheint in so vielen Punkten falsch zu sein. Aber die offensichtlichen sind:
Viele Leute haben richtig gesagt, Design Patterns handeln sehr stark vom Beschriften und Benennen einer gängigen Praxis. Denken Sie also an ein Hemd, ein Hemd hat einen Kragen, aus irgendeinem Grund entfernen Sie den Kragen oder einen Teil des Kragens. Die Benennung und Beschriftung ändert sich, aber es ist immer noch ein T-Shirt im Wesentlichen. Genau das ist hier der Fall, kleine Detailänderungen, die nicht bedeuten, dass Sie dieses Muster "ermordet" haben. (Nochmals die extreme Formulierung beachten)
Nach meiner Erfahrung müssen Sie bei geringen Anforderungen nur einen kleinen Teil der Codebasis ändern. Einige mögen ein bisschen hacky sein, aber nichts zu ernstes, um die Wartbarkeit oder Lesbarkeit wesentlich zu beeinträchtigen, und oft genügen ein paar Zeilen mit Kommentaren, um den hacky-Teil zu erklären. Dies ist auch eine sehr verbreitete Praxis.
quelle
Lassen Sie uns einen Moment innehalten und uns das grundlegende Problem hier ansehen - die Architektur eines Systems, bei dem das Architekturmodell zu stark an systemnahe Features gekoppelt ist, sodass die Architektur im Entwicklungsprozess häufig unterbrochen wird.
Ich denke, wir müssen uns daran erinnern, dass die Verwendung von Architektur- und Designmustern, die damit zusammenhängen, auf einer angemessenen Ebene verlegt werden muss und dass die Analyse der richtigen Ebene nicht trivial ist. Auf der einen Seite können Sie die Architektur Ihres Systems mit nur sehr grundlegenden Einschränkungen wie "MVC" oder ähnlichem leicht auf einem zu hohen Niveau halten, was dazu führen kann, dass Gelegenheiten wie klare Richtlinien und die Nutzung von Code verpasst werden und wo Spaghetti-Code leicht möglich ist gedeihen in all dem freien Raum.
Auf der anderen Seite könnten Sie Ihr System genauso gut überplanen, wie die Einschränkungen auf einer bis ins Detail gehenden Ebene festzulegen, wobei Sie davon ausgehen, dass Sie sich auf Einschränkungen verlassen können, die in der Realität volatiler sind als erwartet, und ständig Ihre Einschränkungen brechen und zwingt Sie, ständig umzugestalten und wieder aufzubauen, bis Sie zu verzweifeln beginnen.
Änderungen der Anforderungen an ein System werden immer in geringerem oder größerem Umfang vorhanden sein. Und die potenziellen Vorteile der Verwendung von Architektur- und Designmustern sind immer vorhanden, sodass es nicht wirklich darum geht, Designmuster zu verwenden oder nicht, sondern auf welcher Ebene Sie sie verwenden sollten.
Dies setzt voraus, dass Sie nicht nur die aktuellen Anforderungen des vorgeschlagenen Systems verstehen, sondern auch wissen, welche Aspekte davon als stabile Kerneigenschaften des Systems angesehen werden können und welche Eigenschaften sich möglicherweise im Laufe der Entwicklung ändern.
Wenn Sie feststellen, dass Sie ständig mit unorganisiertem Spaghetti-Code kämpfen müssen, tun Sie wahrscheinlich nicht genug Architektur oder auf einem zu hohen Niveau. Wenn Sie feststellen, dass Ihre Architektur häufig kaputt geht, arbeiten Sie wahrscheinlich mit einer zu detaillierten Architektur.
Die Verwendung von Architektur- und Designmustern ist nicht etwas, in das man ein System einfach "einkleiden" kann, als würde man einen Schreibtisch streichen. Hierbei handelt es sich um Techniken, die mit Bedacht angewendet werden sollten, und zwar auf einer Ebene, auf der die Abhängigkeiten, auf die Sie sich verlassen müssen, eine hohe Wahrscheinlichkeit haben, stabil zu sein, und auf der sich die Mühe lohnt, die Architektur zu modellieren und die tatsächlichen Abhängigkeiten / Architekturen / Muster zu implementieren als Code.
In Bezug auf das Problem einer zu detaillierten Architektur können Sie sich auch nur anstrengen, wenn die Architektur nicht viel wert ist. Siehe risikobasierte Architektur als Referenz. Ich mag dieses Buch. Gerade genug Softwarearchitektur , vielleicht auch.
Bearbeiten
Ich habe meine Antwort geklärt, da mir klar wurde, dass ich mich oft als "zu viel Architektur" ausdrückt, wobei ich wirklich "zu detaillierte Architektur" meinte, was nicht genau dasselbe ist. Eine zu detaillierte Architektur kann wahrscheinlich oft als "zu viel" Architektur angesehen werden, aber selbst wenn Sie die Architektur auf einem guten Niveau halten und das schönste System schaffen, das die Menschheit jemals gesehen hat, könnte dies zu viel Aufwand für die Architektur bedeuten, wenn die Prioritäten liegen auf Funktionen und Time-to-Market.
quelle
Ihr Freund scheint aufgrund seiner Anekdote mit zahlreichen Gegenwinden konfrontiert zu sein. Das ist bedauerlich und kann ein sehr schwieriges Umfeld für die Arbeit sein. Trotz der Schwierigkeit war er auf dem richtigen Weg, Muster zu verwenden, um sein Leben leichter zu machen, und es ist eine Schande, dass er diesen Weg verlassen hat. Der Spaghetti-Code ist das ultimative Ergebnis.
Da es zwei verschiedene Problembereiche gibt, technische und zwischenmenschliche, werde ich sie jeweils separat ansprechen.
Zwischenmenschlich
Der Kampf, den Ihr Freund hat, ist mit sich schnell ändernden Anforderungen verbunden und wie sich dies auf seine Fähigkeit auswirkt, wartbaren Code zu schreiben. Ich würde zunächst sagen, dass Anforderungen, die sich über einen so langen Zeitraum zweimal täglich ändern, ein größeres Problem darstellen und eine unrealistische implizite Erwartung haben. Die Anforderungen ändern sich schneller als sich der Code ändern kann. Wir können nicht erwarten, dass der Code oder der Programmierer mithalten. Dieses schnelle Änderungstempo ist symptomatisch für eine unvollständige Konzeption des gewünschten Produkts auf einer höheren Ebene. Das ist ein Problem. Wenn sie nicht wissen, was sie wirklich wollen, verschwenden sie viel Zeit und Geld, um es nie zu bekommen.
Es kann sinnvoll sein, Grenzen für Änderungen festzulegen. Gruppieren Sie Änderungen alle zwei Wochen zu Sets und frieren Sie sie dann für die zwei Wochen ein, während sie implementiert werden. Erstellen Sie eine neue Liste für die nächsten zwei Wochen. Ich habe das Gefühl, dass sich einige dieser Änderungen überschneiden oder widersprechen (z. B. zwischen zwei Optionen hin und her waffeln). Wenn Veränderungen schnell und heftig vor sich gehen, haben sie alle höchste Priorität. Wenn Sie sie zu einer Liste zusammenfassen, können Sie mit ihnen zusammenarbeiten, um das zu organisieren und zu priorisieren, was für die Maximierung des Aufwands und der Produktivität am wichtigsten ist. Sie sehen möglicherweise, dass einige ihrer Änderungen albern oder weniger wichtig sind und geben Ihrem Freund etwas Luft zum Atmen.
Diese Probleme sollten Sie jedoch nicht davon abhalten, guten Code zu schreiben. Schlechter Code führt zu schlimmeren Problemen. Es kann einige Zeit dauern, die Umgestaltung von einer Lösung zu einer anderen durchzuführen, aber genau die Tatsache, dass dies möglich ist Anspruch nehmen zeigt die Vorteile guter Codierungspraktiken anhand von Mustern und Prinzipien.
In einer Umgebung mit häufigen Änderungen, technische Schulden Wille fällig. Es ist weitaus besser, dafür Zahlungen zu leisten, als das Handtuch zu werfen und zu warten, bis es zu groß wird, um es zu überwinden. Wenn ein Muster nicht mehr nützlich ist, korrigieren Sie es, aber kehren Sie nicht zu den Cowboy-Codierungsmethoden zurück.
Technisch
Ihr Freund scheint ein gutes Verständnis für die grundlegenden Designmuster zu haben. Null-Objekt ist ein guter Ansatz für das Problem, mit dem er konfrontiert war. In Wahrheit ist es immer noch ein guter Ansatz. Wo er Herausforderungen zu haben scheint, ist das Verständnis der Prinzipien hinter den Mustern, das Warum von dem, was sie sind. Ansonsten glaube ich nicht, dass er seinen Ansatz aufgegeben hätte.
(Was folgt, ist eine Reihe von technischen Lösungen, die in der ursprünglichen Frage nicht gefragt wurden, die aber zeigen, wie wir uns zu Illustrationszwecken an Muster halten können.)
Das Prinzip hinter null Objekt ist die Idee, das zu verkapseln, was variiert . Wir verstecken, was sich ändert, damit wir nicht überall anders damit umgehen müssen. Hier kapselte das Nullobjekt die Varianz in der
product.Price
Instanz (ich werde es einPrice
Objekt nennen und ein Nullobjektpreis wird seinNullPrice
).Price
ist ein Domain-Objekt, ein Geschäftskonzept. Manchmal kennen wir in unserer Geschäftslogik den Preis noch nicht. Das passiert. Perfekter Anwendungsfall für das Null-Objekt.Price
s haben eineToString
Methode, die den Preis ausgibt, oder eine leere Zeichenfolge, wenn sie nicht bekannt ist (oderNullPrice#ToString
eine leere Zeichenfolge zurückgibt). Dies ist ein vernünftiges Verhalten. Dann ändern sich die Anforderungen.Wir müssen ein
null
an die API-Ansicht oder einen anderen String an die Manager-Ansicht ausgeben . Wie wirkt sich das auf unsere Geschäftslogik aus? Nun, das tut es nicht. In der obigen Aussage habe ich das Wort 'view' zweimal verwendet. Dieses Wort wurde wahrscheinlich nicht explizit gesprochen, aber wir müssen uns darin üben, die verborgenen Wörter in Anforderungen zu hören. Warum ist das Sehen so wichtig? Weil es uns sagt, wo der Wandel wirklich stattfinden muss : aus unserer Sicht.Abgesehen davon : Ob wir ein MVC-Framework verwenden oder nicht, spielt hier keine Rolle. Während MVC eine sehr spezifische Bedeutung für "Ansicht" hat, verwende ich es in der allgemeineren (und möglicherweise zutreffenderen) Bedeutung eines Teils des Präsentationscodes.
Wir müssen dies also wirklich in der Ansicht korrigieren. Wie könnten wir das machen? Der einfachste Weg, dies zu tun, wäre eine
if
Aussage. Ich weiß, das Null-Objekt sollte alle Wenns loswerden, aber wir müssen pragmatisch sein. Wir können die Zeichenfolge überprüfen, um festzustellen, ob sie leer ist, und wechseln:Wie wirkt sich das auf die Verkapselung aus? Der wichtigste Teil hier ist, dass die Ansichtslogik in der Ansicht gekapselt ist . Auf diese Weise können wir unsere Geschäftslogik / Domänenobjekte vollständig von Änderungen in der Sichtlogik isolieren. Es ist hässlich, aber es funktioniert. Dies ist jedoch nicht die einzige Option.
Wir könnten sagen, dass sich unsere Geschäftslogik dahingehend geändert hat, dass wir Standardzeichenfolgen ausgeben möchten, wenn kein Preis festgelegt ist. Wir können unsere
Price#ToString
Methode geringfügig anpassen (tatsächlich eine überladene Methode erstellen). Wir können einen Standard-Rückgabewert akzeptieren und diesen zurückgeben, wenn kein Preis festgelegt ist:Und jetzt wird unser Ansichtscode:
Die Bedingung ist weg. Wenn Sie dies jedoch zu oft tun, kann dies zu einer Zunahme von Sonderfallmethoden in Ihren Domänenobjekten führen. Dies ist daher nur dann sinnvoll, wenn dies nur in wenigen Fällen vorkommt.
Wir könnten stattdessen eine
IsSet
Methode erstellenPrice
, die einen Booleschen Wert zurückgibt:Logik anzeigen:
Wir sehen die Rückkehr der Bedingung in der Ansicht, aber die Geschäftslogik sagt mehr, wenn der Preis festgelegt ist. Wir können es
Price#IsSet
jetzt woanders verwenden, da wir es zur Verfügung haben.Schließlich können wir die Idee, einen Preis vollständig zu präsentieren, in einem Helfer für die Ansicht zusammenfassen. Dies würde die Bedingung verbergen, während das Domänenobjekt so weit erhalten bleibt, wie wir möchten:
Logik anzeigen:
Es gibt viele weiteren Möglichkeiten , um die Änderungen zu machen (wir verallgemeinern könnten
PriceStringHelper
in ein Objekt , dass die Renditen ein Standard , wenn ein String leer ist), aber diese sind ein paar schnell diejenigen , die (zum größten Teil) erhalten sowohl die Muster und die Prinzipien, wie sowie der pragmatische Aspekt einer solchen Änderung.quelle
Die Komplexität eines Entwurfsmusters kann Sie beißen, wenn das Problem, das es lösen sollte, plötzlich verschwindet. Leider wird dieses Risiko aufgrund der Begeisterung und Popularität von Designmustern nur selten explizit genannt. Die Anekdote Ihres Freundes hilft viel, um zu zeigen, wie sich Muster nicht auszahlen. Jeff Atwood hat einige gute Worte zum Thema.
Dokumentieren Sie Variationspunkte (sie sind Risiken) in Anforderungen
Viele der komplexeren Entwurfsmuster (Null-Objekt weniger) enthalten das Konzept geschützter Variationen , dh "Identifizieren von Punkten mit vorhergesagten Variationen oder Instabilitäten; Zuweisen von Verantwortlichkeiten zum Erstellen einer stabilen Schnittstelle um diese herum". Adapter, Besucher, Fassade, Ebenen, Beobachter, Strategie, Dekorateur usw. nutzen dieses Prinzip. Sie "zahlen sich aus", wenn die Software in der Dimension der erwarteten Variabilität erweitert werden muss und die "stabilen" Annahmen stabil bleiben.
Wenn Ihre Anforderungen so instabil sind, dass Ihre "vorhergesagten Abweichungen" immer falsch sind, verursachen die angewendeten Muster Schmerzen oder sind bestenfalls nicht benötigte Komplexität.
Craig Larman spricht von zwei Möglichkeiten, geschützte Variationen anzuwenden:
Beide sollten von Entwicklern dokumentiert werden, aber Sie sollten wahrscheinlich Kundenbindung für die Variationspunkte haben.
Um das Risiko zu managen, kann man sagen, dass jedes Entwurfsmuster, das PV anwendet, auf einen Variationspunkt in den vom Kunden festgelegten Anforderungen zurückgeführt werden sollte. Wenn ein Kunde einen Variationspunkt in den Anforderungen ändert, muss sich Ihr Design möglicherweise grundlegend ändern (weil Sie wahrscheinlich in Design [Muster] investiert haben, um diese Variation zu unterstützen). Keine Notwendigkeit, Zusammenhalt, Kopplung usw. zu erklären.
Zum Beispiel möchte Ihr Kunde, dass die Software mit drei verschiedenen Bestandsführungssystemen funktioniert. Das ist ein Variationspunkt, um den Sie herum entwerfen. Wenn der Kunde diese Anforderung nicht erfüllt, verfügen Sie natürlich über eine Reihe nutzloser Designinfrastrukturen. Der Kunde muss wissen, dass Variationspunkte etwas kosten.
CONSTANTS
im Quellcode sind eine einfache Form von PVEine andere Analogie zu Ihrer Frage wäre, zu fragen, ob die Verwendung
CONSTANTS
im Quellcode eine gute Idee ist. Mit Bezug auf dieses Beispiel , sagen wir mal der Kunde die Notwendigkeit Passwörter gelöscht. Daher würde dieMAX_PASSWORD_SIZE
konstante Verteilung in Ihrem Code unbrauchbar und sogar die Wartung und Lesbarkeit beeinträchtigen. Würden Sie die Verwendung vonCONSTANTS
als Grund dafür verantwortlich machen?quelle
Ich denke, es hängt zumindest teilweise von der Art Ihrer Situation ab.
Sie haben ständig wechselnde Anforderungen angesprochen. Wenn der Kunde sagt "Ich möchte, dass diese Imkereianwendung auch mit Wespen funktioniert", dann scheint dies die Art von Situation zu sein, in der sorgfältiges Design den Fortschritt unterstützen und nicht behindern würde (insbesondere, wenn Sie bedenken, dass sie dies in Zukunft tun möchte Halten Sie auch Fruchtfliegen.)
Auf der anderen Seite, wenn die Art der Änderung eher so aussieht wie "Ich möchte, dass diese Imkerei-Anwendung die Gehaltsabrechnung meines Waschsalon-Konglomerats verwaltet", werden Sie von keiner Codemenge aus Ihrem Loch herausgeholt.
Designmuster haben nichts von Natur aus Gutes. Sie sind Werkzeuge wie jedes andere - wir verwenden sie nur, um unsere Arbeit mittel- bis langfristig zu erleichtern. Wenn ein anderes Werkzeug (wie Kommunikation oder Recherche ) nützlicher ist, verwenden wir dieses.
quelle