Dies ist eine eher philosophische Frage, die sich mit der .NET-Plattform befasst, aber möglicherweise ist sie auch für andere Sprachen nützlich. Ich mache viele Unit-Tests und vor allem, wenn ich Komponenten von Drittanbietern verwende, mit denen ich oft zu kämpfen habe. In .NET besteht ein enormer Anspruch auf Komponentendesign (er), zu entscheiden, welche Methode virtuell sein soll oder nicht. Auf der einen Seite ist es die Verwendung von Komponenten (was sinnvoll ist, um virtuell zu sein), auf der anderen Seite die Verspottbarkeit von Komponenten . Sie können Shims verwenden , um Komponenten von Drittanbietern zu verspotten. Dies führt jedoch häufig zu schlechtem Design und Komplexität. Wie ich mich erinnern kann, ging es bei der Diskussion darüber, alle Methoden virtuell zu machen (JAVA hat es von Anfang an) in .NET um Leistung. Aber es ist immer noch das Problem? Warum sind nicht alle Methoden in .NET virtuell oder warum hat nicht jede Klasse mindestens eine Schnittstelle?
quelle
Antworten:
Wie Anders sagt , geht es zum Teil um Leistung und zum Teil darum, schlecht durchdachte Entwürfe zu sperren, um den Umfang der Probleme zu verringern, die später von Menschen verursacht werden, die blind Dinge erben, die nicht für die Vererbung konzipiert wurden.
Die Leistung scheint offensichtlich zu sein - während die meisten Methoden auf moderner Hardware nicht bemerkt werden, kann ein virtueller Getter selbst bei moderner Hardware, die sich immer mehr auf leicht vorhersehbare Anweisungen in der CPU-Pipeline stützt, einen spürbaren Erfolg verursachen.
Der Grund, alles standardmäßig virtuell zu machen, scheint nur eines zu sein: Unit-Testing-Frameworks. Es scheint mir, dass dies ein schlechter Grund ist, wo wir den Code an das Framework anpassen, anstatt ihn richtig zu entwerfen.
Vielleicht liegt das Problem bei den hier verwendeten Frameworks. Sie sollten verbessert werden, um das Ersetzen von Funktionen zur Laufzeit durch injizierte Shims zu ermöglichen, anstatt Code zu erstellen, der dies tut (mit allen Hacks, um private Methoden zu umgehen, sowie nicht-virtuelle, nicht um Erwähnen Sie statische Funktionen und Funktionen von Drittanbietern.
Der Grund, warum Methoden standardmäßig nicht virtuell sind, ist wie Anders sagte, und jeder Wunsch, sie virtuell zu machen, um sie an ein Unit-Test-Tool anzupassen, stellt den Wagen vor das Pferd. Das richtige Design schlägt künstliche Einschränkungen.
Jetzt können Sie all dies abmildern, indem Sie Schnittstellen verwenden oder Ihre gesamte Codebasis überarbeiten, um Komponenten (oder Microservices) zu verwenden, die über die Nachrichtenübermittlung anstelle von direkt verkabelten Methodenaufrufen kommunizieren. Wenn Sie die Oberfläche einer Einheit zum Testen vergrößern, um eine Komponente zu sein, und diese Komponente vollständig in sich geschlossen ist, müssen Sie nicht wirklich damit schrauben, um sie zu testen.
quelle
Ihre Frage enthält zwei Elemente, daher werde ich versuchen, sie der Reihe nach zu beantworten:
Warum sind .NET-Methoden nicht standardmäßig virtuell?
Vererbung hat in der Praxis viele Probleme . Wenn es also als Teil eines Entwurfs verwendet werden soll, sollte es sorgfältig abgewogen werden. Indem Methoden standardmäßig nicht virtuell gemacht werden, wird der Entwickler theoretisch dazu ermutigt, beim Entwerfen einer Klasse über Vererbung nachzudenken. Ob das in der Praxis funktioniert, ist selbstverständlich.
Warum implementieren nicht alle Klassen eine Schnittstelle?
Schlechtes Design ist die einfache Antwort. Obwohl sie lange Zeit allgemein als bewährte Verfahren anerkannt wurden, entwerfen viele Leute ihre Systeme leider immer noch nicht mit Blick auf DI und TDD.
Die Kombination von Klassen, die nicht vollständig vererbbar sind und nicht leicht verspottet werden können, erzeugt einen "perfekten Sturm" von schwer zu testendem Code. Bis wir jedoch den Tag erreichen, an dem jeder DI und das Design-to-Interface-Prinzip verwendet, kann nicht viel getan werden, um die Schmerzen zu lindern.
quelle
interface
nur weil zu implementieren . Welchen Wert hat es, eininterface
für das zu haben, was im Wesentlichen ein verherrlichtes Tupel ist? (Obwohl die Verwendung eines POJO / POCO selbst möglicherweise ein Konstruktionsfehler ist)As soon as you use classes as types, you are no longer doing OO
- Klassen sind Typen. Was?? Die normale Klassenvererbung ist OO, egal was Sie sagen. Sie können sich nicht mehr entscheiden, dass es nicht mehr OO ist, nur weil DI jetzt der letzte Schrei ist.