.NET developers should by familiar with the standard access modifiers (public, protected, internal, private). However, in loosely coupled code we can regard interface implementations as a fifth access modifier. This concept was originally introduced to me by Udi Dahan the only time I’ve had the pleasure of meeting him. That was many years ago and while I didn’t grok it back then, I’ve subsequently come to appreciate it quite a lot.
Although I can’t take credit for the idea, I’ve never seen it described, and it really deserves to be.
The basic idea is simple:
If a consumer respects the Liskov Substitution Principle (LSP), the only visible members are those belonging to the interface. Thus, the interface represents a dimension of visibility.
As an example, consider this simple interface from AutoFixture:
public interface ISpecimenContext
{
object Resolve(object request);
}
A well-behaved consumer can only invoke the Resolve method even though an implementation may have additional public members:
public class SpecimenContext : ISpecimenContext
private readonly ISpecimenBuilder builder;
public SpecimenContext(ISpecimenBuilder builder)
if (builder == null)
throw new ArgumentNullException("builder");
this.builder = builder;
public ISpecimenBuilder Builder
get { return this.builder; }
#region ISpecimenContext Members
public object Resolve(object request)
return this.Builder.Create(request, this);
#endregion
Even though the SpecimenContext class defines the Builder property, as well as a public constructor, any consumer respecting the LSP will only see the Resolve method.
In fact, the Builder property on the SpecimenContext class mostly exists to support unit testing because I sometimes need to assert that a given instance of SpecimenContext contains the expected ISpecimenBuilder. This doesn’t break encapsulation since the Builder is exposed as a read-only property, and it more importantly doesn’t pollute the API.
To support unit testing (and whichever other clients might be interested in the encapsulated ISpecimenBuilder) we have a public property that follows all framework design guidelines. However, it’s essentially an implementation detail, so it’s not visible via the ISpecimenContext interface.
When writing loosely coupled code, I’ve increasingly begun to see the interfaces as the real API. Most other (even public) members are pure implementation details. If the members are public, I still demand that they follow the framework design guidelines, but I don’t consider them parts of the API. It’s a very important distinction.
The interfaces define the bulk of an application’s API. Most other types and members are implementation details.
An important corollary is that constructors are implementation details too, since they can never by part of any interfaces.
In that sense we can regard interfaces as a fifth access modifier – perhaps even the most important one.
Remember Me
a@href@title, b, em, i, strike, strong
Page rendered at Thursday, February 23, 2012 4:53:09 AM (Romance Standard Time, UTC+01:00)
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.