The principle of interface segregation in relation to classes or objects?

To remind (from the wiki ):

The principle of interface segregation (ISP) states that no client should be forced to depend on methods that he does not use.

Now look at my example.

Here is my changing nature. It is being edited from somewhere and it can notify of changes through the read-only interface:

interface ICounter { event Action<int> NewNumber; } class Counter : ICounter { public event Action<int> NewNumber; int number = 0; public void IncrementAndSend(int x) { number += x; if (NewNumber != null) NewNumber(number); } } 

And here is the class from the transport layer that uses it. Look at the two injection options ( Attach_1 and Attach_2 ) and my assumptions below:

 class OneToManyRouter { IEnumerable<Counter> _destinations; public OneToManyRouter(IEnumerable<Counter> destinations) { _destinations = destinations; } // 1 public void Attach_1(ICounter source) { source.NewNumber += (n) => { foreach (var dest in _destinations) dest.IncrementAndSend(n); }; } // 2 public void Attach_2(Counter source) { source.NewNumber += (n) => { foreach (var dest in _destinations) dest.IncrementAndSend(n); }; } } 
  • ISPs are real objects. You should not use "excessive" links to incoming parameters.
  • ISPs are classes. If your class already uses the full interface somewhere, there is no need to restrict the reference type in certain methods. In this example, the ICounter interface is excessive.
  • This architecture is completely flawed from the point of view of SOLID principles (then why?).
+4
source share
2 answers

ISP does not apply to classes or objects, but strictly about interfaces, in particular, about interface design. This principle is designed to prevent the grouping of semi-connected methods in one interface, so that users do not need only a subset of these methods to implement the rest as empty functions (either throwing a NotImplementedException or leaving it literally empty: { } ). Thus, it is easier to implement more consistent classes and use interfaces more efficiently.

In your example, you combine the Counter class with the ICounter interface in a way that is not directly related to the concept of ISP:

  • ISPs are real objects. You should not use "excessive" links to incoming parameters.

This is partly true (if I correctly interpret the concept of "overly"). However, as I said, ISP is not related to how to interact with real objects, but how to define a useful interface.

  • ISPs are classes. If your class already uses the full interface, you do not need to restrict the reference type in certain methods. In this example, the ICounter interface is excessive.

This is not true. The fact that a class implements an interface does not mean anything if you create a dependency on a particular class, not an interface. Remember that the interface provides a decoupling of various parts of your program, forcing components to rely on contracts, and not on a specific implementation, which may change in the future. Using a particular class, you lose this advantage. And again, this is not entirely related to the concept of ISP.

  • This architecture is completely wrong in terms of SOLID principles (then why?).

From an architectural point of view, with an emphasis on SOLID principles, I would suggest having a dependency on ICounter , not Counter , including IncrementAndSend as part of the interface definition.

+2
source

I think it would be better to add the IncrementAndSend method to the interface and make the OneToManyRouter class dependent on IEnumerable <ICounter>. In my opinion, this is not an ISP violation, because the action of the NewNumber event and the IncrementAndSend method are strictly related. Hope this helps you.

0
source

Source: https://habr.com/ru/post/1492342/


All Articles