Visual Basic

Meeting Reuse Requirements Effectively

Visual Basic offers a rich selection of methods to achieve effective reusability. As with many things that involve a choice, you can choose either correctly or incorrectly. In a large computer application, an incorrect choice can mean weeks or months of extra effort. Mistakes will also inevitably occur because of the wide range of options available. For example, you can be sure that many Visual Basic programmers will be eager to create custom controls simply because they now can thanks to Visual Basic 5 and 6. A particular problem to watch for is the "gold-plating" syndrome, which occurs when a programmer spends too much time adding unnecessary features. Although such features work, they serve only as superfluous gloss on the application-and worse yet, the time spent fiddling with them can jeopardize your schedule.

The following sections provide an overview of the different methods you can use to achieve effective reuse.

Code Reuse Using Objects

Creating and distributing objects is one of the most powerful means of achieving reusability. An object is a discrete unit of functionality. Object components within Visual Basic can be either internal or external to an application, and they can be shared between applications, as shown in Figure 14-1. External object components have an advantage in that they can be physically deployed anywhere on a network. By strategically deploying object components to maximize resources, you can save possibly thousands of dollars when you consider that a typical development's cost comprises both development and deployment overheads.

Figure 14-1 Applications sharing object components

Inherently, object components are loosely coupled and generic. Each object component in Figure 14-1 is totally self-contained and can be used by any number of applications or components. An object component should have no "knowledge" of the outside world. For example, if you have an object component that contains a method to retrieve a list of customers for a given criterion, that method should accept the criterion as input and return the list of customers. It is up to the caller, or client, using the object's, or server's, method to display or process the results. You could code the object's method to fill a list of customers on the form, but that object would be tied to the particular interface component on the form. If you wanted to reuse the object's method in another application, you would need to have an interface component of the same type and name on that application's form. The object would therefore be tightly coupled because it "knew about" the interface.

From a business perspective, object components provide a way of controlling and managing business logic. Business logic consists of rules that can change to meet the needs of the business. By placing such logic in object components and locating these on a server, you can make changes instantly available with low installation overhead, especially since polymorphic (multiple) interfaces in Visual Basic 6 allow you different interfaces within the same component. For example, if a bank were offering an additional 2 percent interest to any customers with over $10,000 in their savings accounts, the functionality could be specified in an account calculations object, as shown in the following pseudocode:

Procedure Calculate Monthly Interest For Customer Cust_No
      High_Interest_Threshold = 10000
      Get Customer_Balance for Customer Cust_No
      Get Interest_Rate_Percent
      If Customer_Balance < High_Interest_Threshold Then
          Add Interest_Rate_Percent to Customer_Balance
      Else
          Add Interest_Rate_Percent + 2% to Customer_Balance
      End If
  End Procedure

In this example, the special offer might have been an incentive that was not anticipated when the application was originally designed. Thus, implementing the functionality in a non-object-component environment would probably involve quite a few additional steps:

  • Adding a high interest threshold field to the database
  • Adding to the maintenance functionality to amend the high interest threshold
  • Amending the monthly balance calculation formula to include an additional calculation
  • Shutting down the database to make changes
  • Rebuilding the application EXE file
  • Testing and debugging
  • Reinstalling the application on the client PCs

As you can see, a relatively simple change request can involve a lot of time and money. Using an object component design, you can drastically reduce the amount of effort required to implement such a change. To make the same change in an object component system requires slightly less effort. The differences are explained here:

  • The account calculations object calculates interest payments, so locating the code module to change will be fairly simple.
  • Because only the account calculations object requires a change, only this component needs to be rebuilt. With this type of design, the object components are most likely to be installed on a server so that only one copy of the object needs to be reinstalled. The object can also be made to work in the new way for some applications and in the old way for other applications without any of the applications changing at all.
  • Testing will be limited to the object that has changed because its functionality is completely encapsulated.

This very simple example shows how objects-in this case, distributed objects-offer a major advantage in terms of maintenance. A good example of how shrewd object distribution can save money is one that Peet Morris often uses in his seminars:

If you imagine an application that utilizes a word processor to print output, by installing the print object and a copy of the word processor on the server, each user can access the single installation for printing. Whether you have 5 or 500 users, you still need only one copy of the word processor.

Another advantage of distributed objects is that you can install object components on the most suitable hardware. Imagine that you have several object components, some that perform critical batch processing and some that perform non-critical processes. You can put the critical tasks on a dedicated fault-tolerant server with restricted access and locate the non-critical processes on a general-purpose server. The idea here is that you don't necessarily need all your hardware to be high specification: you can mix and match. The capability to move object components away from the desktop PC means that the client or user interface code can be much smaller and won't require high-end PCs to run. With distributed objects, it's a simple enough task to relocate object components so that you can experiment almost on the fly to determine the best resource utilization.