Ich hatte vor kurzem eine Diskussion mit einem Freund über OOP in der Entwicklung von Videospielen.
Ich erklärte die Architektur eines meiner Spiele, das zur Überraschung meines Freundes viele kleine Klassen und mehrere Abstraktionsebenen enthielt. Ich argumentierte, dass dies das Ergebnis von mir war, dass ich mich darauf konzentrierte, alles einer einzigen Verantwortung zu unterwerfen und auch die Kopplung zwischen den Komponenten zu lösen.
Seine Sorge war, dass die große Anzahl von Klassen zu einem Alptraum für die Instandhaltung werden würde. Ich war der Meinung, dass dies genau das Gegenteil bewirken würde. Wir diskutierten dies für einige Jahrhunderte und waren uns schließlich einig, dass wir nicht einverstanden waren. Vielleicht gab es Fälle, in denen sich SOLID-Prinzipien und richtiger OOP nicht wirklich gut mischten.
Sogar der Wikipedia-Eintrag zu SOLID-Prinzipien besagt, dass es sich um Richtlinien handelt , die beim Schreiben von wartbarem Code helfen, und dass sie Teil einer Gesamtstrategie agiler und adaptiver Programmierung sind.
Meine Frage lautet also:
Gibt es Fälle in OOP, in denen sich einige oder alle SOLID-Prinzipien nicht dazu eignen, Code zu bereinigen?
Ich kann mir sofort vorstellen, dass das Liskov-Substitutionsprinzip möglicherweise einem anderen Aspekt der sicheren Vererbung widerspricht. Das heißt, wenn jemand ein anderes nützliches Muster entwickelt, das durch Vererbung implementiert wird, ist es durchaus möglich, dass der LSP in direktem Konflikt damit steht.
Gibt es noch andere Vielleicht funktionieren bestimmte Arten von Projekten oder bestimmte Zielplattformen besser mit einem weniger SOLID-Ansatz?
Bearbeiten:
Ich möchte nur spezifizieren, dass ich nicht frage, wie ich meinen Code verbessern kann;) Der einzige Grund, warum ich ein Projekt in dieser Frage erwähnte, war, einen kleinen Kontext anzugeben. Meine Frage bezieht sich auf OOP und Designprinzipien im Allgemeinen .
Wenn Sie neugierig auf mein Projekt sind, sehen Sie sich das an .
Bearbeiten 2:
Ich stellte mir vor, dass diese Frage auf drei Arten beantwortet werden könnte:
- Ja, es gibt OOP-Konstruktionsprinzipien, die teilweise im Widerspruch zu SOLID stehen
- Ja, es gibt OOP-Designprinzipien, die SOLID vollständig widersprechen
- Nein, SOLID ist die Knie der Biene und OOP wird für immer besser damit sein. Aber wie bei allem ist es kein Allheilmittel. Verantwortungsvoll trinken.
Die Optionen 1 und 2 hätten wahrscheinlich lange und interessante Antworten geliefert. Option 3 hingegen wäre eine kurze, uninteressante, aber insgesamt beruhigende Antwort.
Wir scheinen uns Option 3 anzunähern.
quelle
Antworten:
Im Allgemeinen nicht. Die Geschichte hat gezeigt, dass die SOLID-Prinzipien in hohem Maße zu einer stärkeren Entkopplung beitragen, was sich wiederum in einer höheren Flexibilität des Codes und damit in der Fähigkeit niederschlägt, Änderungen Rechnung zu tragen und das Überlegen, Testen und Wiederverwenden des Codes zu erleichtern. Kurz gesagt, machen Sie Ihren Code sauberer.
Jetzt kann es Fälle geben, in denen die SOLID-Prinzipien mit DRY (wiederholen Sie sich nicht), KISS (halten Sie es einfach dumm) oder anderen Prinzipien eines guten OO-Designs kollidieren. Und natürlich können sie mit der Realität der Anforderungen, den Einschränkungen des Menschen, den Einschränkungen unserer Programmiersprachen und anderen Hindernissen kollidieren.
Kurz gesagt, SOLID-Prinzipien eignen sich immer zur Bereinigung von Code, aber in einigen Szenarien eignen sie sich weniger als widersprüchliche Alternativen. Sie sind immer gut, aber manchmal sind andere Dinge besser .
quelle
Count
undasImmutable
und Eigenschaften wiegetAbilities
[deren Rückgabe anzeigen würde, ob Dinge wieCount
"effizient" sein werden] enthält, dann könnte man eine statische Methode haben, die mehrere Sequenzen nimmt und sie so aggregiert, dass sie verhält sich wie eine einzelne längere Sequenz. Wenn solche Fähigkeiten im grundlegenden Sequenztyp vorhanden sind, auch wenn sie nur mit StandardimplementierungenIch denke, ich habe eine ungewöhnliche Perspektive, da ich sowohl im Finanzbereich als auch im Spielebereich gearbeitet habe.
Viele der Programmierer, die ich in Spielen getroffen habe, waren schrecklich im Software Engineering - aber sie brauchten keine Praktiken wie SOLID. Traditionell packen sie ihr Spiel in eine Schachtel - dann sind sie fertig.
Ich habe festgestellt, dass Entwickler im Finanzbereich sehr schlampig und undiszipliniert sein können, da sie nicht die Leistung benötigen, die Sie in Spielen leisten.
Beide obigen Aussagen sind natürlich Über-Verallgemeinerungen, aber tatsächlich ist sauberer Code in beiden Fällen kritisch. Für die Optimierung ist klarer und leicht verständlicher Code unerlässlich. Aus Gründen der Wartungsfreundlichkeit möchten Sie dasselbe.
Das heißt nicht, dass SOLID nicht ohne Kritik ist. Sie heißen Prinzipien und sollen dennoch wie Richtlinien befolgt werden? Also, wann genau soll ich ihnen folgen? Wann sollte ich die Regeln brechen?
Sie könnten sich wahrscheinlich zwei Code-Teile ansehen und sagen, welcher am besten zu SOLID passt. Für sich allein gibt es jedoch keine objektive Möglichkeit, Code in SOLID umzuwandeln. Es geht definitiv um die Interpretation des Entwicklers.
Es ist keine Selbstverständlichkeit zu sagen, dass "eine große Anzahl von Klassen zu einem Alptraum der Instandhaltung führen kann". Wenn die SRP jedoch nicht richtig interpretiert wird, kann dieses Problem leicht auftreten.
Ich habe Code mit vielen Schichten von so ziemlich keiner Verantwortung gesehen. Klassen, die nichts anderes tun, als den Status von einer Klasse zur anderen zu übergeben. Das klassische Problem zu vieler Indirektionsebenen.
Wenn SRP missbraucht wird, kann dies zu einem Mangel an Kohäsion in Ihrem Code führen. Sie können dies feststellen, wenn Sie versuchen, eine Funktion hinzuzufügen. Wenn Sie immer mehrere Stellen gleichzeitig ändern müssen, fehlt Ihrem Code die Kohäsion.
Open-Closed ist nicht ohne Kritiker. Siehe beispielsweise Jon Skeets Überprüfung des Open Closed-Prinzips . Ich werde seine Argumente hier nicht wiedergeben.
Ihre Argumentation zu LSP scheint eher hypothetisch und ich verstehe nicht wirklich, was Sie mit einer anderen Form der sicheren Vererbung meinen?
ISP scheint SRP etwas zu duplizieren. Sicherlich müssen sie so interpretiert werden, wie Sie niemals vorhersagen können, was alle Clients Ihrer Schnittstelle tun werden. Die zusammenhängende Schnittstelle von heute ist der ISP-Verstoß von morgen. Die einzige unlogische Schlussfolgerung ist, dass nicht mehr als ein Mitglied pro Schnittstelle vorhanden ist.
DIP kann zu unbrauchbarem Code führen. Ich habe Klassen mit einer großen Anzahl von Parametern im Namen von DIP gesehen. Diese Klassen hätten normalerweise ihre zusammengesetzten Teile "neu" geschrieben, aber ich, der Name der Testfähigkeit, wir dürfen das neue Schlüsselwort nie wieder verwenden.
SOLID allein reicht nicht aus, um sauberen Code zu schreiben. Ich habe Robert C. Martins Buch " Clean Code: Ein Handbuch für agiles Software-Handwerk " gesehen. Das größte Problem dabei ist, dass es einfach ist, dieses Buch zu lesen und als Regeln zu interpretieren. Wenn Sie das tun, verpassen Sie den Punkt. Es enthält eine große Liste von Gerüchen, Heuristiken und Prinzipien - viel mehr als nur die fünf von SOLID. Alle diese "Prinzipien" sind keine wirklichen Prinzipien, sondern Richtlinien. Onkel Bob beschreibt sie selbst als "Cubby Holes" für Konzepte. Sie sind ein Balanceakt; Wenn Sie eine Richtlinie blind befolgen, treten Probleme auf.
quelle
Hier ist meine Meinung:
Obwohl SOLID-Prinzipien auf eine nicht redundante und flexible Codebasis abzielen, kann dies zu einem Kompromiss bei der Lesbarkeit und Wartung führen, wenn zu viele Klassen und Ebenen vorhanden sind.
Es geht vor allem um die Anzahl der Abstraktionen . Eine große Anzahl von Klassen ist möglicherweise in Ordnung, wenn sie auf wenigen Abstraktionen basieren. Da wir die Größe und die Einzelheiten Ihres Projekts nicht kennen, ist es schwer zu sagen, aber es ist etwas beunruhigend, dass Sie neben einer großen Anzahl von Klassen auch mehrere Ebenen erwähnen .
Ich denke, SOLID-Prinzipien stimmen nicht mit OOP überein, aber es ist immer noch möglich, nicht sauberen Code zu schreiben, der daran festhält.
quelle
In meinen frühen Entwicklungsjahren begann ich, ein Roguelike in C ++ zu schreiben. Da ich die gute objektorientierte Methodik anwenden wollte, die ich aus meiner Ausbildung gelernt hatte, sah ich die Spielelemente sofort als C ++ - Objekte.
Potion
,Swords
,Food
,Axe
,Javelins
Usw. alle von einem grundlegenden Kern abgeleitetenItem
Code, Handhabung Namen, Symbol, Gewicht, solche Sachen.Dann programmierte ich die Taschenlogik und sah mich einem Problem gegenüber. Ich kann
Items
in die Tasche stecken, aber wenn ich eine auswähle, woher weiß ich dann, ob es einePotion
oder eine istSword
? Ich habe im Internet nachgeschlagen, wie man Gegenstände ablehnt. Ich habe die Compiler-Optionen gehackt, um Laufzeitinformationen zu aktivieren, damit ich weiß, was meine abstrahiertenItem
wahren Typen sind, und die Logik für Typen umgeschaltet, um zu wissen, welche Operationen ich zulassen würde (z. B. das Trinken vermeidenSwords
undPotions
auf meine Füße setzen).Es drehte den Code im Wesentlichen in eine große Kugel aus halb kopypastiertem Schlamm. Als das Projekt weiterging, begann ich zu verstehen, was der Designfehler war. Was passiert ist, ist, dass ich versucht habe, Klassen zu verwenden, um Werte darzustellen. Meine Klassenhierarchie war keine aussagekräftige Abstraktion. Was ich getan haben sollte macht
Item
eine Reihe von Funktionen zu implementieren, wieEquip ()
,Apply ()
undThrow ()
, und jede verhalten auf Werte basieren. Verwenden von Aufzählungen, um Ausrüstungsslots darzustellen. Verwenden von Aufzählungen, um verschiedene Waffentypen darzustellen. Verwenden Sie mehr Werte und weniger Klassifizierung, da meine Unterklassifizierung keinen anderen Zweck hatte, als diese endgültigen Werte zu füllen.Da Sie der Objektmultiplikation unter einer Abstraktionsebene gegenüberstehen, denke ich, dass meine Einsicht hier wertvoll sein kann. Wenn Sie anscheinend zu viele Objekttypen haben, kann es sein, dass Sie die zu verwendenden Typen mit den zu verwendenden Werten verwechseln.
quelle
Ich bin absolut auf der Seite Ihres Freundes, aber es könnte eine Frage unserer Bereiche und der Art der Probleme und Entwürfe sein, die wir angehen, und insbesondere, welche Arten von Dingen in Zukunft wahrscheinlich Änderungen erfordern. Unterschiedliche Probleme, unterschiedliche Lösungen. Ich glaube nicht an richtig oder falsch, sondern nur an Programmierer, die versuchen, den bestmöglichen Weg zu finden, um ihre speziellen Designprobleme am besten zu lösen. Ich arbeite in VFX, was nicht allzu unähnlich zu Game Engines ist.
Aber das Problem, mit dem ich in einer SOLID-konformen Architektur zu kämpfen hatte (sie war COM-basiert), konnte grob auf "zu viele Klassen" oder "zu viele Funktionen" als "reduziert" werden Ihr Freund könnte beschreiben. Ich würde speziell sagen: "Zu viele Interaktionen, zu viele Orte, die sich möglicherweise schlecht verhalten könnten, zu viele Orte, die möglicherweise Nebenwirkungen hervorrufen könnten, zu viele Orte, die möglicherweise geändert werden müssen, und zu viele Orte, die möglicherweise nicht das tun, was wir glauben, dass sie tun . "
Wir hatten eine Handvoll abstrakter (und reiner) Schnittstellen, die von einer Schiffsladung von Subtypen implementiert wurden (in diesem Diagramm im Zusammenhang mit den Vorteilen von ECS wurde der Kommentar unten links ignoriert):
Wo eine Bewegungsschnittstelle oder eine Szenenknotenschnittstelle von Hunderten von Untertypen implementiert werden kann: Lichter, Kameras, Netze, Physiklöser, Shader, Texturen, Knochen, primitive Formen, Kurven usw. usw. (und es gab oft mehrere Typen von jedem ). Und das ultimative Problem war wirklich, dass diese Designs nicht so stabil waren. Wir hatten wechselnde Anforderungen und manchmal mussten sich die Schnittstellen selbst ändern. Wenn Sie eine abstrakte Schnittstelle ändern möchten, die von 200 Subtypen implementiert wird, ist dies eine äußerst kostspielige Änderung. Wir begannen, dies zu mildern, indem wir abstrakte Basisklassen verwendeten, die die Kosten für solche Konstruktionsänderungen reduzierten, aber dennoch teuer waren.
Als Alternative habe ich mich mit der Entity-Component-Systemarchitektur befasst, die in der Spielebranche eher verbreitet ist. Das hat alles so verändert:
Und wow! Das war so ein Unterschied in Bezug auf die Wartbarkeit. Die Abhängigkeiten flossen nicht mehr zu Abstraktionen , sondern zu Daten (Komponenten). Und zumindest in meinem Fall waren die Daten trotz der sich ändernden Anforderungen viel stabiler und einfacher zu erstellen (obwohl sich das, was wir mit denselben Daten tun können, bei sich ändernden Anforderungen ständig ändert).
Auch weil die Entitäten in einem ECS Komposition anstelle von Vererbung verwenden, müssen sie eigentlich keine Funktionalität enthalten. Sie sind nur der analoge "Container der Komponenten". Das machte es so die analogical 200 Subtypen , die eine Bewegung umgesetzt Schnittstelle wiederum in 200 Entity - Instanzen (nicht getrennte Typen mit separatem Code) , die einfach eine Bewegung speichern Komponente (was nichts anderes ist als Daten mit Bewegung verbunden). A
PointLight
ist keine separate Klasse / Subtyp mehr. Es ist überhaupt keine Klasse. Es ist eine Instanz einer Entität, die nur einige Komponenten (Daten) kombiniert, die sich auf die Position im Raum (Bewegung) und die spezifischen Eigenschaften von Punktlichtern beziehen. Die einzige Funktionalität, die mit ihnen verbunden ist, befindet sich in den Systemen wie demRenderSystem
, der nach Lichtkomponenten in der Szene sucht, um zu bestimmen, wie die Szene gerendert werden soll.Da sich die Anforderungen im Rahmen des ECS-Ansatzes änderten, mussten häufig nur ein oder zwei Systeme geändert werden, die mit diesen Daten arbeiten, oder es musste nur ein neues System an der Seite eingeführt oder eine neue Komponente eingeführt werden, wenn neue Daten benötigt wurden.
Zumindest für meine Domain, und ich bin mir fast sicher, dass dies nicht für alle gilt, hat dies die Dinge so viel einfacher gemacht, da die Abhängigkeiten in Richtung Stabilität flossen (Dinge, die sich überhaupt nicht oft ändern mussten). Dies war in der COM-Architektur nicht der Fall, als die Abhängigkeiten einheitlich zu Abstraktionen flossen. In meinem Fall ist es viel einfacher, herauszufinden, welche Daten für die Bewegung im Voraus erforderlich sind, als alle möglichen Dinge, die Sie damit tun können, was sich im Laufe der Monate oder Jahre häufig ein wenig ändert, wenn neue Anforderungen eingehen.
Gut, sauberer Code kann ich nicht sagen, da manche Leute sauberen Code mit SOLID gleichsetzen, aber es gibt definitiv einige Fälle, in denen die Trennung von Daten von der Funktionalität wie beim ECS und die Umleitung von Abhängigkeiten von Abstraktionen zu Daten die Dinge auf jeden Fall viel einfacher machen können Ändern Sie aus offensichtlichen Kopplungsgründen, wenn die Daten viel stabiler sind als die Abstraktionen. Natürlich können Abhängigkeiten von Daten die Pflege von Invarianten erschweren, aber ECS tendiert dazu, dies durch die Systemorganisation auf ein Minimum zu reduzieren, wodurch die Anzahl der Systeme, die auf einen bestimmten Komponententyp zugreifen, minimiert wird.
Abhängigkeiten müssen nicht unbedingt in Richtung Abstraktionen fließen, wie DIP nahelegt. Abhängigkeiten sollten sich auf Dinge auswirken, bei denen es sehr unwahrscheinlich ist, dass sie künftig geändert werden müssen. Das kann in allen Fällen Abstraktionen sein oder nicht (es war sicherlich nicht in meinem Fall).
Ich bin mir nicht sicher, ob ECS wirklich ein Geschmack von OOP ist. Einige Leute definieren es so, aber ich sehe es als sehr unterschiedlich in den Kopplungseigenschaften und der Trennung von Daten (Komponenten) von Funktionalität (Systemen) und der fehlenden Datenkapselung. Wenn es als eine Form von OOP betrachtet wird, würde ich denken, dass es sehr im Widerspruch zu SOLID steht (zumindest die strengsten Vorstellungen von SRP, Open / Closed, Liskov-Substitution und DIP). Ich hoffe jedoch, dass dies ein vernünftiges Beispiel für einen Fall und ein Gebiet ist, in dem die grundlegendsten Aspekte von SOLID, zumindest wenn die Leute sie allgemein in einem besser erkennbaren OOP-Kontext interpretieren würden, möglicherweise nicht so zutreffend sind.
Teeny Klassen
Das ECS hat meine Ansichten stark in Frage gestellt und verändert. Wie Sie dachte ich früher, dass die Idee der Wartbarkeit die einfachste Implementierung für Dinge ist, die möglich ist, was viele Dinge und darüber hinaus viele voneinander abhängige Dinge impliziert (auch wenn die Abhängigkeiten zwischen Abstraktionen bestehen). Es ist am sinnvollsten, wenn Sie nur auf eine Klasse oder Funktion zoomen, um die einfachste Implementierung zu sehen, und wenn wir keine sehen, überarbeiten Sie sie und zerlegen Sie sie möglicherweise sogar weiter. Es kann jedoch leicht vorkommen, dass Sie übersehen, was mit der Außenwelt passiert, da jedes Mal, wenn Sie etwas relativ Komplexes in zwei oder mehr Dinge aufteilen, diese zwei oder mehr Dinge in einigen Fällen unweigerlich miteinander interagieren müssen (siehe unten) Weise oder etwas außerhalb muss mit allen von ihnen interagieren.
Heutzutage finde ich, dass es einen Spagat zwischen der Einfachheit von etwas und wie vielen Dingen gibt und wie viel Interaktion erforderlich ist. Die Systeme in einem ECS sind in der Regel ziemlich umfangreich, da nicht-triviale Implementierungen die Daten wie
PhysicsSystem
oderRenderSystem
oder verarbeitenGuiLayoutSystem
. Die Tatsache, dass ein komplexes Produkt so wenige von ihnen benötigt, erleichtert es jedoch, einen Schritt zurückzutreten und über das Gesamtverhalten der gesamten Codebasis nachzudenken. Da ist etwas dran, was darauf hindeuten könnte, dass es keine schlechte Idee ist, sich auf die Seite weniger massigerer Klassen zu stellen (die immer noch eine wohl singuläre Verantwortung tragen), wenn dies bedeutet, dass weniger Klassen gepflegt und begründet werden müssen und weniger Interaktionen stattfinden das System.Wechselwirkungen
Ich sage eher "Interaktionen" als "Kopplung" (obwohl das Reduzieren von Interaktionen das Reduzieren von beiden impliziert), da Sie Abstraktionen verwenden können, um zwei konkrete Objekte zu entkoppeln, aber sie immer noch miteinander sprechen. Sie könnten im Verlauf dieser indirekten Kommunikation immer noch Nebenwirkungen verursachen. Und oft stelle ich fest, dass meine Fähigkeit, über die Korrektheit eines Systems nachzudenken, eher mit diesen "Wechselwirkungen" als mit "Kopplung" zusammenhängt. Das Minimieren von Interaktionen erleichtert es mir, alles aus der Vogelperspektive zu betrachten. Das heißt, Dinge, die überhaupt nicht miteinander sprechen, und in diesem Sinne tendiert ECS auch dazu, "Interaktionen" wirklich zu minimieren und nicht nur auf das Nötigste zu koppeln (zumindest habe ich keine Ahnung).
Das könnte zumindest teilweise an mir und meinen persönlichen Schwächen liegen. Ich habe das größte Hindernis für mich gefunden, Systeme von enormer Größe zu erstellen, und immer noch selbstbewusst darüber nachzudenken, durch sie zu navigieren und das Gefühl zu haben, dass ich potenzielle gewünschte Änderungen auf vorhersehbare Weise überall vornehmen kann Nebenwirkungen. Es ist das größte Hindernis, das auftaucht, wenn ich von Zehntausenden von LOC zu Hunderttausenden von LOC zu Millionen von LOC wechsle, selbst für Code, den ich komplett selbst geschrieben habe. Wenn mich etwas vor allem zu einem Crawl verlangsamt, kann ich in diesem Sinne nicht mehr nachvollziehen, was in Bezug auf Anwendungsstatus, Daten und Nebenwirkungen vor sich geht. Es' Es ist nicht die Roboterzeit, die für eine Änderung erforderlich ist, die mich so sehr bremst, sondern die Unfähigkeit, die vollständigen Auswirkungen der Änderung zu verstehen, wenn das System über die Fähigkeit meines Verstandes hinauswächst, darüber nachzudenken. Und die Reduzierung der Interaktionen war für mich die effektivste Möglichkeit, das Produkt mit viel mehr Funktionen zu vergrößern, ohne dass ich persönlich von diesen Dingen überwältigt werde, da die Reduzierung der Interaktionen auf ein Minimum die Anzahl der möglichen Stellen ebenfalls verringert möglicherweise sogar den Anwendungszustand ändern und erhebliche Nebenwirkungen verursachen.
Es kann sich so etwas drehen (wo alles im Diagramm Funktionalität hat und offensichtlich ein reales Szenario die vielfache Anzahl von Objekten haben würde, und dies ist ein "Interaktions" -Diagramm, kein Kopplungsdiagramm, als Kopplung man hätte abstraktionen dazwischen):
... dazu, wo nur die Systeme Funktionalität haben (die blauen Komponenten sind jetzt nur Daten, und jetzt ist dies ein Kopplungsdiagramm):
Und es tauchen Überlegungen dazu auf und vielleicht eine Möglichkeit, einige dieser Vorteile in einen konformeren OOP-Kontext einzufügen, der besser mit SOLID kompatibel ist, aber ich habe die Entwürfe und Wörter noch nicht ganz gefunden, und ich finde es schwierig, da die Terminologie, die ich gewohnt war, alle direkt mit OOP zu tun zu haben. Ich versuche immer wieder, die Antworten der Leute durchzulesen und mein Bestes zu geben, um meine eigenen zu formulieren, aber es gibt einige interessante Dinge an der Natur eines ECS, auf die ich nicht perfekt eingehen konnte kann sogar auf Architekturen angewendet werden, die es nicht verwenden. Ich hoffe auch, dass diese Antwort nicht als ECS-Promotion herauskommt! Ich finde es einfach sehr interessant, da das Entwerfen eines ECS meine Gedanken drastisch verändert hat.
quelle
SOLID-Prinzipien sind gut, aber KISS und YAGNI haben bei Konflikten Vorrang. Der Zweck von SOLID besteht darin, die Komplexität zu verwalten. Wenn SOLID jedoch selbst angewendet wird, wird der Code komplexer, wodurch der Zweck zunichte gemacht wird. Wenn Sie beispielsweise ein kleines Programm mit nur wenigen Klassen haben, kann das Anwenden von DI, Schnittstellentrennung usw. die Gesamtkomplexität des Programms sehr gut erhöhen.
Das Open / Closed-Prinzip ist besonders umstritten. Grundsätzlich heißt es, dass Sie einer Klasse Features hinzufügen sollten, indem Sie eine Unterklasse oder eine separate Implementierung derselben Schnittstelle erstellen, die ursprüngliche Klasse jedoch unberührt lassen. Wenn Sie eine Bibliothek oder einen Dienst verwalten, die bzw. der von nicht koordinierten Clients verwendet wird, ist dies sinnvoll, da Sie das Verhalten, auf das sich der Client verlassen kann, nicht unterbrechen möchten. Wenn Sie jedoch eine Klasse ändern, die nur in Ihrer eigenen Anwendung verwendet wird, ist es oft einfacher und übersichtlicher, die Klasse einfach zu ändern.
quelle
Durch meine Erfahrung:-
Große Klassen sind exponentiell schwieriger zu warten, wenn sie größer werden.
Kleine Klassen sind einfacher zu verwalten und die Schwierigkeit, eine Sammlung kleiner Klassen zu verwalten, steigt rechnerisch mit der Anzahl der Klassen.
Manchmal sind große Klassen unvermeidbar, ein großes Problem erfordert manchmal eine große Klasse, aber sie sind viel schwieriger zu lesen und zu verstehen. Für gut benannte kleinere Klassen kann nur der Name ausreichen, um zu verstehen, dass Sie nicht einmal den Code betrachten müssen, es sei denn, es liegt ein sehr spezielles Problem mit der Klasse vor.
quelle
Es fällt mir immer schwer, die Grenze zwischen dem „S“ des Festkörpers und dem (möglicherweise altmodischen) Bedürfnis zu ziehen, einem Objekt all das Wissen über sich selbst zu geben.
Vor 15 Jahren arbeitete ich mit Deplhi-Entwicklern zusammen, die ihren heiligen Gral hatten, um Klassen zu haben, die alles enthielten. Für eine Hypothek könnten Sie also Versicherungen und Zahlungen sowie Einkommen und Darlehen und Steuerinformationen hinzufügen und die zu zahlende Steuer berechnen und abziehen, und sie könnte sich selbst serialisieren, auf der Festplatte verbleiben usw. usw.
Und jetzt habe ich dasselbe Objekt in viele, viele kleinere Klassen unterteilt, die den Vorteil haben, dass sie viel einfacher und besser Unit-getestet werden können, aber keinen guten Überblick über das gesamte Geschäftsmodell geben.
Und ja, ich weiß, dass Sie Ihre Objekte nicht an die Datenbank binden möchten, aber Sie können ein Repository in der großen Hypothekenklasse hinzufügen, um das zu lösen.
Außerdem ist es nicht immer einfach, gute Namen für Klassen zu finden, die nur eine winzige Aufgabe haben.
Ich bin mir also nicht sicher, ob das "S" immer eine gute Idee ist.
quelle