Frage Wo gebe ich all diese Schnittstellen an?


Ich versuche, meine Füße nass mit Unit-Tests zu bekommen. Ich habe derzeit keine Gewohnheit, Interfaces für Klassen zu schreiben, es sei denn, ich sehe einen Grund, warum ich eine andere Implementierung eintauschen müsste. Nun, jetzt sehe ich einen Grund: Spott.

Angesichts der Tatsache, dass ich von einer Handvoll Schnittstellen auf vielleicht Hunderte gehe, fiel mir als Erstes auf: Wo sollte ich all diese Schnittstellen platzieren? Mische ich sie einfach mit allen konkreten Implementierungen zusammen oder lege sie in einen Unterordner. Z. B. sollten Controller-Schnittstellen in root / Controller / Interfaces, root / Controllers oder etwas ganz anderes gehen? Was raten Sie?


21
2018-06-16 00:41


Ursprung


Antworten:


Bevor ich über Organisation diskutiere:

Nun, jetzt sehe ich einen Grund: Spott.

Sie können auch mit Klassen spotten. Subclassing funktioniert gut als Option, anstatt immer Interfaces zu machen.

Schnittstellen sind unglaublich nützlich - aber ich würde nur empfehlen, eine Schnittstelle zu erstellen, wenn es einen Grund gibt, eine Schnittstelle zu erstellen. Ich sehe oft Schnittstellen, die erstellt werden, wenn eine Klasse gut funktionieren würde und logischer sinnvoll wäre. Sie sollten nicht "Hunderte von Interfaces" machen müssen, nur um sich Implementierungen auszutricksen - Kapselung und Subklassenbildung funktionieren dafür ziemlich gut.

Davon abgesehen, organisiere ich normalerweise meine Interfaces zusammen mit meinen Klassen, da das Gruppieren verwandter Typen in denselben Namespaces am sinnvollsten ist. Die Hauptausnahme ist bei internen Implementierungen von Schnittstellen - diese können überall sein, aber ich mache manchmal einen "internen" Ordner + einen internen Namespace, den ich speziell für "private" Schnittstellenimplementierungen (sowie andere Klassen, die rein interne Implementierung sind) verwenden ). Dies hilft mir, den Hauptnamensraum sauber zu halten, so dass die einzigen Typen die Haupttypen sind, die sich auf die API selbst beziehen.


18
2018-06-16 00:45



Hier ist ein Vorschlag: Wenn fast alle Ihre Schnittstellen nur eine Klasse unterstützen sollen, fügen Sie einfach die Schnittstelle zu derselben Datei wie die Klasse selbst unter demselben Namespace hinzu. Auf diese Weise haben Sie keine separate Datei für die Schnittstelle, die das Projekt wirklich durcheinander bringen könnte oder einen Unterordner nur für Schnittstellen benötigt.

Wenn Sie selbst verschiedene Klassen mit derselben Schnittstelle erstellen, würde ich die Schnittstelle in den gleichen Ordner wie die Klasse zerlegen, es sei denn, es wird völlig unordentlich. Aber ich denke nicht, dass das passieren würde, weil ich bezweifle, dass Sie Hunderte von Klassendateien in demselben Ordner haben. Wenn das der Fall ist, sollte das entsprechend der Funktionalität aufgeräumt werden und der Rest wird für sich selbst sorgen.


8
2018-06-16 01:19



Es kommt darauf an. Ich mache das: Wenn Sie eine abhängige 3rd Party Assembly hinzufügen müssen, verschieben Sie die konkreten Versionen in eine andere Klassenbibliothek. Wenn nicht, können sie im selben Verzeichnis und Namespace nebeneinander bleiben.


1
2018-06-16 00:46



Hier ist etwas, mit dem Sie beginnen können

http://aspalliance.com/2064_Creating_a_SOLID_Visual_Studio_Solution.all


0
2018-06-16 00:47



Ich finde, dass, wenn ich Hunderte von Schnittstellen in meinem Projekt benötige, um Abhängigkeiten zu isolieren, ich finde, dass es ein Problem in meinem Design geben könnte. Dies ist besonders der Fall, wenn viele dieser Schnittstellen nur eine Methode haben. Eine Alternative dazu besteht darin, dass Ihre Objekte Ereignisse auslösen und dann Ihre Abhängigkeiten an diese Ereignisse binden. Nehmen wir zum Beispiel an, Sie möchten Ihre Daten persistieren. Ein durchaus sinnvoller Weg wäre, dies zu tun:

public interface IDataPersistor
{
    void PersistData(Data data);
}

public class Foo
{
    private IDataPersistor Persistor { get; set; }
    public Foo(IDataPersistor persistor)
    {
        Persistor = persistor;
    }

    // somewhere in the implementation we call Persistor.PersistData(data);

}

Eine andere Möglichkeit, dies ohne Interfaces oder Mocks zu tun, wäre dies:

public class Foo
{
    public event EventHandler<PersistDataEventArgs> OnPersistData;

    // somewhere in the implementation we call OnPersistData(this, new PersistDataEventArgs(data))
}

Dann können Sie in unserem Test anstelle eines Mocks folgendes tun:

Foo foo = new Foo();
foo.OnPersistData += (sender, e) => { // do what your mock would do here };

// finish your test

Ich finde das sauberer als Mocks übermäßig zu verwenden.


0
2018-06-16 04:18