Intent
Encapsulate business logic using a “controller” class to become the primary entry point from which all business logic (usually of a specific business category) will be contained and/or driven. Provide Web services with single entities to call directly.
Problem
For this pattern, probably the simplest of all mentioned patterns in this book, the problem solved is also simple. When developing Web services in .NET, developers may immediately get the tendency to begin placing business logic within the code directly behind the Web service class provided by VS.NET. This includes any Web methods added to a Web service. The problem here is that, as you may already surmise, “cluttering up” this section with business rules and complex logic can soon become very difficult to manage. Another problem with this sort of “develop before design” approach is that if you desire to reuse those services elsewhere, it will always force the calling client to go through the Web service to do it. The architecture actually may “require” that all back-end business functions be called from a single entry point, such as a Web service. This is probably due to security and control. However, this may not be the most efficient means of invoking business services. Those who have already been developing Web services realize that there is a performance penalty when invoking a business function through a Web service if called as a standard Web service client.
To provide the “best of both worlds,” that is, to provide an optional means to force all traffic through a Web service while also allowing other means of invoking controlled business functions, a Service Façade should be used. The Service Façade, like a traditional façade, simply provides a “controller” object to expose all public “callable” business functions to any external clients. The Service Façade becomes the server to the actual code directly behind that of the Web service and its Web methods (Figure 4.7). Instead of cluttering the implementation directly behind the Web method, this simply delegates calls to the appropriate Service Façade object. This also provides another means of invoking the business functions without forcing the client to go through the Web service or act as a Web service client. The Service Façade could be called from a standard ASP.NET implementation or another server component.
Figure 4.7. Service Façade implementation class diagram.
The difference between a traditional façade pattern and a Service Façade is “architectural,” meaning that the Service Façade must take into account the possibility of both Web methods acting as a client to the façade and other non–Web-service clients. This is implementation-specific. For example, exceptions thrown from the Service Façade should take multiple clients into account, as well as provide a Web service-friendly error-handling mechanism. In some cases, you should avoid throwing exceptions altogether or in some designs do so when transactions are logged. The point is that Web service clients may need to be taken into account at this level.
Forces
Use the Service Façade Pattern when:
-
Implementing complex business logic that may be called externally.
-
Servicing multiple clients from a Web service.
-
Code becomes too complex to place directly into a Web service class.
-
The design calls for categorizing business functionality that may contain different means of handing architectural features, such as exception handling, logging, security, etc.
-
Web service class inherits from System.Web.Services.WebService and must also inherit from another base class in order to receive additional functionality, such as when needing to derive from System.EnterpriseServices.ServicedComponent. (This is the case when the controllers become COM+ components, because multiple-implementation inheritance is not supported in .NET.)
Structure
Figure 4.8. Service Façade generic class diagram.
Consequences
-
Eliminates having to place complex logic within the language implementation of a Web service or ASP.NET file directly (aspx or asmx source). Instead of “cluttering up” the source code directly within a Web method, the developer should utilize a Service Façade class. A Service Façade is strictly a façade that coordinates and houses complex business logic for a specific business category.
-
Provides manager for specific business areas. A Service Façade also acts like a traditional Façade pattern in that it manages specific business areas, providing high-level business functions typically exposed to the public. The exposed business functions in this case will be accessible to the Web service. A Web method can be defined for each publicly exposed façade function, or functions can be grouped into single Web method. Using a single Web method was explained in the Service Factory sections in this chapter.
-
Provides an entity in which to house Web service-specific exception handling. When throwing exceptions to external calling clients, the architecture must take into the account the tier that will be directly callable. In the case of the Service Façade, any Web service clients will be indirectly calling the Service Façade because the Web service stands between the client and the Façade class. In order for some clients to receive rich error-handling adjustments, there may need to be adjustments made to the architecture, depending on where the client is located.
-
Provides an entity in which to house Web service-specific parameter passing. Along the same lines as the above point, passing data between tiers physically located on the same machine could be quite different. There may be architectural scenarios, such as when the calling protocol uses SOAP, where changes to the parameter passing scheme need to be made. These architectural adjustments could be housed within the logic of the Service Façade. Neither the callable business object within the system nor the Web service class itself should be cluttered with this type of logic. Doing so will provide a more reusable design.
Participants
-
Service (CreditCardService)— This is any Web service containing Web methods. Each Web method calls a requested exposed business method on the façade. This can be specific methods or simply (as in our case) a single interface method (e.g., Execute()). The Web service simply becomes the direct interface to the Web client. The Web method does not contain any business-specific functionality. The business rules are all delegated to the ConcreteFacade class or any of its optional parent entities.
-
Façade (Same name as implementation)— Base class for any façade classes that act as a controller to any service. The façade, in this case, speaks only the “language” of the business as it publicly exposes high-level business functionality. This simply means that only public interfaces are exposed to its Web method clients. Web service client requests are delegated from a Web method to the Service Façade.
-
ConcreteFacade (CreditCardFacade)— The main implementer of the publicly available business interface. This class could be self-contained or could delegate to other specialized business objects. Most business rules are contained or driven from here, especially those related to packaging data that must be sent back to the Web service client.
Implementation
The beauty of the Service Façade pattern is that is it simple. It requires more forethought only when it begins to provide the facilities to take into account its Web service clients (as mentioned earlier). Such facilities include handling exceptions or parameters in special ways. However, features such as these are implementation-specific. How to design exception handling or data passing is really another topic and is covered in Chapter 2. The Service Façade, however, provides the construct within which to build these features so that once again, the code directly “behind” the Web methods remains clean, and the business services housed by the Service Façade remain reusable. Implementing the Service Façade is very similar to any of the controller or manager classes that I'm sure you have designed in the past.
Keep in mind that the Service Façade, like a traditional façade (GoF), is the driver of publicly available business logic. It should require more forethought if you are designing a more complicated system (no kidding, right?). The point is, if there will be several categories of business functionality, different approaches should be considered. One implementation approach would be to use an abstract class or interface from which to derive each façade. In fact, this is what our example uses. This is certainly not a requirement and shows only one implementation. Another approach is to create a full implementation-inheritable base class for all façades. The choice is yours and depends more on how the Service Façade itself will be implemented. For example, if you building a mission-critical system that must support multiple clients, shared resources, and possible transaction management, then implementing your Service Façade classes as COM+ components may be a wise choice. If this is the case, you should use either a simple interface or a full base class as the parent to your Service Façade. The reason is that .NET does not support multiple inheritance. Deriving from more than one base class is not permitted unless the class you are also deriving from is an interface. If you are a Java programmer, you are already familiar with this rule. Because adding COM+ features requires inheriting from the System.EnterpriseServices.ServicedComponent, you could make the parent Façade class inherit from it, thus gaining this functionality for each Service Façade child class. You could if your parent Façade class was an abstract class and you still wanted to derive from another base class, but it would seem odd and would not (considered by some) be the cleanest of designs. For our example, I use an abstract base class with the option of knowing that this could be relatively easy to change to an implementation base class if I so desired. We could then incorporate COM+ features by using ServicedComponent as its base class. For now, let's just stick with an abstract parent class to the Service Façade (Listing 4.7).
Listing 4.7 Service Façade sample implementation.
public class PaymentFacade : Façade // Façade is abstract { private ProductManager m_oProduct = null; public PaymentFacade(){;} public PaymentFacade(DataSet RawPacket) : base (RawPacket){;} public PaymentFacade(Packet oPacket) : base (oPacket){;} public override DataSet Execute(DataSet dsPacket, bool bCache) { Packet oPacket; // builds the packet from the raw dataset PreparePacket(dsPacket); if (Product == null) { Product = CreateProduct(GetPacket()); if (bCache) { Product.PrepareCache(); } } else{ Product.Packet = GetPacket();} oPacket = Product.DoOp(); // return raw packet back to caller return PreparePacket(oPacket); // this returns a DataSet // from a Packet using the // PacketTranslator } public ProductManager Product { get { return m_oProduct; } set { m_oProduct = value; } } public ProductManager CreateProduct(Packet oPacket) { ProductManager oProdMan; // packet type should have been set during PreparePacket() // in calling DoOp... switch (oPacket.Type) { case Constants.CREDIT_CARD_AUTH: oProdMan = (ProductManager) new Product1(oPacket); break; case Constants.CREDIT_CARD_SETTLE: oProdMan = (ProductManager) new Product2(oPacket); break; default: oProdMan = null; break; } return oProdMan; } // for testing only.. public object SomeOtherBusinessFunction() { //... } }
The Service Façade, once you take away some of the mentioned design options, is really a container with publicly accessible business methods. This example uses a single point of entry into the façade, as was demonstrated in the Service Factory sections earlier in this chapter. This was done to allow the Service Façade not only to be called from within a Web method but also to be used in the factory. This implementation, once plugged into a factory, delegates all specific business details to a Product Manager class (also described in this chapter). The PaymentFacade below is a ServiceFacade in charge of all credit card payment transactions. It can be called by several different Web methods (e.g., CreditCardAuthorize, CreditCardSettlement). Although most of the specific business rules are delegated to other classes, this façade understands one service type—payments. In essence, it is the kernel of the payment system. Using the data from the passed DataSet (e.g., Packet.Type), it will determine which Product class (e.g., CreateProduct()) should handle the incoming transaction. In our example, this is also where the packet is “prepared” and transformed into a more malleable data format, one that the business components of this type can easily work with. As you can probably surmise, this is only the tip of the iceberg. Much more functionality can now be place within the Service Façade. For the PaymentFacade, it would obviously be those features specific to payment processing. The point is that the ServiceFacade is the place to focus any high-level business design. For prototyping reasons, this may also be the place where you begin your conceptual work. It can become the best place to begin “sketching out” a high-level design.
Related Patterns
-
Façade (GoF)
-
Proxy (GoF)