it-swarm-eu.dev

Sollte die Lösung so allgemein wie möglich oder so spezifisch wie möglich sein?

Angenommen, ich habe eine Entität mit dem Attribut "Typ". Es könnte mehr als 20 mögliche Typen geben.

Jetzt werde ich gebeten, etwas zu implementieren, mit dem der Typ von A-> B geändert werden kann. Dies ist der einzige Anwendungsfall.

Sollte ich also etwas implementieren, das willkürliche Typänderungen zulässt, solange es sich um gültige Typen handelt? Oder sollte ich NUR zulassen, dass es gemäß der Anforderung von A-> B wechselt, und jede andere Typänderung wie B-> A oder A-> C ablehnen?

Ich kann die Vor- und Nachteile von beiden Seiten erkennen, wo eine generische Lösung weniger Arbeit bedeuten würde, falls in Zukunft eine ähnliche Anforderung auftaucht, aber es würde auch eine größere Wahrscheinlichkeit bedeuten, dass etwas schief geht (obwohl wir den Anrufer zu 100% kontrollieren Punkt).
Eine bestimmte Lösung ist weniger fehleranfällig, erfordert jedoch in Zukunft mehr Arbeit, wenn eine ähnliche Anforderung auftritt.

Ich höre immer wieder, dass ein guter Entwickler versuchen sollte, die Änderung zu antizipieren und das System so zu gestalten, dass es in Zukunft leicht zu erweitern ist. Was klingt nach einer generischen Lösung?

Edit :

Hinzufügen weiterer Details zu meinem nicht so spezifischen Beispiel: Die "generische" Lösung erfordert in diesem Fall weniger Arbeit als die "spezifische" Lösung, da die spezifische Lösung eine Validierung sowohl des alten als auch des neuen Typs erfordert, während die generische Lösung müssen nur den neuen Typ validieren.

127
LoveProgramming

Meine Faustregel:

  1. wenn Sie zum ersten Mal auf das Problem stoßen, lösen Sie nur das spezifische Problem (dies ist das YAGNI Prinzip).
  2. wenn Sie das zweite Mal auf dasselbe Problem stoßen, sollten Sie den ersten Fall verallgemeinern, wenn es nicht viel Arbeit ist
  3. sobald Sie drei spezielle Fälle haben, in denen Sie die generalisierte Version verwenden können, sollten Sie mit der Planung der generalisierten Version beginnen. Inzwischen sollten Sie das Problem gut genug verstehen, um es tatsächlich verallgemeinern zu können.

Dies ist natürlich eine Richtlinie und keine feste Regel: Die eigentliche Antwort besteht darin, von Fall zu Fall Ihr bestes Urteilsvermögen zu verwenden.

298
Daniel Pryden

Eine spezifische Lösung [...] erfordert in Zukunft mehr Arbeit, wenn ähnliche Anforderungen erforderlich sind

Ich habe dieses Argument mehrere Dutzend Mal gehört, und meiner Erfahrung nach stellt es sich regelmäßig als Trugschluss heraus. Wenn Sie jetzt oder später verallgemeinern, wenn die zweite ähnliche Anforderung auftritt, wird die Arbeit insgesamt fast gleich sein. Es macht also absolut keinen Sinn, zusätzlichen Aufwand in die Verallgemeinerung zu investieren, wenn Sie nicht wissen, dass sich dieser Aufwand jemals auszahlt.

(Dies gilt natürlich nicht, wenn eine allgemeinere Lösung weniger kompliziert ist und weniger Aufwand erfordert als eine bestimmte, aber meiner Erfahrung nach sind dies seltene Fälle. Eine solche Art von Szenario wurde später in die Frage eingearbeitet, und es ist nicht die Eine meiner Antworten ist ungefähr).

Wenn der "zweite ähnliche Fall" auftaucht, ist es Zeit, über Verallgemeinerungen nachzudenken. Es wird dann viel einfacher sein, korrekt zu verallgemeinern , da diese zweite Anforderung Ihnen ein Szenario bietet, in dem Sie überprüfen können, ob Sie die richtigen Dinge generisch gemacht haben. Wenn Sie versuchen, nur für einen Fall zu verallgemeinern, schießen Sie im Dunkeln. Die Chancen stehen gut, dass Sie bestimmte Dinge, die nicht verallgemeinert werden müssen, übergeneralisieren und andere Teile übersehen, die dies sollten. Und wenn dann ein zweiter Fall auftritt und Sie feststellen, dass Sie die falschen Dinge verallgemeinert haben, müssen Sie viel mehr Arbeit tun, um dies zu beheben.

Ich empfehle daher, jede Versuchung zu verzögern, Dinge "nur für den Fall" zu tun. Dieser Ansatz führt nur dann zu mehr Arbeits- und Wartungsaufwand, wenn Sie die Gelegenheit verpasst haben, drei, vier oder mehr Mal zu verallgemeinern, und dann einen Stapel ähnlich aussehenden (also doppelten) Codes warten müssen.

96
Doc Brown

TL; DR : es hängt davon ab, was Sie zu lösen versuchen.

Ich hatte ein ähnliches Gespräch mit meinen Gramps darüber, während wir darüber sprachen, wie Func und Action in C # großartig sind. My Gramps ist ein sehr alter Timer-Programmierer, bei dem es um Quellcodes geht, seit Software auf Computern ausgeführt wurde, die einen ganzen Raum beanspruchten.

Er hat mehrmals in seinem Leben die Technik gewechselt. Er schrieb Code in C, COBOL, Pascal, BASIC, Fortran, Smalltalk, Java und begann schließlich C # als Hobby. Ich lernte mit ihm zu programmieren und saß auf seinem Schoß, während ich aber war Ein Devling, der meine ersten Codezeilen im blauen Editor von IBMs SideKick wegschneidet. Als ich 20 Jahre alt war, hatte ich bereits mehr Zeit mit Codieren verbracht als mit Spielen im Freien.

Das sind ein bisschen meine Erinnerungen, also entschuldigen Sie mich, wenn ich beim Nacherzählen nicht gerade praktisch bin. Ich mag diese Momente etwas.

Das hat er zu mir gesagt:


"Sollten wir uns für die Verallgemeinerung eines Problems entscheiden oder es in dem spezifischen Umfang lösen, fragen Sie? Nun, das ist eine ... Frage."

Gramps machte eine Pause, um einen kurzen Moment darüber nachzudenken, während er die Position seiner Brille auf seinem Gesicht festlegte. Er spielte ein Match-3-Spiel auf seinem Computer, während er eine Deep Purple's LP auf seinem alten Soundsystem hörte.

"Nun, das würde davon abhängen, welches Problem Sie lösen wollen", sagte er mir. "Es ist verlockend zu glauben, dass es eine einzige, heilige Lösung für alle Designentscheidungen gibt, aber es gibt keine. Software-Architektur ist wie Käse, verstehen Sie?"

"... Käse, Gramps?"

"Egal, was Sie über Ihren Favoriten denken, es wird immer jemanden geben, der denkt, dass es stinkt".

Ich blinzelte einen Moment verwirrt, aber bevor ich etwas sagen konnte, ging Gramps weiter.

"Wenn Sie ein Auto bauen, wie wählen Sie das Material für ein Teil aus?"

"Ich ... ich denke, es hängt von den damit verbundenen Kosten ab und davon, was das Teil tun sollte, nehme ich an."

"Es hängt von dem Problem ab, das das Teil zu lösen versucht. Sie werden keinen Reifen aus Stahl oder eine Windschutzscheibe aus Leder herstellen. Sie wählen das Material aus, das das Problem, das Sie zur Hand haben, am besten löst. Nun, was ist ein Generische Lösung? Oder eine bestimmte? Zu welchem ​​Problem, zu welchem ​​Anwendungsfall? Sollten Sie einen voll funktionsfähigen Ansatz wählen, um einem Code, der nur einmal verwendet wird, maximale Flexibilität zu geben? Sollten Sie einen sehr speziellen, fragilen Code schreiben Ein Teil Ihres Systems, der viele Verwendungszwecke und möglicherweise viele Änderungen erfahren wird. Designentscheidungen wie diese entsprechen den Materialien, die Sie für ein Teil in einem Auto auswählen, oder der Form des Legosteins, den Sie für den Bau eines kleinen Hauses auswählen Welcher Legostein ist der beste? "

Der ältere Programmierer griff nach einem kleinen Lego-Zugmodell, das er auf seinem Tisch hat, bevor er fortfuhr.

"Sie können das nur beantworten, wenn Sie wissen , wofür Sie diesen Baustein benötigen. Wie zum Teufel wissen Sie, ob die spezifische Lösung besser ist als die generische eine oder umgekehrt, wenn Sie nicht einmal wissen, welches Problem Sie lösen möchten? Sie können nicht über eine Entscheidung hinaussehen, die Sie nicht verstehen. "

".. Hast du gerade The Matrix zitiert? "

"Was?"

"Nichts, mach weiter."

"Nun, nehmen wir an, Sie versuchen, etwas für das nationale Rechnungssystem zu erstellen. Sie wissen, wie diese höllische API und ihre XML-Datei mit dreißigtausend Zeilen von innen aussehen. Wie würde eine 'generische' Lösung zum Erstellen dieser Datei überhaupt aussehen? Die Datei ist voll von optionalen Parametern, voll von Fällen, die nur ganz bestimmte Geschäftszweige verwenden sollten. In den meisten Fällen können Sie sie ignorieren. Sie müssen kein generisches Rechnungssystem erstellen, wenn Sie das einzige sind. Ich werde immer Schuhe verkaufen. Erstellen Sie einfach ein System für den Verkauf von Schuhen und machen Sie es zum besten Schuhverkaufsrechnungssystem auf dem Markt. Wenn Sie nun ein Rechnungssystem für jeden Kundentyp erstellen müssten, für eine breitere Anwendung - Zum Beispiel als unabhängiges, generisches Verkaufssystem weiterverkauft zu werden - jetzt ist es interessant, die Optionen zu implementieren, die nur für Gas, Lebensmittel oder Alkohol verwendet werden. Jetzt das sind mögliche Anwendungsfälle. Vorher Es waren nur einige hypothetische Nicht verwenden Fälle, und Sie wollen nicht implementieren Nicht verwenden Fälle. Nicht benutzen ist der kleine Bruder von Nicht brauchen. "

Gramps setzte den Lego-Zug wieder an seinen Platz und wandte sich wieder seinem Match-3-Spiel zu.

"Um eine generische oder spezifische Lösung für ein bestimmtes Problem auswählen zu können, muss man zuerst verstehen, was zum Teufel dieses Problem ist. Ansonsten raten Sie nur, und raten ist die Aufgabe von Managern, nicht von Programmierern. Wie fast Alles in der IT kommt darauf an. "


Also, da hast du es. "Es hängt davon ab, ob". Das ist wahrscheinlich der mächtigste Zwei-Wort-Ausdruck, wenn man über Software-Design nachdenkt.

65
T. Sar

In erster Linie sollten Sie versuchen, vorauszusehen, ob eine solche Änderung wahrscheinlich ist - nicht nur eine entfernte Möglichkeit irgendwo auf der ganzen Linie.

Wenn nicht, ist es normalerweise besser, sich jetzt für die einfache Lösung zu entscheiden und sie später zu erweitern. Es ist durchaus möglich, dass Sie ein viel klareres Bild davon haben, was dann benötigt wird.

14
doubleYou

Wenn Sie in einer Domain arbeiten, die für Sie neu ist, sollte die von Daniel Pryden erwähnte Dreierregel definitiv angewendet werden. Wie sollen Sie nützliche Abstraktionen erstellen, wenn Sie ein Anfänger in diesem Bereich sind? Menschen sind oft selbstsicher in ihrer Fähigkeit, Abstraktionen zu fangen, obwohl dies selten der Fall ist. Nach meiner Erfahrung ist vorzeitige Abstraktion nicht weniger böse als Codeduplizierung. Falsche Abstraktionen sind wirklich schmerzhaft zu verstehen. Manchmal noch schmerzhafter zu refaktorisieren.

Es gibt ein Buch , das meinen Standpunkt zu einem unbekannten Bereich anspricht, in dem Entwickler arbeiten. Es besteht aus bestimmten Domänen mit extrahierten nützlichen Abstraktionen.

13
Zapadlo

Angesichts der Art des Hauptteils Ihrer Frage, vorausgesetzt ich habe ihn richtig verstanden, sehe ich dies tatsächlich als Entwurfsfrage für zentrale Systemmerkmale, mehr als als eine Frage zu generischen oder spezifischen Lösungen.

Und wenn es um zentrale Systemfunktionen und -funktionen geht, sind die zuverlässigsten diejenigen, die nicht vorhanden sind. Es lohnt sich, auf der Seite des Minimalismus zu irren, insbesondere wenn man bedenkt, dass es im Allgemeinen einfacher ist, Funktionen zentral hinzuzufügen, lange gewünscht, als problematische Funktionen zu entfernen, die lange unerwünscht waren und zahlreiche Abhängigkeiten aufweisen, da dies die Arbeit mit dem System so viel schwieriger gemacht hat als es sein muss, während mit jeder neuen Funktion endlose Designfragen aufgeworfen werden.

In der Tat würde ich versuchen, dies nicht als Typersatz von A nach B zu betrachten, wenn dies nicht möglich ist, da ich nicht genau vorhersehen kann, ob dies in Zukunft häufig benötigt wird, und stattdessen nur nach einer Möglichkeit suchen, den Zustand von A zu transformieren. Stellen Sie beispielsweise einige Felder in A so ein, dass sie sich verwandeln und dem Benutzer wie B erscheinen, ohne sich tatsächlich in einen anderen Typ zu verwandeln. Sie könnten A möglicherweise dazu bringen, B privat zu erstellen, indem Sie Kompositions- und Aufruffunktionen in B verwenden, wenn A den Status hat wird festgelegt, um anzugeben, dass B nachgeahmt werden soll, um die Implementierung nach Möglichkeit zu vereinfachen. Das sollte eine sehr einfache und minimal invasive Lösung sein.

Trotzdem würde ich, in Anlehnung an viele andere, vorschlagen, in diesem Fall generische Lösungen zu vermeiden, aber mehr noch, weil ich davon ausgehe, dass dies in Betracht gezogen wird, dem zentralen System eine sehr kühne Fähigkeit hinzuzufügen, und da würde ich Schlagen Sie vor, auf der Seite des Auslassens zu irren, besonders für den Moment.

4
user204677

Es ist schwierig, eine allgemeine Antwort auf dieses spezielle Problem zu geben ;-)

Je allgemeiner es ist, desto mehr Zeit gewinnen Sie für zukünftige Änderungen. Aus diesem Grund verwenden viele Spielprogramme beispielsweise das Entity Component Pattern , anstatt ein sehr ausgeklügeltes, aber starres Typsystem der Charaktere und Objekte im Spiel zu erstellen.

Auf der anderen Seite erfordert die Herstellung von etwas Generischem eine Vorabinvestition in Zeit und Aufwand in das Design, die viel höher ist als für etwas sehr Spezifisches. Dies birgt das Risiko einer Überentwicklung und sogar des Verlusts potenzieller zukünftiger Anforderungen.

Es lohnt sich immer zu sehen, ob es eine natürliche Verallgemeinerung gibt, die Ihnen einen Durchbruch bringt. Letztendlich ist es jedoch eine Frage des Gleichgewichts zwischen dem Aufwand, den Sie jetzt aufwenden können, und dem Aufwand, den Sie möglicherweise in Zukunft benötigen.

3
Christophe
  1. Hybrid. Dies muss keine Entweder-Oder-Frage sein. Sie können die API für allgemeine Typkonvertierungen entwerfen, während Sie nur die spezifische Konvertierung implementieren, die Sie gerade benötigen. (Stellen Sie einfach sicher, dass jemand, der Ihre allgemeine API mit einer nicht unterstützten Konvertierung aufruft, mit einem "nicht unterstützten" Fehlerstatus fehlschlägt.)

  2. Testen. Für die A-> B-Konvertierung muss ich einen (oder eine kleine Anzahl) Tests schreiben. Für eine generische x-> y-Konvertierung muss ich möglicherweise eine ganze Matrix von Tests schreiben. Das ist wesentlich mehr Arbeit, selbst wenn alle Konvertierungen eine einzige generische Implementierung gemeinsam haben.

    Wenn sich andererseits herausstellt, dass es eine generische Möglichkeit gibt, alle möglichen Conversions zu testen, gibt es nicht viel mehr Arbeit und ich bin möglicherweise geneigt, früher zu einer generischen Lösung zu gehen.

  3. Kupplung. Ein Konverter von A nach B muss möglicherweise die Implementierungsdetails zu A und B kennen (enge Kopplung). Wenn sich A und B noch weiterentwickeln, bedeutet dies, dass ich den Konverter (und seine Tests) möglicherweise immer wieder aufsuchen muss, was scheiße ist, aber zumindest auf A und B beschränkt ist.

    Wenn ich mich für eine generische Lösung entschieden hätte, die Zugriff auf die Details aller Typen benötigt, muss ich möglicherweise den generischen Konverter (und eine Reihe von Tests) weiter optimieren, auch wenn sich C und D weiterentwickeln, was mich verlangsamen kann - obwohl noch niemand in ein C oder ein D konvertieren muss.

    Wenn sowohl die generischen als auch die spezifischen Konvertierungen so implementiert werden können, dass sie nur lose mit den Details der Typen verknüpft sind, würde ich mir darüber keine Sorgen machen. Wenn eines davon lose gekoppelt erfolgen kann, das andere jedoch eine enge Kopplung erfordert, ist dies ein starkes Argument für den lose gekoppelten Ansatz direkt vor dem Tor.

3
Adrian McCarthy

Sollte die Lösung so allgemein wie möglich oder so spezifisch wie möglich sein?

Das ist keine beantwortbare Frage.

Das Beste, was Sie vernünftigerweise erhalten können, sind einige Heuristiken, um zu entscheiden, wie allgemein oder spezifisch eine bestimmte Lösung zu erstellen ist. Wenn Sie so etwas wie den folgenden Prozess durcharbeiten, ist normalerweise die Annäherung erster Ordnung korrekt (oder gut genug). Wenn dies nicht der Fall ist, ist der Grund wahrscheinlich zu domänenspezifisch, um hier ausführlich behandelt zu werden.

  1. Näherung erster Ordnung: die übliche YAGNI-Dreierregel, wie sie von Daniel Pryden, Doc Brown, et al. beschrieben wurde.

    Dies ist eine allgemein nützliche Heuristik, da es wahrscheinlich das Beste ist, was Sie tun können, dass nicht von der Domäne und anderen Variablen abhängt.

    Die anfängliche Vermutung lautet also: Wir machen das Spezifischste.

  2. Annäherung zweiter Ordnung: basierend auf Ihrem Expertenwissen über die Lösungsdomäne, sagen Sie

    Die "generische" Lösung erfordert in diesem Fall weniger Arbeit als die "spezifische" Lösung

    so könnten wir YAGNI neu interpretieren und empfehlen, unnötige Arbeit zu vermeiden , anstatt unnötige Allgemeinheit zu vermeiden. Wir könnten also unsere anfängliche Vermutung ändern und stattdessen die einfachste Sache machen.

    Wenn Ihre Kenntnisse in der Lösungsdomäne jedoch darauf hinweisen, dass die einfachste Lösung wahrscheinlich viele Fehler aufwirft oder schwer angemessen zu testen ist oder andere Probleme verursacht, ist eine einfachere Codierung nicht unbedingt ein Grund genug, unsere zu ändern ursprüngliche Wahl.

  3. Näherung dritter Ordnung: Schlägt Ihr Wissen über Problemdomäne vor, dass die einfachste Lösung tatsächlich korrekt ist, oder lassen Sie viele Übergänge zu, von denen Sie wissen, dass sie bedeutungslos oder falsch sind?

    Wenn die einfache, aber generische Lösung problematisch aussieht oder Sie nicht sicher sind, ob Sie diese Risiken beurteilen können, ist es wahrscheinlich besser, die zusätzliche Arbeit zu erledigen und bei Ihrer anfänglichen Vermutung zu bleiben.

  4. Annäherung vierter Ordnung: Verändert Ihr Wissen über das Kundenverhalten oder die Beziehung dieser Funktion zu anderen oder die Prioritäten des Projektmanagements oder ... andere nicht streng technische Überlegungen Ihre aktuelle Arbeitsentscheidung?

3
Useless

Dies ist keine einfache Frage, die mit einer einfachen Antwort zu beantworten ist. Viele Antworten haben Heuristiken gegeben, die auf einer Regel von 3 oder ähnlichem basieren. Es ist schwierig, über solche Faustregeln hinauszugehen.

Um Ihre Frage wirklich wirklich zu beantworten, müssen Sie berücksichtigen, dass Ihr Job höchstwahrscheinlich nichts implementiert, was A-> B ändert. Wenn Sie ein Auftragnehmer sind, ist dies möglicherweise die Voraussetzung, aber wenn Sie ein Mitarbeiter sind, wurden Sie beauftragt, viele, viele kleinere Aufgaben für das Unternehmen zu erledigen. Das Ändern von A-> B ist nur eine dieser Aufgaben. Ihr Unternehmen wird sich darum kümmern, wie gut die zukünftigen Änderungen auch vorgenommen werden können, auch wenn dies in der Anfrage nicht angegeben ist. Um "TheBestImplementation (tm)" zu finden, müssen Sie sich das Gesamtbild dessen ansehen, worum Sie wirklich gebeten werden, und dann die kleine Anforderung interpretieren, die Sie erhalten haben, um A-> B zu ändern.

Wenn Sie ein Programmierer mit niedrigem Einstiegsniveau sind, der gerade das College abgeschlossen hat, ist es oft ratsam, genau das zu tun, was Ihnen gesagt wurde. Wenn Sie als Softwarearchitekt mit 15 Jahren Erfahrung eingestellt wurden, ist es normalerweise ratsam, über große Dinge nachzudenken. Jeder eigentliche Job wird irgendwo zwischen "genau das tun, was die enge Aufgabe ist" und "über das große Ganze nachdenken" liegen. Sie werden herausfinden, wo Ihr Job in dieses Spektrum passt, wenn Sie genug mit Menschen sprechen und genug für sie arbeiten.

Ich kann einige konkrete Beispiele nennen, bei denen Ihre Frage eine endgültige Antwort auf der Grundlage des Kontexts hat. Stellen Sie sich den Fall vor, in dem Sie sicherheitskritische Software schreiben. Dies bedeutet, dass Sie ein Testteam haben, um sicherzustellen, dass das Produkt die versprochene Leistung erbringt. Einige dieser Testteams müssen jeden einzelnen möglichen Pfad durch den Code testen. Wenn Sie mit ihnen sprechen, stellen Sie möglicherweise fest, dass Sie, wenn Sie das Verhalten verallgemeinern, ihre Testkosten um 30.000 US-Dollar erhöhen, da sie alle diese zusätzlichen Pfade testen müssen. In diesem Fall nicht allgemeine Funktionalität hinzufügen, auch wenn Sie die Arbeit deswegen 7 oder 8 Mal duplizieren müssen. Sparen Sie dem Unternehmen Geld und tun Sie genau das, was in der Anfrage angegeben ist.

Stellen Sie sich andererseits vor, Sie erstellen eine API, mit der Kunden auf Daten in einem Datenbankprogramm zugreifen können, das Ihr Unternehmen erstellt. Ein Kunde fordert Änderungen A-> B an. APIs haben normalerweise einen Aspekt von goldenen Handschellen: Sobald Sie einer API Funktionen hinzufügen, sollten Sie diese Funktionen normalerweise nicht entfernen (bis zur nächsten Hauptversionsnummer). Viele Ihrer Kunden sind möglicherweise nicht bereit, die Kosten für das Upgrade auf die nächste Hauptversionsnummer zu bezahlen. Daher bleiben Sie möglicherweise lange Zeit bei der von Ihnen gewählten Lösung. In diesem Fall empfehle ich sehr, die generische Lösung von Anfang an zu erstellen. Sie möchten wirklich keine schlechte API mit einmaligen Verhaltensweisen entwickeln.

2
Cort Ammon

Eine Richtlinie, die ich vor einiger Zeit aufgestellt habe, lautet für mich: "Schreiben Sie für hypothetische Anforderungen nur hypothetischen Code." Das heißt, wenn Sie zusätzliche Anforderungen erwarten, sollten Sie ein wenig darüber nachdenken, wie Sie diese implementieren können, und Ihren aktuellen Code so strukturieren, dass er nicht auf diese Weise blockiert.

Aber schreiben Sie jetzt keinen tatsächlichen Code für diese - denken Sie nur ein wenig darüber nach, was Sie tun würden. Andernfalls machen Sie die Dinge normalerweise unnötig komplex und werden wahrscheinlich später verärgert sein, wenn tatsächliche Anforderungen auftreten, die von Ihren Erwartungen abweichen.

Vier Ihr Beispiel: Wenn Sie alle Verwendungszwecke der Konvertierungsmethode unter Ihrer Kontrolle haben, können Sie sie vorerst einfach convertAToB aufrufen und planen, eine Refactoring-Methode zum Umbenennen in der Methode IDE) umzubenennen Wenn Sie später allgemeinere Funktionen benötigen. Wenn die Konvertierungsmethode jedoch Teil einer öffentlichen API ist, kann dies ganz anders sein: Wenn Sie so spezifisch sind, wird die Generalisierung später blockiert, da es in diesem Fall schwierig ist, Dinge umzubenennen.

1

Hmm ... nicht viel Kontext für eine Antwort ... in Anlehnung an frühere Antworten: "Es kommt darauf an".

In gewissem Sinne müssen Sie auf Ihre Erfahrungen zurückgreifen. Wenn nicht deins, dann jemand älterer in der Domäne. Sie könnten darüber streiten, was die Akzeptanzkriterien besagen. Wenn es sich um etwas handelt, das im Sinne von "Der Benutzer sollte in der Lage sein, den Typ von" A "in" B "zu ändern" gegenüber "Der Benutzer sollte in der Lage sein, den Typ von seinem aktuellen Wert in einen zulässigen alternativen Wert zu ändern".

Häufig werden Akzeptanzkriterien interpretiert, aber gute QS-Mitarbeiter können Kriterien schreiben, die für die jeweilige Aufgabe geeignet sind, wodurch die erforderliche Interpretation minimiert wird.

Gibt es Domain-Einschränkungen, die keinen Wechsel von "A" zu "C" oder einer anderen Option erlauben, sondern nur "A" zu "B"? Oder ist dies nur eine eng spezifizierte Anforderung, die nicht "vorausschauend" ist?

Wenn der allgemeine Fall schwieriger wäre, würde ich vor Beginn der Arbeit nachfragen, aber wenn ich in Ihrem Fall vorhersagen könnte, dass in Zukunft andere Änderungsanforderungen vom Typ "Typ" kommen würden, wäre ich versucht: a) Schreiben Sie etwas, das für den allgemeinen Fall wiederverwendbar ist, und b) wickeln Sie es in eine Bedingung ein, die vorerst nur A -> B zulässt.

Einfach genug, um den aktuellen Fall in automatisierten Tests zu überprüfen, und einfach genug, um sich später anderen Optionen zu öffnen, wenn/wenn andere Anwendungsfälle auftreten.

1
railsdog

Ich höre immer wieder, dass ein guter Entwickler versuchen sollte, die Änderung zu antizipieren und das System so zu gestalten, dass es in Zukunft leicht zu erweitern ist.

Im Prinzip ja. Dies führt jedoch nicht notwendigerweise zu generischen Lösungen.

Für mich gibt es in der Softwareentwicklung zwei Arten von Themen, bei denen Sie mit zukünftigen Änderungen rechnen sollten:

  • Bibliotheken, die von Dritten verwendet werden sollen, und
  • gesamtsoftwarearchitektur.

Der erste Fall wird gelöst, indem Sie Ihre Kohäsion/Kopplung, Abhängigkeitsinjektion oder was auch immer beobachten. Der zweite Fall betrifft eine abstraktere Ebene, z. B. die Auswahl einer serviceorientierten Architektur anstelle eines großen monolotischen Codeblobs für eine große Anwendung.

In Ihrem Fall fragen Sie nach einer bestimmten Lösung für ein bestimmtes Problem, die keinerlei vorhersehbare Auswirkungen auf die Zukunft hat. In diesem Fall sind YAGNI und DRY gute Mottos zum Schießen:

  • YAGNI (du wirst es nicht brauchen) sagt dir, dass du das absolut minimale, grundlegende Zeug implementieren sollst, das du brauchst und verwendest im Moment. Dies bedeutet, dass Sie das Minimum implementieren, mit dem Ihre aktuelle Testsuite von rot nach grün wechselt, wenn Sie die Entwicklung im TDD/BDD/FDD-Stil verwenden sollten. Keine einzige Zeile mehr.
  • TROCKEN (wiederholen Sie sich nicht) bedeutet, dass Sie, wenn Sie erneut auf ein ähnliches Problem stoßen, dann genau prüfen, ob Sie eine generische Lösung benötigen.

In Kombination mit anderen modernen Methoden (wie einer guten Testabdeckung, um sicher umgestalten zu können) bedeutet dies, dass Sie schnell geschriebenen, schlanken, mittleren Code erhalten, der nach Bedarf wächst.

was nach einer generischen Lösung klingt, ist der richtige Weg?

Nein, es hört sich so an, als ob Sie Programmierumgebungen, Sprachen und Tools haben sollten, die es einfach und unterhaltsam machen, bei Bedarf eine Umgestaltung vorzunehmen. Generische Lösungen bieten das nicht. Sie entkoppeln die Anwendung von der eigentlichen Domain.

Schauen Sie sich moderne ORMs oder MVC-Frameworks an, zum Beispiel Ruby auf Rails; auf Anwendungsebene liegt der Schwerpunkt auf nicht generischen Arbeiten. Die Rails = Bibliotheken selbst sind offensichtlich fast 100% generisch, aber der Domain-Code (um den es in Ihrer Frage geht) sollte in dieser Hinsicht nur minimale Spielereien enthalten.

0
AnoE

Eine andere Art, über das Problem nachzudenken, besteht darin, zu überlegen, was Sinn macht.

Zum Beispiel gab es eine Anwendung, die ich entwickelte und die Abschnitte enthielt, die fast dasselbe taten, aber inkonsistente Berechtigungsregeln hatten. Da es keinen Grund gab, sie anders zu halten, ließ ich sie bei der Überarbeitung dieses Abschnitts alle Berechtigungen auf die gleiche Weise ausführen. Dadurch wurde der Gesamtcode kleiner, einfacher und die Benutzeroberfläche konsistenter.

Als das Management beschloss, anderen Personen Zugriff auf eine Funktion zu gewähren, konnten wir dies durch einfaches Ändern einer Flagge tun.

Offensichtlich ist es sinnvoll, die spezifische Typkonvertierung vorzunehmen. Ist es auch sinnvoll, zusätzliche Typkonvertierungen vorzunehmen?

Denken Sie daran, wenn die allgemeine Lösung schneller zu implementieren ist, ist auch der spezifische Fall einfach. Überprüfen Sie einfach, ob dies die einzige Typkonvertierung ist, die Sie zulassen.

Wenn sich die Anwendung in einem stark regulierten Bereich befindet (eine medizinische oder finanzielle Anwendung), versuchen Sie, mehr Personen in Ihr Design einzubeziehen.

0
Robert Baron