To remind (from wiki):
The interface-segregation principle (ISP) states that no client should be forced to depend on methods it does not use.
And now look at my example.
Here's my mutable entity. It is edited from somewhere and it is able to notify about changes through 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's the class from transport layer which uses it. Look at two variants of injection (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);
};
}
}
- ISP is about real objects. You must not use "excessive" references to incoming parameters.
- ISP is about classes. If your class already uses full interface
somewhere, no need to restrict reference type in particular methods.
ICounter
interface is excessive in this example. - This architecture is completely wrong from the point of SOLID principles (then why?).