|
|
Designing Distributed OO Applications in VisualAge for C++By Dale Nilsson, IBM
The motives for using a distributed design are varied. A distributed design gives you much more flexibility in deploying your application. You may not know the size of the client systems where the application will be running, and memory and disk constraints could be crucial factors for the application to run. A distributed design allows application executables to be easily split between the client and a server. The application objects can be concentrated on a fat client to improve performance, or they can be centralized on the server to permit thin clients to use the application. Traditional 3rd generation languages like C and COBOL can be fairly difficult to break-up into pieces and allow functions to be distributed. Third generation languages are procedural and inherently are more monolithic in design. This is a pretty fancy way of saying that applications written in 3rd generation languages tend to be large systems with roughly defined interfaces if any. This doesn't mean that you can't make a distributed application using a 3rd generation language, rather that Object-Oriented programming is better suited for this purpose do to its basic characteristics. A good OO design is the start of a good distributed OO design. The trick is to isolate common loosely coupled classes that will allow for splitting function between a client and server(s) in your application. One of the key tests of a good distributed design is the ability to easily move pieces of the application to other machines. A key aspect to Object-Oriented software is encapsulation, the hiding of data within a class and providing a defined interface to access the data. Encapsulation helps you to separate the functions of an application so it can be distributed. The Visual Builder in the VisualAge products is a good way to illustrate some of the design alternatives. You can define the interfaces and visually construct relationships between the classes. It is important to note that you should not use the Visual Builder as a design tool. It is an implementation tool and has no functions for analysis and it is not simple to redefine interfaces. Viewing the classes in the Visual Builder is much more illustrative than reviewing source code. Even with encapsulation, you don't get a good OO design for free. You could develop an OO application with one class containing all the data and methods for the application. The classic Adder application as shown in figure 1 is a great example of this design. As you can see, all the logic is bound to the user interface. This design can be done in OO languages, but it is really not the preferred way to design good OO applications. The user interface and the logic are tightly coupled. In fact, the code is imbedded in the user interface. This application will work correctly, but it will be a maintenance nightmare and the only reuse you can get is through Mr. Clipboard.
Figure 1 The first step in improving this design is to separate the user interface or 'view' code from the logic or 'model' code. In figure 2 you can see a separate Calc class which has the add method and 3 data attributes. This separate class helps for a number of reasons. First, you can reuse it in a number of applications, and you don't need to recode it. This design principle is a fundamental benefit of the VisualAge Visual Builder supporting the different languages. The Visual Builder is well suited for designing the user interface classes and the part interfaces for nonvisual classes. This design is not only for use with the Visual Builder, you can achieve the same design by coding the old fashion way, by coding these classes in an editor.
Figure 2 Now that the application has a separate Calc class, this class can be compiled and built in a separate executable DLL. This DLL can be moved to a server, and at runtime, it can be invoked assuming the appropriate communication software is working. Although this is a very basic example, it also illustrates a key feature in the Open Class notification framework. The notification framework is extensively documented in the online book 'Building Parts for Fun and Profit.' The framework providers for Observers and Notifiers, and the Open Class controls are Notifiers because they subclass INotifier. Events and changes to data attributes send notification messages. In some cases these notification messages can be excessive and need to be changed. In figure 2, each of the pushbuttons calls a method in the Calc class for the appropriate math function. The Calc has 3 attributes (num1, num2, and result) that hold the inputs and out of these functions. This is a good design for tightly coupled classes, but it is important to remember that there are performance considerations for the attribute to attribute connections. Every time a character is typed in one of the entry fields, this information is transmitted and received by any class that needs to use it. This behavior is usually not worth the performance overhead that is causes. For small applications the overhead is negligible, but for larger applications with many classes and a lot of layering, the performance will be noticeably degraded. The Calc class does not need to have a tight coupling with the Adder view class. In fact, most real application calculations require much more data which could be gathered from a number of sources. To decouple the dependency, you need to define methods in the Calc class that accept parameters as shown in figure 3. You can have methods with no parameters and complementary methods that use parameters. This will allow you to use the class in both tightly coupled and loosely coupled implementations. Defining methods with parameters is much more traditional for typical C and C++ applications, and it will enable the application to be distributed and work with acceptable performance.
Figure 3 This simple design can be easily expanded, and it scales very well for larger applications. You may have a large number of User Interface classes and Model or Logic classes that can be combined to form your application. A good example is the data access classes generated from the Data Access Builder. These classes are mapped from tables and views of a database and can frequently access a database on a server. Good candidates for a distributed design are those functions that most likely will reside on a server. A very good example of this is any database or persistence access classes. These classes can be used without being tightly coupled to the user interface, and more than likely will be accessing data on the server. It makes good sense to save room on the client disk and memory. By keeping these classes on the server, you need to keep the executables relatively small. One big data access DLL on the server that is invoked when any data is needed) would defeat the some of the benefits of a distributed design. What are bad candidates for distributed objects? Functions that are tightly coupled with data dependencies are not good candidates for separating to achieve a distributed design. However, you may want to separate these into classes to achieve better reuse or maintainability. The methods used in a user interface to enable and disable controls is tightly coupled to the user interface and should have good runtime performance. This is a good example of function that should not be separated for the purposes of achieving a distributed design. So in figure 4 you can see two new nonvisual classes incorporated into the Adder application. The Database class is a great candidate for a distributed object. It is very loosely coupled to the other classes in the application and can be easily distributed. The ScreenMgr class is tightly coupled to the user interface both functionally and for performance reasons. So this is obviously a bad choice for being a distributed object. In real life, the classes you use will not always be as easy as this. So you should use experiments, iteration, and peer reviews to determine if specific classes in you application are good for distribution.
Figure 4 How should you determine these dependencies and the coupling of the classes? Well I hate to use the 'D' word, but a little up front design goes a long way. And a few use cases will help a lot in making sure that the application will meet the users needs. Also a dash of common sense and of course a bit of user input wouldn't hurt either. To summarize the points covered, designing distributed OO applications gives you more flexibility when deploying an application. In a distributed design, you will inherently have more classes and some associated overhead, but that is the price you must pay for a more flexible design. In order to achieve a distributed design, you need to separate the model and view classes and make sure you implement methods with parameters to complement methods that do not require parameters. Some Object-Oriented application designs aren't well suited for a distributed implementation because they are user interface intensive or the functions are tightly coupled. There are many reasons why these application designs became what they are, but it really doesn't matter. The key thing to remember is that you can dig into the design and use some of the design tips to make it a distributed design. It may take a few iterations, but the resulting distributed design will be a big improvement, and it will provide much more flexibility for deploying the application. DCE, DCOM, DSOM, and VisualAge are trademarks of their respective companies. Enjoy the article? Subscribe to Eye on Objects! |
|
Dale Nilsson is a Senior Software Consultant with IBM VisualAge. He has been programming software since 1976 using a number of different programming languages using PCs, minis, and mainframes. He has experience working with customers and vendors throughout the United States, Europe, Asia, and South America. Dale currently works with customers providing software consulting and education, technical presentations, and application design using Visualage for C++ and VisualAge for Java. He is also an Advisor and Contributor to the VisualAge Certification program. |
|
![]() |