When pursuing logic-to-contract coupling, additional
coupling flexibility can be built into the service architecture by
further establishing layers of implementation logic. Service Façade advocates the positioning of façade components between the service contract and the core service logic (Figure 1),
as well as between the core service logic and the underlying service
implementation resources (in particular legacy resources).
The former positioning
protects the core service logic from changes to the contract or impacts
that may result from the application of Concurrent Contracts.
The latter positioning of
the façade logic allows for core business logic to be captured in one
layer and logic proprietary to specific parts of the implementation
(such as databases or legacy APIs) to reside in a different layer. When
those underlying legacy resources need to be changed or replaced in the
future, the impact to the service architecture is further shielded.
Typically a Service Façade can contain code that:
chooses which methods or functions to call in the core implementation
compensates for changes in logic and/or data model so that logic-to-contract coupling is retained
allows the core business logic to remain physically separate and stable if the service contract itself should need to change
The following series of examples shows how you could build a façade that removes address information from a person.
Consider first the service interface:
Example 1.
[ServiceContract] interface IPersonService { [OperationContract] person GetPerson(int personId); }
|
The following class implements the interface and returns the information that another .NET class produces:
Example 2.
class PersonService : IPersonService { public person GetPerson(int personId) { return ServiceImplementation.GetPersonById(personId); } }
|
Another class can also implement the interface, but notice that this class doesn’t just return the information that ServiceImplementation creates:
Example 3.
class SimplePersonService : IPersonService { public person GetPerson(int personId) { var person = ServiceImplementation. GetPersonById(personId); person.address = null; return person; } }
|
The class that really implements most of the underlying façade functionality is ServiceImplementation, as follows:
Example 4.
class ServiceImplementation { public static person GetPersonById(int personId) { return new person { id = personId }; } }
|
Note
how in the preceding example, the two different façade components
implement WCF code (since they implement the interface that is annotated
with WCF attributes), but the core service logic is not WCF code. This
allows the core implementation to exist unaware of WCF.