IOSP Roslyn Analyzer

This project began as an article for the German magazine dotnetpro. It contains a Roslyn Analyzer for the Integration Operation Segregation Principle (IOSP).

The package analyzes whether methods Integration Operation Segregation Principle violate. The principle states that a method is either an integration method or an operation. Integration methods call other methods that are defined and implemented in your solution. If one of your methods calls another of your methods, it is the task of this method to integrate the called methods. On the other hand, an operation must not call any of your own methods. An operation calls APIs (framework and runtime methods) and contains expressions such as "x + 2 < 42". API calls are calls to external methods that are not defined in your code. For example Console.WriteLine or object.ToString API calls.

In order to clearly separate integration and operation, we can establish the following simple rules:

  • Integration:
    • Calls only your own methods
  • Operation:
    • Only calls external methods from runtime and frameworks
    • May contain expressions

The reasoning behind the IOSP is as follows: If we strictly separate integration from operation, this leads to a better understanding of the code structure. This is because the level of abstraction is clearly separated into high-level vs. low-level code. Integration methods are at a high level of abstraction. They only call other methods in order to integrate them. Therefore, it is easy to understand such a high-level integration method. On the other hand, an operation is easy to read because it only contains code at a low level. Given that an operation is also assigned to the Single Responsibility Principle (SRP), an operation is easy to read and understand because it only contains low-level code that solves a specific problem. To understand an operation, it is not necessary to understand other methods from the solution. It is only necessary to understand calls to runtime or framework functionalities.

The second advantage of conformity with the IOSP is testability. If we strictly separate integration from operation, we can test the operations in isolation. Since operations do not call other methods from our solution, each operation is a separate functional unit. Therefore, we do not need mocks to separate an operation from its dependencies. It has no dependencies, otherwise it would mix operational code with integration and thus violate the IOSP. The integration methods do not contain any logic. It is therefore not necessary to separate the integration methods from their dependencies. The only task of the integration methods is to integrate calls to other methods. So we test the integration methods with integration tests.

Integration methods can include control structures such as foreach, for, while, if or switch/case-instructions. They just must not contain expressions. It is fine to call a function that contains the expression:

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

vs.

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

Using the NuGet package

Install the package in your implementation projects. It is not necessary to install it in test projects because a test always violates the IOSP: a test contains calls to your own methods, the methods you want to test. And it calls Assert.That and other methods from the test framework. So we always mix integration and operation in a test.

The following image shows the package in action. JetBrains Rider is used as the IDE here. The method name is highlighted because the method violates the IOSP. If you move the mouse over the method name, a description is displayed. The description shows why the IOSP is violated by displaying integration and operation components. In the example, the method calls HandleUseCase on the one hand the method Insert on. This is integration because the method belongs to us. On the other hand, the methods ToString and NewGuid which belong to the .NET framework. In addition, the method contains the expression customer.name == ""which is also only permitted in operations.

IOSP Analyzer Example 1
en_USEnglish