Integration and Extension at the Business Logic Layers
There are many technical approaches to creating systems that can be integrated and/or extended. This section draws from my experience creating the necessary architectural infrastructure for enterprise class software systems. The techniques are easily adapted to other kinds of application architectures. Refer to Figure 8-3 as you read this section and the next one.
Figure 8-3. Integration and extension techniques
Technologies and Locus of Control
Before talking about integration or extension approaches, it is important to distinguish between the technologies that are used to create these features and the locus of control when performing the integration of extension.
The technology part is easy. A well designed services architecture and/or design model should be able to support whatever technology is required by your target market. In practice, this means that you will be supporting multiple kinds of integration technologies. More modern technologies, such as Enterprise Java Beans or Web services, may need to sit alongside more traditional technologies, such as COM or plain old C libraries. You may even be required to support the same functionality with slightly different implementation semantics, as when you are required to support multiple standards that each address the same functionality but have not been unified (such as the cryptographic standards PKCS11 and the Microsoft CAPI).
The locus of control question is a bit more challenging. In general, either the caller is in control or the system is in control. When the caller is in control, they are most likely treating your application as a service that creates and produces a result. The call may be blocking or non-blocking , and you may or may not provide status. Ultimately, though, the caller is in control.
When the system is in control you're almost always using either a registration or callback model in which the caller registers some aspect of functionality to the system. The system then invokes this functionality at predefined events. Ultimately, the system is in control (or should be). These two approaches are discussed in greater detail in the next sections.
Integration through APIs
Application programming interfaces (APIs) expose one or more aspects of functionality to developers of other systems. They are based on the idea that the other developer is creating an application that is the primary locus of control; your system becomes a set of services accessed through any means appropriatefor example, a library, such as C or C++ library; a component, such as a COM, JavaBean, or Enterprise JavaBean (EJB); a Web service; and/or a message-oriented interface. The use of APIs is primarily associated with the desire to integrate your application into some other application.
If you have constructed your application according to the principles espoused earlier, it is usually easy to create APIs that allow customers access to your system's functionality. The most direct approach is to expose the services layer first, possibly exposing other layers as required. This is far superior to allowing your customer direct access to your database, which bypasses all of the business logic associated with your application.
Consider the following items as you create APIs:
While C-based interfaces may be the universal choice, every platform has some variant that works best. For example, if you're creating an application under MS Windows, you will almost certainly want to provide a COM-based interface. Other customers may require a J2EE approach and demand EJBs that can be integrated into their application.
Market Segment Preferences
In addition to the pressures exerted on an API by the platform, different market segments may also exhibit preferences for one approach or another. If you're working with innovators, chances are good that they will want to use the most innovative approaches for integrating and/or extending your system. As of the writing of this book, this means providing Web services. In the future, who knows ? Other market segments may request different approaches. You may need to support them all.
In Chapter 2 I discussed the importance of the context diagram for identifying possible partners in creating an augmented product. Your partners will have their own preferences for integration. Understanding them will help you create the integration and extension approaches most likely to gain their favor.
If you have ever been frustrated by a vendor providing a nonsensical API, you should have all of the motivation you need to create one that is sensibly named and sensibly structured. Try to remember that making it easy to use your APIs is in your best interests.
Security and Session Data
Many business applications manage stateful data, often based on the concept of a user who is logged in and working with the application (a session). State or session data may be maintained in any number of ways. For example, in Web applications a session is often managed by embedding a session identifier in each transaction posted to the server once the user has logged in, either as part of the URL or as part of the data in the Web page. If you're using a heavy client (e.g., a Windows client application) you can manage state or session data directly in the client or share it between the client and the server.
Developing APIs for applications that rely on session data is harder than developing them for applications that don't. You have to provide your customers with a means to specify and manage session- related parameters, such as timeouts and security protocols. Depending on how your application works with other applications, you may need a way to identify another application through a user ID so that rights can be managed. You may also need facilities for managing session data as functions are invoked. If your server manages session data through an opaque session identifier, for example, you have to tell your customers not to modify this handle.
Exposing Only What Customers Need
Be careful about liberally exposing all of the APIs in your system. Every one you expose increases the work in creating and sustaining your product. It is also unlikely that every exposed function provides the same value to your customer; not everything is needed. In a complex system, different operations exhibit different performance profiles and make different demands on underlying system resources. Some APIs may invoke complex functions that take a long time to execute and should only be used with proper training. You don't want your customer to accidentally bring the system to a grinding halt through improper API use.
Tarchitects should work carefully with marketects to define the smallest set of APIs that makes sense for the target market. Because there may be many constituents to satisfy , consider defining sets: one (or more) for internal use and one for integration/extension, possibly governed through security access controls. I know of one large application development team that created three APIs: one for the team's internal use, one for use by other application development teams within the same company, and one for external customers. The APIs differed in functionality and performance based on such things as error checking and calling semantics.
APIs Stabilized over Multiple Releases
It can be difficult to predict the APIs needed in the first few releases of a product, and it is rare that you get it right the first time. Be forewarned that it may take several releases to stabilize the right APIs for a given target market.
Clearly Understood Options
Your application may provide for certain features that are simply not available in the API. Stating what canand cannot be done with an API makes it considerably easier for a customer or system integration consultant to determine the best way to approach a complex problem.
Extension through Registration
Registration is a process whereby the capabilities of your application are extended in one or more ways by developers who register a component or callback function with your system. Unlike integration through APIs, your system remains the locus of control, calling the registered component at predefined events. Registration is related to the Observer design pattern or the publishsubscribe models of message queuing systems but is not the same thing. When using registration, your application actually hands over control to the registered component. In the latter, your application notifies other components of events but may not hand over control. A great example of registration-based extension is your Web browser, whose functionality can be extended through well-defined plugins. When the right mime type is encountered , application control is transferred to the appropriately registered plugin. Registration-based APIs include callbacks, listeners, plugins (such as a Web browser), and event notification mechanisms. Consider the following when providing for registration-based solutions.
Define the Registration Model
Provide developers with detailed technical information on the language(s) that can be used to create registerable components, when and how these components are registered, how to update registered components, and so forth. Some applications require that plug-ins be in a specific directory and follow a platform-specific binary model. Other applications require that all components register themselves through a configuration file. Some allow you to change registered components while the application is running; others require you to restart the application to acquire new or updated components. You have a wide variety of choicesjust make certain you're clear on those you have chosen .
Define the Event Model
The specific events available to the developer, when they occur, the format of the notification mechanism, and the information provided in a callback must all be made available to developers.
Define Execution Control Semantics
Execution control semantics refer to such things as blocking or nonblocking calls, thread and/or process management, and any important timing requirements associated with external components. Some applications transfer control to a plug-in to process a request within the same process space. Others invoke a separate process, then hand over control to the plug-in. Still others invoke the registered component as a simple function and block, awaiting the results.
Define Resource Management Policies
All decisions regarding resource management, from provisioning to management and recovery, must be defined. Consider all resources that may affect your application or that may be required for a successful integration, including, but not limited to, memory, file handles, processing power, and bandwidth.
Define Error/Exception Protocols
Errors and exceptions in one application often must be propagated through your API to another application. You may also have to define conversion semantics; that is, what might be an "error" in one application may be an "exception" in another.