IOSP Roslyn Analyzer

Dieses Projekt begann als Artikel für das deutsche Magazin dotnetpro. Es enthält einen Roslyn Analyzer für das Integration Operation Segregation Principle (IOSP).

Das Paket analysiert, ob Methoden das Integration Operation Segregation Principle verletzen. Das Prinzip besagt, dass eine Methode entweder eine Integrationsmethode oder eine Operation ist. Integrationsmethoden rufen andere Methoden auf, die in Ihrer Lösung definiert und implementiert sind. Wenn eine Ihrer Methoden eine andere Ihrer Methoden aufruft, ist es Aufgabe dieser Methode, die aufgerufenen Methoden zu integrieren. Andererseits darf eine Operation keine Ihrer eigenen Methoden aufrufen. Eine Operation ruft APIs (Framework- und Laufzeitmethoden) auf und enthält Ausdrücke wie „x + 2 < 42“. API-Aufrufe sind Aufrufe an fremde Methoden, die nicht in Ihrem Code definiert sind. Zum Beispiel sind Console.WriteLine oder object.ToString API-Aufrufe.

Um Integration und Operation klar zu trennen, können wir folgende einfache Regeln aufstellen:

  • Integration:
    • Ruft nur Ihre eigenen Methoden auf
  • Operation:
    • Ruft nur fremde Methoden aus Runtime und Frameworks auf
    • Kann Ausdrücke enthalten

Die Begründung hinter dem IOSP ist folgende: Wenn wir Integration von Operation strikt trennen, führt dies zu einem besseren Verständnis der Code-Struktur. Dies liegt daran, dass das Abstraktionsniveau klar in High-Level vs. Low-Level-Code getrennt ist. Integrationsmethoden befinden sich auf einer hohen Abstraktionsebene. Sie rufen andere Methoden nur auf, um sie zu integrieren. Daher ist es einfach, eine solche High-Level-Integrationsmethode zu verstehen. Andererseits ist eine Operation leicht zu lesen, weil sie nur Code auf einer niedrigen Ebene enthält. Angesichts dessen, dass eine Operation auch dem Single Responsibility Principle (SRP) entsprechen muss, ist eine Operation leicht zu lesen und zu verstehen, weil sie nur Low-Level-Code enthält, der ein spezifisches Problem löst. Um eine Operation zu verstehen, ist es nicht notwendig, andere Methoden aus der Lösung zu verstehen. Es ist nur notwendig, Aufrufe an Laufzeit- oder Framework-Funktionalitäten zu verstehen.

Der zweite Vorteil der Konformität mit dem IOSP ist die Testbarkeit. Wenn wir Integration von Operation strikt trennen, können wir die Operationen isoliert testen. Da Operationen keine anderen Methoden aus unserer Lösung aufrufen, ist jede Operation eine separate funktionale Einheit. Daher benötigen wir keine Mocks, um eine Operation von ihren Abhängigkeiten zu trennen. Sie hat keine Abhängigkeiten, sonst würde sie operationellen Code mit Integration vermischen und somit gegen das IOSP verstoßen. Die Integrationsmethoden enthalten keine Logik. Daher ist es nicht notwendig, die Integrationsmethoden von ihren Abhängigkeiten zu trennen. Die einzige Aufgabe der Integrationsmethoden ist es, Aufrufe an andere Methoden zu integrieren. Also testen wir die Integrationsmethoden mit Integrationstests.

Integrationsmethoden können Kontrollstrukturen wie foreach, for, while, if oder switch/case-Anweisungen enthalten. Sie dürfen lediglich keine Ausdrücke enthalten. Es ist in Ordnung, eine Funktion aufzurufen, die den Ausdruck enthält:

if(x + 2 == 42) { ... }  // violates IOSP if contained in an integration

vs.

if(ThisIsTheAnswer(x)) { ... }  // ok because it calls other method

Das NuGet Paket verwenden

Installieren Sie das Paket in Ihre Implementierungsprojekte. Es ist nicht notwendig, es in Testprojekte zu installieren, da ein Test immer das IOSP verletzt: ein Test enthält Aufrufe zu Ihren eigenen Methoden, den Methoden, die Sie testen möchten. Und er ruft Assert.That und andere Methoden aus dem Testframework auf. Also mischen wir in einem Test immer Integration und Operation.

Das folgende Bild zeigt das Paket in Aktion. Hier wird JetBrains Rider als IDE verwendet. Der Methodenname ist markiert, weil die Methode das IOSP verletzt. Wenn Sie mit der Maus über den Methodennamen fahren, wird eine Beschreibung angezeigt. Die Beschreibung zeigt, warum das IOSP verletzt wird, in dem Integrations- und Operationsbestandteile angezeigt werden. Im Beispiel ruft die Methode HandleUseCase einerseits die Methode Insert auf. Dies ist Integration, weil die Methode uns gehört. Andererseits werden die Methoden ToString und NewGuid aufgerufen, die zum .NET-Framework gehören. Darüber hinaus enthält die Methode den Ausdruck customer.Name == „“, der ebenfalls nur in Operationen erlaubt ist.

IOSP Analyzer Example 1
de_DEGerman