Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to distinguish 'Role' interfaces from 'Result' interfaces?

Tags:

c#

oop

interface

This issue comes up for me so often in my coding that I'm astonished I can find so little reference to it, and would value other people's thoughts and ideas.

I define lots of APIs, for the frameworks I work on, and within large domain models that I want to break up. Those APIs consist almost entirely of interfaces (meaning, in my case, C# interfaces). I find, over and over again, that I want to distinguish between two kinds of interface. In the absence of finding any more widely used terms, I define these two as follows:

  • 'Role' interfaces are intended to be implemented by objects outside of the API, in order that those objects can be used as arguments for methods defined on the API.

  • 'Result' interfaces are implemented by objects inside the API and made available to other parts of the system via the API. The intent of defining a result interface rather than exposing the object that implements it is to restrict the view of the object to the outside world.

To pick one example, a Payments sub-system might define IPayableItem as a Role interface, implemented by many types in other parts of the application in order that Payments may be generated for them. Those generated Payment objects may be retrieved via the API but defined by the Result interface IPayment.

The only way I can currently distinguish these is by naming convention and/or commenting. Ideally, I would like the distinction enforced by the language, and have it enforce the rule: you can't implement a Result interface outside the API, only use it. But C# doesn't provide any such mechanism. (Can anyone advise me of a language that does?). I could define an attribute, but this still wouldn't enforce anything.

Another important significance of the distinction lies in Semantic Versioning of the API. If I add a new member to a Role interface then this should be seen as a breaking change (and hence a first-level version) - because any existing external implementations will need to add that member. But if I add a member to what I deem to be a 'Result' interface then it should only be my own code that is impacted - it is just a new feature (second-level version) for everyone else. But with no enforced distinction between the two types there's some risk that people are implementing the Result interfaces and hence their code would be broken.

Has anyone else encountered this dilemma? If so, how have you dealt with it? I look forward to your answers.

But please don't both to respond with either of the following arguments (which I have heard all too often):

  • My Result interfaces should be abstract classes rather than interfaces. This does not solve the problem, and potentially makes it worse, since external code can sub-class them.

  • I should be returning the concrete type and ensuring that anything I don't want accessible outside the API is marked 'internal'. There are lots of cases where I need things inside the API to be public, e.g. to be accessible to other frameworks (not going through the API).

like image 282
Richard Pawson Avatar asked Oct 17 '14 16:10

Richard Pawson


People also ask

What is the role of interface?

A role interface is defined by looking at a specific interaction between suppliers and consumers. A supplier component will usually implement several role interfaces, one for each of these patterns of interaction. This contrasts to a HeaderInterface, where the supplier will only have a single interface.

Can a class inherit multiple interfaces in C#?

2) C# does not support "multiple inheritance" (a class can only inherit from one base class). However, it can be achieved with interfaces, because the class can implement multiple interfaces. Note: To implement multiple interfaces, separate them with a comma (see example below).

Can interface inherit another interface?

Interface inheritance : An Interface can extend other interface. Inheritance is inheriting the properties of parent class into child class.


1 Answers

I think what you're asking is it possible to expose an interface, but determine that a given instance is one you created?

If so, you could also create an internal private interface, and mark all your implementations as also implementing the private interface. Then upon being given an object from the outside world, verify it has the internal interface implementation as well.

public interface IPublic
{
    ...
}

internal interface ISecret { }

public class PublicImplementation : IPublic, ISecret
{
    ...
}

Only you can implement the ISecret, so even if someone implements the IPublic and passes it to you, it will fail the ISecret test.

like image 113
Eric Avatar answered Oct 13 '22 17:10

Eric