Friday, April 10, 2020

Design Patterns – The Façade

The façade is, perhaps, the second most commonly implemented design pattern. Just like the Bridge (probably the most widely used pattern of all, and certainly the most fundamental) it is usually implemented without a conscious decision having been made. Does this mean that it merely a statement of the obvious? Perhaps, but the pattern does have a very specific intent, and should definitely be taken seriously.

What is a Façade?
The formal definition for Façade offered by Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides is:
Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use
Succinct, but perhaps not quite so obvious after all. Consider the basic three tier architecture so widely used in software design. How should you define the middle tier? Potentially there are going to be many different objects in that middle tier. For example you may have any, or all, of the following types of object:
·         Data Validation objects·         Business Rule Objects·         Data Transformation Objects·         Data Access/Database Connection Objects
How is your Presentation Tier going to manage all the interactions with these individual objects? You could easily end up with a frightful mess where each object in the Presentation Tier must have detailed knowledge of each of the middle tier objects and has to handle them directly. The resulting system diagram looks horribly like that shown in Figure 1.
Not only is this aesthetically displeasing, it illustrates that we have a tightly coupled system which is, as always, prone to error when things change. Changes to any of the middle tier components must be reflected in all of the Presentation Tier components that access them!

Figure 1: Cross-Tier interactions can get messy!
By implementing a Façade the system becomes much simpler as shown in Figure 2.


Figure 2: Cross Tier Interactions with a Façade Object
Not only is this aesthetically more pleasing but, obviously this is a much more robust design.
Notice that the Presentation Tier objects no longer need detailed knowledge of the individual components of the middle tier. Instead they only need to know how to access the Façade object which is then responsible for controlling all further interactions within the middle tier. This achieves a weakly coupled state that, in turn, means that we can change things at will in the lower level sub-systems without needing to make corresponding changes elsewhere. Providing that the interface exposed by the façade object does not alter, then its internal facing methods are the only places that changes to lower level systems can ever affect.
When should we use a Facade?
The purpose of the façade is to provide a simple interface to a complex system. Although most of the examples in pattern literature talk about ‘sub-systems’ you must remember that a design pattern is not dependent upon the implementation but on the design problem which it addresses. So while it is may not be very common for us, as FoxPro developers to build “complex sub-systems”, we often create complex objects which expose many methods in their interface! So whenever we find ourselves having to call multiple methods on the same object we really should be thinking in terms of implementing a façade.
The usual scenario occurs when we have to run some multi-step process or calculation. Usually our first instinct is to add the relevant methods directly to the object (usually the form!) that requires them. When this gets messy we may provide a ‘control’ method to call the various steps in the correct order and to evaluate results and act accordingly. The resulting code looks something like this:
LPARAMETERS tuInval
llStatus = This.CheckParameters( tuInval )
IF llStatus
  luResult = This.FirstStep( tuInval )
  IF VARTYPE( luResult ) = “N” AND NOT EMPTY( luResult )
    llStatus = This.SecondStep( luResult )
  ELSE
    llStatus = .F.
  ENDIF
ENDIF
RETURN llStatus
This will work perfectly well, of course, until some other object requires access to the code. Now we have a problem. The next stage is to abstract the code from our form and create a stand-alone object, but now we have to make multiple calls to that object – and from more than one place in our application – sound familiar? It should, because this is precisely the scenario that the façade pattern addresses.
Our object should not actually expose all of its methods, instead it should expose a façade consisting of just a few very simple methods which then call other methods internally as needed. By designing things this way we achieve several things:
·         The code can be called from any object·         The process detail is hidden, callers only need to know the exposed interface·         Changes to the implementation are confined to the façade object
How can we implement a façade?
The example given here is for a converter class, defined in Visual FoxPro, that can be implemented directly as a VFP application object, or as a COM component. The interface for this object is extremely simple, and consists of just TWO methods:
·         Convert             Which expects three parameters, a value and the appropriate From/To codes. This method returns the converted value or an error code
·         GetErrors           Interrogates the object’s errors collection and returns either a VFP Error Object or a COM exception, depending on how the object was instantiated
In fact the object has a number of methods which are defined as “Protected” so that they do not even appear in the COM interface, and can only be called internally.
The first thing that this method does, is to pass the received parameters through a validation method to ensure that they are of the correct (expected) data type. We are not concerned, at this point, if the values are meaningful, just that they are expected. Since this method is the only entry point, once we have checked the parameters, we can assume that they are correct in all other places because the only way that values can be sent to another method is from this, or a subordinate, method. This is an additional benefit of the façade!
  *** First thing to do is to ensure we have From/To parameters
  IF NOT .ValidateParam( tuConvFm, "C" ) OR EMPTY( tuConvTo )
    lcErrText = "Invalid 'From' Parameter" + CRLF
  ENDIF
  IF NOT .ValidateParam( tuConvTo, "C" ) OR EMPTY( tuConvTo )
    lcErrText = lcErrText + "Invalid 'To' Parameter" + CRLF 
  ENDIF
  *** And that we have a value too
  IF EMPTY( tuInpVal )
    lcErrText = lcErrText + "No input value passed" + CRLF
  ENDIF
  *** Check the results so far
  IF NOT EMPTY( lcErrText )
    ERROR lcErrText
  ENDIF
Next we need to try and figure out what method we need to call. This is the second direct method call, and the method called returns the name of the conversion method we want, based on the ‘from’ parameter. One of the “rules” I have implemented is that both “From” and “To” measures must be of the same type (you cannot convert a temperature to a length for example).
  *** Now we need to decide what method to call, using the From Parameter
  lcMethod = .GetConv( tuConvFm )
Finally we execute the relevant conversion and get the result
  *** Now just handle the conversion
  luRetVal = EVALUATE( "This." + lcMethod + "( tuInpVal, tuConvFm, tuConvTo )")
This entire block of code is enclosed in a TRY… CATCH so that any error, either here, or in a subordinate method, is caught and sent to the LogError() method for access when needed. The return value is either the converted value, or NULL and it is, of course, up to the client object to determine what to do next.
Façade Pattern Summary
As you can see the façade offers us a lot of benefits as developers by providing us with a methodology that avoids tight coupling and, at the same time, promotes better encapsulation and isolation of code so that the impact of changes are minimized.
I illustrated the façade pattern by using an object dropped on to a form and named explicitly at design time and the façade object also contained the actual code to be implemented. However, there is no absolute reason to do it this way. The façade object could simply have been a “gatekeeper” to a host of other objects and, using an implementation of the Strategy pattern, could instantiate the required object for a task at run time. Remember, patterns can be (and usually are) combined in order to solve real design problems.
Published Sunday, January 21, 2007 10:02 PM by andykr

No comments:

Post a Comment

Writing better code (Part 1)

Writing better code (Part 1) As we all know, Visual FoxPro provides an extremely rich and varied development environment but sometimes to...