Service Fa §adeIntentEncapsulate 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. ProblemFor 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. ForcesUse the Service Fa §ade Pattern when:
StructureFigure 4.8. Service Fa §ade generic class diagram.
Consequences
Participants
ImplementationThe 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 : Faade // Faade 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
|