Ich arbeite an einem Projekt, das viele verschiedene, schrecklich komplexe Dinge in einem Rahmen tut, der leicht von anderen erweiterbar sein soll.
Zuerst waren die Klassen groß und machten mehrere Dinge. Um diese Verhaltensweisen zu ändern, mussten Sie diese Klassen erweitern. Die Methoden waren alle virtuell und änderten den Zustand des Objekts nicht, also war es ziemlich einfach, dies zu tun.
Aber als das System wuchs, wurde es klarer, dass das Framework mit einer Reihe von monolithischen Objekten enden würde, jedes mit langen Erbketten. Dies führte auch zu unerwarteten Abhängigkeiten - eine abstrakte Methode, die eine Sammlung von Klasse X zur Erzeugung des in einer Basisklasse definierten Objekts Y benötigte, diktierte, dass JEDER es tun musste, auch wenn es für die Hälfte des Vererbungsbaums keinen Sinn ergab. Dies führte auch zu massiven Klassen, die zig Unit-Tests erforderten, um eine Codeabdeckung von über 80% zu erreichen, und die Komplexität war so groß, dass Sie nicht sicher waren, ob Sie alles richtig abgedeckt haben. Es war offensichtlich, dass dieses Design den Rahmen sehr starr und unflexibel machen würde.
Also haben wir alles entlang SRP-Linien neu gestaltet. Sie haben Ihre Schnittstelle, eine Basisklasse und möglicherweise eine oder mehrere Implementierungsklassen. Jeder war zusammengesetzt von verschiedenen Objekten, die Schlüsselfunktionen des Gesamtprozesses durchgeführt. Wenn Sie einen Teil ändern wollten, überschreiben Sie eine Methode nicht, Sie würden ein anderes Objekt erzeugen, das die erforderliche Schnittstelle/Basisklasse erweitert und seinen Job anders ausgeführt hat. SRP wurde sogar in die Argumente und Rückgabewerte der Klassenmethoden aufgenommen. Für die Teile des Systems, die flexibel sein müssen, statt Sammlungen der X-Klasse zu übergeben, die zur Herstellung von Y-Objekten verwendet werden, wurde eine Klasse erstellt, um den Produktionsprozess von Y-Objekten einzukapseln. Komponenten im System würden dann diese Produzenten herumreichen, sie mit anderen kombinieren (die Verantwortung der Produzenten), und sie schließlich verwenden, um Y zu produzieren. Dies ließ zu, dass verschiedene Arten von Erzeugern geschaffen wurden, die alle genau behandelt werden konnten das gleiche, obwohl sie sehr unterschiedliche Dinge getan haben. Der Umzug hat auch die Codebasis jeder Klasse drastisch reduziert und sie VIEL einfacher zu testen gemacht.
Ich würde sagen, dass es als neuer Entwickler SEHR SCHWER ist, alles auf dieses Niveau herunter zu brechen. Sie müssen fast einen großen Schlammball schreiben, verstehen, wie es funktioniert, und es dann als verschiedene Komponenten neu gestalten, wobei jeder die Verantwortung für einen Teil des Ganzen übernimmt.
Ich denke, Sie sollten dies in ein Wiki verwandeln, da es keine eindeutige Antwort gibt. – Will
Ich bin mir nicht sicher, ob ich dem zustimme. Ich denke, sie sind mehr und weit weniger richtige Antworten. Und ich glaube, dass zu viele Leute glauben, dass dies viel subjektiver oder kontextsensitiver ist als es tatsächlich ist - weshalb ich die Frage teilweise gestellt habe. Danke für deinen Kommentar. – Thiru