![]() |
Jim Ruehlin
(jruehlin@us.ibm.com) After reading this paper you'll have an idea of how to create your own reusable framework using patterns and IBM Rational XDE 2003. Abstract Note: All models and code are described using XDE v2003 for .NET. A framework similar to the one presented here could be created for the J2EE environment. Code samples are written in C# so they should be clear to any C++ or Java programmer. Reusable architectures The introduction of object oriented programming in the mid 1980s in the form of commercially viable languages such as C++ (Smalltalk was around earlier but wasn't widely used in business environments) directly supported code reuse through classes. Some important, measurable gains in reuse were achieved, but the predicted "big leap forward" in productivity didn't happen as hoped since developers often didn't have any way of determining which classes should be reused. Certainly some code could be reused, making the writing of future code faster and more reliable. But it wasn't until the advent of visual modeling and code generation tools that practitioners began to see that reusing design — concepts and ideas — provided greater economic return than reusing code. They realized that the benefits of reuse at an architectural and design level would provide exponentially more value. Now the blacksmith analogy is more powerful. With the invention of design patterns, the idea is to reuse designs since it's easy and inexpensive to generate code from design models. Now, instead of reusing nails, we're reusing foundations and load-bearing walls like pieces of a pre-fabricated building. We're no longer homebuilders, we're home designers. Instead of getting dozens of your neighbors to pound boards together to build a barn, you can now buy the walls and roof and have a few workmen assemble it in a few hours. So it is with architectural frameworks. Why not start out with 20 percent, or 30 percent, or 60 percent, of your architecture already in place? Why not use the same architecture from application to application, making it easier for software engineers to work with successive applications? Microsoft did this when they created the MFC library. Sun did this when they came up with Java and the J2EE standards, and Microsoft is trying doing it again with .NET. It's simply easier, faster, less expensive, and more reliable to build your Web application on J2EE then it is build a Web application from scratch, like they did in the '90s. In other words, a framework like J2EE provides economically significant reuse for building Web applications. "Good, Fast, Cheap: choose two" is an old engineering koan. One of the three must be sacrificed for the sake of other two. But reusing architectural frameworks is a way to reduce the risk and get better at all three. Rapid architectures In this article we'll use design patterns to rapidly create a framework, which in this case is a pattern of patterns. Applying these patterns in XDE will generate the bulk of our code, so most of the code that implements the framework will be untouched by human hands. Even if this were the only benefit of using patterns we'd still have more reliable code. There will be a few hand-written lines of "glue code" to string things together. In the end we'll have a 3-tier architecture that processes business logic in a repeatable, predictable, and robust (component based) framework. This framework can be reused (applied as a single pattern rather than re-typing code) to create other application architectures even faster. Developers who work on this framework once will not need to go through a learning curve on subsequent applications that use the same framework. And improvements or fixes to the architecture can be rapidly propagated across applications by re-applying patterns rather than hand-modifying code multiple times. Processing business logic First we'll look at the framework's behavior. Figure 1 is a sequence diagram that describes how the framework will process business logic.
Business objects are colored in red. User interface objects are blue. The sequence starts when a user requests a command (an application function) to be executed by interacting with a user interface object, in this case the main form of the application. The form is part of the presentation layer so it doesn't implement any business logic. But it knows enough to pass the request to the business layer. The form will do this through an interface to the business logic layer that is realized by the BusinessLayerProxy class. This is a controller class that has the responsibility of managing the execution of the business logic. The BusinessLayerProxy creates or accesses an instance CommandFactory. The CommandFactory is a Singleton, a class that is guaranteed to have at most one instance (object) of itself in the application. Using the Singleton pattern we guarantee that no matter how many times the BusinessLayerProxy tries to create a CommandFactory, only one instance will exist. CommandFactory already knows if it has an instance, and if so doesn't create another instance. BusinessProxy then asks CommandFactory to create the desired business logic object (command) so the business can be executed. This is CommandFactory's only job — to know how to create the appropriate business logic. In our example application, an integer ID is passed to CommandFactory so it can create the correct Command object. This simple tactic has the advantage of being easy to understand for the purposes of this article. In real life we may need a more robust (and complex) way of identifying which business logic needs to be created. Using other patterns to identify the business logic (such as Abstract Factory or Factory Method) could reduce maintenance overhead and increase usability. All business logic is encapsulated in Command objects by applying the Command pattern. CommandFactory creates an instance of the desired business logic and passes an interface to the command back to the BusinessLayerProxy. BusinessLayerProxy never knows what command it's executing, only that it's executing some business logic through the ICommand interface (notice the return value from CommandFactory). Once the BusinessLayerProxy has the interface it executes the command via the There are some good OO design practices being used in this example. Each class should do just one thing and do it well, so the BusinessLayerProxy manages execution flow, the CommandFactory knows how to create commands, and each command class encapsulates — or is the only gateway to — the logic for a single application service. The business layer is only accessible via the business layer interface, isolating the presentation layer from changes in the business layer. These applications of encapsulation, modularity, and polymorphism are implemented by the patterns. We can leverage these good design practices for free by taking advantage of XDE's pattern expansion capabilities. The framework
The 3-layer Pattern shown here is what the pattern looks like before it's applied. Javascript is used as a placeholder for the parameter name. The Javascript is replaced with the actual package/subsystem name when the pattern is applied, for instance replacing the text "
The application's main form, "Form1," is in the Presentation layer. Since Form1 is part of the Presentation layer it must access the business layer through its interface (see Figure 4). There are three message handlers (the ...
After synchronizing the code for the model shown in Figure 4 we can access business logic through "theBusinessLayer". The "glue code" we need to write for Form1 is just a line in the message handler to request the business layer execute the appropriate logic. The ID "1" is passed to the business layer so the proper business logic can be identified. Now that we've accessed the business layer we need to create the CommandFactory class. We do this by applying the Singleton pattern and creating a new class, CommandFactory, as the singleton. The Singleton pattern is shown in Figure 5.
The text "Singleton" is replaced with "CommandFactory" when we apply the pattern. "Client" becomes "BusinessLayerProxy". Now the BusinessLayerProxy has access to the CommandFactory. We need to identify where the business logic will live using the Command pattern, create that command in CommandFactory when the BusinessLayerProxy requests it, and finally execute that logic in BusinessLayerProxy. A simplified version of the Command pattern is shown in Figure 6. All concrete commands — all business logic — realize the Command interface. The
Every command (business logic) is added using the Command pattern. A new ConcreteCommand will be created each time the Command pattern is applied (e.g. the FirstCommand class), and the other three classes are always reused. This provides a very predictable way to add, modify, and debug business logic. We write a few lines of "glue code" to hook the CommandFactory to the BusinessLayerProxy. We only need to do this once. We also write a couple of lines of code to access FirstCommand from CommandFactory. We'll need to do this each time a new command is added due to the simplified architecture we're using in this example. We added code to Form1 to access the business layer. Here's the code in the BusinessLayerProxy to request and execute the business logic:
Here's the code we write in CommandFactory that calls the appropriate business logic: The last thing to do is write the custom business logic in the A pattern of patterns can be created so the framework can be transported and re-applied elsewhere (see Figure 8). In XDE you can create this pattern of patterns and export it as a Reusable Asset Specification. Other projects can import the framework and re-use it by applying the entire framework as a single pattern, or applying the patterns individually.
Improvements Logging capabilities can be easily added to this framework. Snippets of parameterized code called "code templates" can be added, or "bound" to class operations in XDE by right-clicking the operation. Binding a code template to an operation in a pattern will cause that code to be generated when the code and model are synchronized. Code that logs information to a file can be added to the A framework could even be created that serves as an abstraction layer on top of J2EE, .Net, or other industrial strength architectural frameworks. Developers would create applications using the custom framework, which in turn would create classes appropriate to the underlying architecture in a way that's largely transparent to the designer and implementer. This last example could be very useful to organizations running applications on architectures from multiple vendors, but it would be a serious undertaking. Summary
|
Rapid Creation of Reusable Architectures
最新推荐文章于 2024-11-03 00:02:32 发布