Selectively Exposing Functionallity in .Net
- by David V. Corbin
Any developer should be aware of the principles of encapsulation, cross-tier isolation, and cross-functional separation of concerns. However, it seems the few take the time to consider the adage of "minimal yet complete"1 when developing the software.
Consider the exposure of "business objects" to the user interface. Some common situations occur:
Accessing a given element requires a compound set of calls that do not "make sense" to the User Interface.
More information than absolutely required is exposed to the user interface
It would be much cleaner if a custom interface was provided that exposed exactly (and only) the information that is required by the consumer.
Achieving this using conventional techniques would require the creation (and maintenance!) of custom classes to filter and transpose the information into the ideal format. Determining the ROI on this approach can be very difficult to ascertain, and as a result it is often ignored completely.
There is another approach, which is largely made practical by virtual of the Action and Func delegates. From a callers point of view, the following two samples can be used interchangeably:
interface ISomeInterface
{
void SampleMethod1(string param);
string SamepleMethod2(string param);
}
class ISomeInterface
{
public Action<string> SampleMethod1 {get; }
public Func<string,string> SamepleMethod2 {get; }
}
The capabilities this simple changes enable are significant (and remember it does not cange the syntax at the call site):
The delegates can be initialized to directly call the proper method of any target class.
The delegates can be dynamically updated based on the current state.
The "interface" can NOT be cast to the concrete class (which often exposes more functionallity).
This patterns
By limiting the interface to the exact functionallity required, the reduced surface area will typically result in lower development, testing and maintenance costs.
We are currently in the process of posting a project on CodePlex which illustrates this (and many other) techniques which have proven helpful in creating robust yet flexible solutions that are highly efficient2 and maintainable. This post will be updated as soon as the project is published.
1) Credit: Scott Meyers, Effective C++, Addison-Wesley 1992
2) For those who read my previous post on performance it should be noted that the use of delegates is on the same order of magnitude (actually a tiny amount faster) as conventional interfaces.