This is a discussion on Facade Pattern and its role in a subsystem interface within the Software Patterns forums, part of the Testing category; Hi, I've been following up on some replies by H.S.Lahman to posts I sent to comp.object ...
|
|||||||
| Register | FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read |
|
|||
|
Facade Pattern and its role in a subsystem interface
Hi,
I've been following up on some replies by H.S.Lahman to posts I sent to comp.object relating to modelling interfaces. To summarise, I've followed his advice and encapsulated a set of classes that form my subsystem by using a Facade which derives from the subsystem interface. The rest of the application is free to access the services provided by the subsystem through this Facade interface. I think I generally understand pretty well the role Facade will play here. What I'm not sure about is how best to implement it. I don't like the way it is presented in the GOF book (because it just goes over my head) and I've searched in vain on the net for an example case study. The advice I've been given is to implement it as a pure data transfer interface that has a message id and a data packet. I have tried to implement what I think this is, but my solution is not very elegant. What I'm after, I guess, is a worked example that includes C++ code that I can spend time studying and learn the various techniques that are involved in implementing this. For example, how does the client uses a pure data transfer interface to access the services provided by a subsystem and how does the Facade map the message ids to something meaningful within the context of its own subsystem. My research since I had a go at implementing a solution has revealed that the message id is usually the name of a Facade method. This leads me to believe that for a subsystem that provides many serivces through a simple interface, the Facade could have a lot of methods. My attempt just used an integer id which both client and Facade had access to. The data packet was a void *. Any advice will be much appreciated. |
|
|||
|
Re: Facade Pattern and its role in a subsystem interface
On 30 Oct 2003 14:43:14 -0800, adamjoe1@yahoo.co.uk (Adam) wrote:
>Hi, > >I've been following up on some replies by H.S.Lahman to posts I sent >to comp.object relating to modelling interfaces. > >To summarise, I've followed his advice and encapsulated a set of >classes that form my subsystem by using a Facade which derives from >the subsystem interface. The rest of the application is free to access >the services provided by the subsystem through this Facade interface. > >[...] > >My research since I had a go at implementing a solution has revealed >that the message id is usually the name of a Facade method. This leads >me to believe that for a subsystem that provides many serivces through >a simple interface, the Facade could have a lot of methods. My attempt >just used an integer id which both client and Facade had access to. >The data packet was a void *. Hi Adam, in his electronic book Thinking in Patterns (downloadable at http://www.mindview.net) Bruce Eckel describes the purpose of the facade as follows: "If you have a rather confusing collection of classes and interactions that the client programmer doesn't really need to see, then you can create an interface that [...] only presents what's necessary." Or to put it more simple: "If something is ugly, hide it inside an object." In case I understand you right, you initially were confronted with a fairly complex subsystem which provided a number of services to clients. To make the subsystem easier to understand and more comfortable to use you developed a simplified interface for it by adopting the facade pattern. In addition, for the sake of sophisticated OOP style clients shall not call methods of that interface directly but send messages (plus additional data) to the facade which then maps the messages to services of the subsystem. However, since you did not want to implement a seperate reciever method for every possible message you settled for one single method that takes an integer id and a void pointer to data objects. The void* gets typecasted to the appropriate class according to the type of integer id (giant switch statement?) I agree with you that this is not exactly good style. The main issue with your current design appears to be that facade alone is not sufficient to solve your problem. Patterns like proxy, functor/command or command processor should help you in developing a more elegant solution. You might want to have a look at the book "Pattern-Oriented Software: A System of Patterns" by Buschman et al. (1996), too. Sorry for not having any concrete advice, Malte. --- The above e-mail address is not valid. To contact me, please use my real e-mail address: malte AT t DASH online DOT de Just replace the capitalized words with the corresponding punctuation marks. |
|
|||
|
Re: Facade Pattern and its role in a subsystem interface
Hi Malte,
> In addition, for the sake of sophisticated OOP style clients shall not > call methods of that interface directly but send messages (plus > additional data) to the facade which then maps the messages to > services of the subsystem. Your summation is about right although I'm not sure about the above paragraph. To clarify: I now have a subsystem that exposes 1 interface with a couple of methods on it. In C++ terms, this is a class with only pure virtual functions, that has a message id and a void pointer parameters. The Facade derives from this interface and uses the message id parameter to determine which class within the subsystem to invoke an operation on. The client maintains a pointer (of the same type as the interface) to the Facade so it can call its methods. > Sorry for not having any concrete advice, Thanks for your reply anyway. I must say I'm surprised at the lack of response to this post and this subject in general. |
|
|||
|
Re: Facade Pattern and its role in a subsystem interface
>To clarify:
> >I now have a subsystem that exposes 1 interface with a couple of >methods on it. In C++ terms, this is a class with only pure virtual >functions, that has a message id and a void pointer parameters. The >Facade derives from this interface and uses the message id parameter >to determine which class within the subsystem to invoke an operation >on. The client maintains a pointer (of the same type as the interface) >to the Facade so it can call its methods. Ahh, now I seem to get you. I thought that you had your facade implemented like the string command part of the Windows MCI, where you send strings to the interface of the multimedia system which then executes the requested operations. An example would be: MyFacade.AcceptCommand("open digitalvideo", (void*)SomeDataStruct) This is what I believed you were doing - which is obviously not the case. Do I understand you correctly that all the subsystems in your system are "facaded" by 1 single interface, meaning that each subsystem is assessed through the same set of fairly general methods (like Execute(), Abort(), Status() and so forth). A concrete facade infers from its MessageID which subsystem to operate on and therefore also knows what class the void* data structure ought to be typecasted to. Is that right? What remains unclear to me is the nature of your complex original subsystem and its classes. There are many quite divergent structures of subsystems one could possibly imagine. To outline only 2 of them: 1. The subsystem consists of many pretty similar classes like Frog, Fly, Bee and Flower. The facade wraps these classes and interconnections to make a Frog comply to the same interface as a Flower, e. g. with universal functions such as Feed(), Spawn() or Die(). 2. The subsystem is a pile of distinct classes which fulfil special purposes in a common context. This might be a package of network utilities like the "net" command in the Windows OS which offers a variety of functions, e. g. Net Use, Net View and Net Send. I suppose a facade for the latter would be implemented rather differently compared to the first case. Maybe you can specify your problem in this sense. Regards, Malte --- The above e-mail address is not valid. To contact me, please use my real e-mail address: malte AT t DASH online DOT de Just replace the capitalized words with the corresponding punctuation marks. |
|
|||
|
Re: Facade Pattern and its role in a subsystem interface
Hi Malte,
Thanks again for your reply. It seems I'm not getting my point across very well. > I thought that you had your facade implemented like the string command > part of the Windows MCI, where you send strings to the interface of > the multimedia system which then executes the requested operations. > An example would be: > > MyFacade.AcceptCommand("open digitalvideo", (void*)SomeDataStruct) > > This is what I believed you were doing - which is obviously not the > case. I don't know anything about Windows MCI but your example is close. See below. Msg Id is just an int that means the same thing to both the client and the facade. MyFacade.AcceptCommand(msgId, (void*)SomeDataStruct) > Do I understand you correctly that all the subsystems in your system > are "facaded" by 1 single interface Each subsystem exposes one interface. One interface per subsystem. Each interface has a concrete facade derivative. > Each subsystem is > assessed through the same set of fairly general methods (like > Execute(), Abort(), Status() and so forth). Each subsystem is accessed through its own set of general methods. Subsystem A may have Execute() and Abort() methods while Subsystem B may have Read() and Write() methods. > A concrete facade infers > from its MessageID which subsystem to operate on and therefore also > knows what class the void* data structure ought to be typecasted to. > Is that right? > Not quite. Each concrete facade infers from its MessageID which class within its own subsystem to operate on. In Subsystem B there may be several classes that the Read() operation is appropriate to. For example there may be different types of memory that can be read. The client invokes Read() on the interface with a given message id. The Facade looks at the message id and invokes the appropriate operation on the aporpriate class within the subsystem. > What remains unclear to me is the nature of your complex original > subsystem and its classes. There are many quite divergent structures > of subsystems one could possibly imagine. To outline only 2 of them: > 1. The subsystem consists of many pretty similar classes like Frog, > Fly, Bee and Flower. The facade wraps these classes and > interconnections to make a Frog comply to the same interface as a > Flower, e. g. with universal functions such as Feed(), Spawn() or > Die(). > > 2. The subsystem is a pile of distinct classes which fulfil special > purposes in a common context. This might be a package of network > utilities like the "net" command in the Windows OS which offers a > variety of functions, e. g. Net Use, Net View and Net Send. > > I suppose a facade for the latter would be implemented rather > differently compared to the first case. > Maybe you can specify your problem in this sense. > OK. It is more like your second example. Each subsystem consists of a set of distinct classes which collaborate together to provide some functionality within the system. A subsystem encapsulates a subject matter. The Facade should provide an interface to the subject matter appropriate to that view of its clients. For example a HardwareInterface subsystem may provide services such as Read and Write which depending on the message Id may result in writing data to non volatile RAM or writing an event to an event log. The implementation of the write service is delegated to other classes by the Facade according to the message id. Does this help? Regards Adam |
|
|||
|
Re: Facade Pattern and its role in a subsystem interface
>Thanks again for your reply. It seems I'm not getting my point across
>very well. Might also be me not getting your point very well ;-) >Each subsystem is accessed through its own set of general methods. >Subsystem A may have Execute() and Abort() methods while Subsystem B >may have Read() and Write() methods. >[...] >Each concrete facade infers from its MessageID which class >within its own subsystem to operate on. >[...] >Each subsystem consists of a set of distinct classes which collaborate >together to provide some functionality within the system. A subsystem >encapsulates a subject matter. Alright! I'm enlightened now. Many subsystems with many classes. One Facade per subsystem. Many public interface methods per facade. Which class of a subsystem a specific facade method ought to act upon gets specified by the MessageID. Every interface method internally delegates the concrete operation to a private method based on the MessageID. Probably I would think about externalizing the private methods and encapsulate them in a command (command/functor pattern). These commands can be requested from a command factory (factory pattern) by the clients. Hence, if a client wanted to Write() something to a log, the client would do it this way: // subsystem gets instantiated somewhere SomeSubsystem mySubsystem; [...] // now a client decides to log something // first he fills a log data structure LogDataStructure logData; logData.Text= "System slips into manic state."; logData.Target= idErrorLog; logData.Expires= tomorrow(); // then he gets a logging command base on the given data WriteToLogCommand logCmd = CommandFactory.CreateCommand(logData, mySubsystem); // The factory internally checks for the "Target" property and returns // the appropriate command, filled with your data about what, where // and when to log. Moreover, the factory equips the command with a // reference to the subsystem. // finally execute the command // (method Execute() is common to all commands) logCmd.Execute(); Instead of facades with giant internal switch statements you now deal with a transparent set of commands. All of them know the subsystem and its classes good enough to be able to perform the requested operations. You might well add a level of decoupling with the visitor pattern. A command internally would spawn a visitor which itself would then visit the subsystem. Implemention somewhat as follows: // the command's execute method void WriteToLogCommand.Execute() { SubsystemLoggingVisitor logVisitor(text, target, expires); // the command got the values from the factory which read them // out off the logData structure mysubsystem.Accept(logVisitor); // mySubsystem also was handed to the command by the factory } // the subsystem's accept method void SomeSubsystem.Accept(SystemVisitorBaseClass aVisitor) { aVisitor.VisitSystem(this); } Now all subsystems comply to the same interface - which mainly consists of just the Accept() method. Moreover, the Accept() method of any system could decide whether to accept the visiting command or decline the request, e. g. based on some internal state. HTH, Malte --- The above e-mail address is not valid. To contact me, please use my real e-mail address: malte AT t DASH online DOT de |