Note
These docs are a work in progress. While conceptually correct, the diagrams/code samples on this page might not be 100% in line with the current implementation in Copper.
Multi-facet service
Context and problem
Given that we want to expose a service by it's interface, and we have to adhere to the contract factoring rules (specified in the WCF book and Righting Software). There is a limit to the number of operations possible that we are allowed to expose on that given contract. It brings up the question how to keep the cost vs. count balance in check by not having to many actual services, while still having logically coherent contracts that abide the rules.
Solution
The solution to this problem is to allow for multiple facets
that any service class
can expose. There are a number of techniques that allow you to achieve multi-facet services, and even spec these out further. These techniques are from the Righting Software book.
Managers
Engine/Access
Factoring down
From
interface IScannerAccess
{
long ScanCode();
void AdjustBeam();
void OpenPort();
void ClosePort();
}
class BarcodeScanner : IScannerAccess
{...}
class QRCodeScanner : IScannerAccess
{...}
To
interface IReaderAccess
{
long ReadCode();
void OpenPort();
void ClosePort();
}
interface IScannerAccess : IReaderAccess
{
void AdjustBeam();
}
class BarcodeScanner : IScannerAccess
{...}
class QRCodeScanner : IScannerAccess
{...}
class KeypadReader : IReaderAccess
{...}
class RFIDReader : IReaderAccess
{...}
Factoring sideways
Most common technique to split out into multiple facets, making the service class implement each facet. This makes it easy to collapse or expand the architecture later on, as facets can be moved between service classes.
Example:
interface ICommunicationDevice
{
void OpenPort();
void ClosePort();
}
interface IReaderAccess
{
long ReadCode();
}
class BarcodeScanner :
IScannerAccess,ICommunicationDevice
{...}
Factoring up
Extending each derived contract by inheriting from a shared base contract.
Example:
interface IDeviceControl
{
void Abort();
long RunDiagnostics();
}
interface IReaderAccess : IDeviceControl
{...}
interface IBeltAccess : IDeviceControl
{...}