Advanced Object Oriented Programming with Visual FoxPro 6.0

The Code Generation Wizard

Both Visual FoxPro Modeling Wizards are compiled into one application (VFPModel.app), which is one of many files you receive when downloading the wizards from the Microsoft Visual FoxPro Web site. The site states that the wizards are for use with Visual FoxPro 5.0. In fact, they were shipped long after Visual FoxPro 5.0 was done, but too early for Visual FoxPro 6.0. For this reason, they work well with Visual FoxPro 6.0.

When using Visual FoxPro 6.0, you should install the Modeling Wizards into the following directory (given that you installed Visual FoxPro 6.0 in the default directory):

C:\Program Files\Microsoft Visual Studio\VFP98\Tools\Modeling

The actual installation process is simple. The setup program copies files only into the specified directory. You can move them to other directories at any time without having to set additional parameters or properties.

Run the Visual FoxPro Modeling Wizards like so:

DO Home()+"Tools\Modeling\VFPModel.app"

This brings up a dialog that allows you to choose the wizard you want to run (see Figure 1). After you run the wizards once, they register themselves in Visual FoxPro as regular Visual FoxPro wizards, and they're available from the Wizard Selection dialog under the Tools/Wizards/All menu item. Figure 2 shows the Code Generation Wizard in the regular wizards dialog.

Figure 1. The launch pad for the Visual FoxPro Modeling Wizards.

Figure 2. The Wizard Selection dialog shows the Code Generation Wizard.

You can also install the wizards in the Tools menu (my preference). To do so, simply call VFPModel.app with "0" as the first parameter. Here's an example:

DO Home()+"Tools\Modeling\VFPModel.app" WITH 0

I added this line of code to my startup program, so the wizards are automatically added to the menu when I start Visual FoxPro. Figure 3 shows the new Tools menu with the installed Modeling Wizards.

Figure 3. The Modeling Wizards as a new item in the Tools menu.

Importing your first model

Before we explore the details of the Code Generation Wizard, let's import a model and generate some source code. To do so, start the Code Generation Wizard using one of the possible starting options I introduced above. Figure 4 shows the first step of the wizard.

Figure 4. In step 1 of the Code Generation Wizard, specify the model and a class destination file (library).

First we specify the model file we want to import. We also specify a default class library where we want to store all the generated classes. (Note that the wizard creates only visual classes. If you wanted to see real source code, you'd have to use the Class Browser's source-generation feature to create low-level source code.) The specified destination file is only a default setting and might be overwritten in a number of places (see below). The library I specified in this example didn't exist, so the wizard automatically created it for me (after I approved it, that is).

Once we move on to step 2, the wizard actually starts to import and analyze the entire model. For this reason, moving from step 1 to step 2 can take some time. Still, it's lightning fast compared to writing all the code by hand. Figure 5 shows step 2 with an imported model.

Figure 5. The entire model has already been imported internally. We can now choose the classes we want to generate and/or update.

The tree shows all the packages we created in our model. Once we select a package, we see all the classes belonging to it. Initially, all classes are selected. However, we can deselect classes if we don't want to import them. As you'll see later on, a lot of additional functionality is hidden in this step (see below), but for now we'll move on to step 3a (see Figure 6).

Figure 6. Selecting a base class for the imported classes.

Step 3a allows us to select a base class for all imported classes. Typically this would be Custom, but you could also select any other existing Visual FoxPro base class. If that isn't enough for you, you can also select any user-defined class.

The selected class will be used as the default parent class for all imported classes. Not all classes will be of the same Visual FoxPro base class, but you can specify this in other places (see below). The class we specify in step 3 will be used only for classes that have no base classes specified and no other parent classes in the model that would define the base class.

Step 3b (see Figure 7) requires choosing some additional base class settings.

Figure 7. Specify base class substitutes to use your own set of base classes.

Step 3b allows you to substitute your own base classes for the default FoxPro base classes for each of the model elements. As we have discussed before, it is dangerous to inherit directly from base classes. In this dialog we can specify that the model use cMyExtraordinary-FormClass for all forms it encounters as it imports the model. To specify base class substitutes, simply right-click on the class you want to redefine and select a new class from the dialog.

Typically, different sets of base classes are used for different projects. Reassigning all those classes every time you run the wizard wouldn't be practical. For this reason, the Code Generation Wizard allows you to create reusable profiles. Once you define a set of base class substitutes, simply click the Save Profile button, assign a new profile name, and preserve the set for later use (see Figure 8). You can define as many profiles as you want.

In well-designed models we'd be done already. The next regular step is the Finish step of the wizard. However, if there are conflicts in the model, we need to resolve them before we move on. I'll discuss resolving conflicts later, so let's assume the model we are importing is flawless. Figure 9 shows the final step of the Code Generation Wizard.

The options in the last step don't influence the way the source code is generated, but they do allow you to specify how the created code is displayed and what other files are generated and updated. The option group on top defines whether the classes are only imported, or whether they are displayed in the Class Browser right away. I recommend starting the Class Browser at once, since you will always want to see what has been created.

Figure 8. The profile manager.

Figure 9. Almost done! The last step of the Code Generation Wizard allows us to set some additional options.

At this point you can also specify that the existing model should be updated, in case you changed anything. This would be important if you had conflicts, in which case those changes would be written back to the model right away. This can be dangerous in some situations, so be careful with this feature (after all, it changes your actual model). No conflicts occurred in our example, so this setting won't have any effect.

The wizard also suggests creating a log file. This is always a good choice. Remember that the wizard touches source code. It can't be bad to know the details of what it did.

As mentioned above, the wizard imports the entire model on the way from step 1 to step 2, so when you click Finish, the wizard only writes buffered data in the specified files. This happens rather quickly. Once this is done, the log file is displayed (if you chose to create one) and the results are displayed in the Class Browser (see Figure 10) if that's what you requested.

As you can see, all classes have been placed in one huge class library and they're all based on the Visual FoxPro base class Custom. This doesn't make a lot of sense for most projects. In the rest of this chapter I'll explain how to create more sophisticated models and how to specify details.

Figure 10. Our first generated class library displayed in the Class Browser.

Selecting model files more efficiently

Visual FoxPro communicates with the modeling tool using OLE Automation. The wizards are smart enough to figure out what modeling tool you are using (Rational Rose or Visual Modeler) and they know how to deal with each tool. If you have both tools installed, the wizards invoke the one you used last. Every time Rose or Visual Modeler shuts down, it adds an entry to the Registry, indicating that it is the standard modeling tool from now on. So if you want to influence the tool to be used, start the tool of your choice and shut it down right away. Then start the Modeling Wizards.

If you are currently working on a model, and an instance of the tool is running, the wizards allow you to use the current model, rather than asking you to select a model file (see Figure 11). This is the option I use most frequently. It makes everything much easier, and it also speeds up the process.

Step 2's secret options

Step 2 looks simple at first sight. It shows all the packages and, once you click on them, all the classes in each package. You can select and deselect classes by simply clicking on them. If you deselect a class, it won't be imported. This feature was implemented to give you the option of leaving out classes that you have already imported and that haven't changed (see below for more information about updating existing code). This is very important because it can take a long time to import a large model.

You might also encounter other reasons for deselecting a class. One would be to exclude classes that are not meant to be implemented in Visual FoxPro. Data or menu objects are typical examples. However, step 2 is not the place to do that. After all, you'd have to do that every time you wanted to update your libraries. It is much better to set these options in the model, where those settings are persistent. (See below for more information about this.)

Figure 11. Rose is running in the background, so we can choose to import the current model.

Step 2 hides quite a bit of additional functionality. If you double-click a class, you get a Class Properties dialog (see Figure 12) that displays properties in the modeling sense. This shouldn't be confused with properties of Visual FoxPro classes. Basically, this is an options dialog for each class.

The General tab contains some basic information such as the class name, base classes, parent class, the class library in which to store this class when implemented in Visual FoxPro, and whether the class should be implemented at all. You can also set these options in the model file (see below).

Figure 12. Class options displayed in the Properties dialog.

The Methods tab (see Figure 13) shows you guessed it all methods of the class and a brief description (if a description was defined in the model). The Properties tab does the same for properties. Thanks to the displayed icon, we also have an indicator of the visibility of the method or property.

Figure 13. All methods of the selected class.

The Inheritance tab gives more information about the inheritance structure. It lists all the parent classes of the class (see Figure 14).

Figure 14. The inheritance structure of our class.

As you might have noticed, there is space for a list of parent classes, but Visual FoxPro supports only one parent class, so this seems to be a waste of space. Or is it? Well, not really. Multiple inheritance might not be allowed in Visual FoxPro, but it is allowed in the modeling tools. For this reason, the wizard needs to be ready to handle multiple-inheritance scenarios. If more than one parent class was defined, they would all appear in this list. See below for more information about multiple inheritance and inheritance conflicts.

If you want to see more information about a class, simply double-click on it to display the class properties. This way, you can work your way up the entire inheritance tree.

The remaining two tabs hold some information about relations to other classes and the written documentation as specified in the model. Most of this information is better viewed in the modeling tool.

Resolving conflicts

Models are not necessarily compatible with Visual FoxPro's object model. Modeling tools have to be able to handle all kinds of object-oriented languages and environments. Some of them support features others don't. In Visual FoxPro, the two main areas of concern are class naming and inheritance structure.

Naming conflicts

Naming conflicts can occur as a result of illegal characters (typically spaces in class names) or Visual FoxPro's case-insensitivity. Both issues are handled differently in other object-oriented languages.

Naming conflicts are automatically identified by the Code Generation Wizard and displayed in step 4a (see Figure 15).

Figure 15. The wizard automatically identifies naming conflicts.

Step 4a shows two lists with items that raise issues. The left-hand list shows classes; the right one shows methods and properties belonging to each class. Red exclamation points indicate immediate problems, while gray ones point out that some properties or methods may have invalid names. Each item also has a brief description that explains the problem that occurred. As you can see in Figure 15, spaces are usually the main reason for conflicts, as well as duplicate class names caused by the fact that Visual FoxPro isn't case sensitive.

You can manually fix naming problems by clicking the item (hold the button for a little while) and typing a new name. When you are done, you have to click the Refresh button. The wizard will then revalidate the entire model. This can take awhile for large models. Checking for conflicts is a non-trivial task. Every change you make can cause additional conflicts, so the entire model has to be scanned and analyzed again. Doing this after every little change would take way too long. For this reason, you can resolve a number of conflicts at once before pressing the Refresh button, which initiates a batch update before the model is checked for conflicts again.

If you don't want to resolve naming conflicts by hand, click the Auto Resolve Conflicts button. The wizard will then do its best to rename the classes in a way that still makes sense to humans. However, you will get better results by changing class names yourself.

Once all conflicts are resolved, the wizard automatically moves on to the next step.

Inheritance conflicts

The only problem that can cause inheritance conflicts is multiple inheritance, which is not supported at all by Visual FoxPro.

There are two different ways to deal with multiple inheritance. In step 2, you can look up class details and see whether you have multiple inheritance problems (see Figures 16 and 17).

Figure 16. The parent class can't be identified because of conflicts.

Figure 17. Multiple parent classes aren't good! Here you can remove them right away.

In the Inheritance tab of the Class Properties dialog, you can remove additional parent classes. However, step 2 of the Code Generation Wizard lets you get away with inheritance conflicts. After all, it doesn't even know about the conflict unless you look up the details, and that's okay. Resolving conflicts isn't why step 2 was created in the first place. Step 4b was created to handle this (see Figure 18). You won't get past this step unless all inheritance conflicts are resolved.

Figure 18. Resolving inheritance conflicts.

In step 4b, all classes that have inheritance conflicts are pointed out to you. Once you select a class, the right-hand list shows all parent classes. You can now simply deselect the classes you don't want. Once all the conflicts are resolved, the wizard automatically moves on to the next step.

Unfortunately, resolving inheritance conflicts isn't as easy as removing one (or more) of the parent classes. You might be able to satisfy the Code Generation Wizard, but you most likely won't be able to create a working set of class libraries. Usually, multiple inheritance is designed for a good reason. By simply removing parent classes you also remove functionality that is likely to be substantial to the class. Therefore, you severely damage your model. I suggest stopping all attempts to generate code as soon as you encounter inheritance conflicts and going back to the drawing board to redesign your model!

Setting Visual FoxPro options in the model

Setting options in the Code Generation Wizard is cumbersome. Microsoft realized that as well and gave us the ability to set Visual FoxPro options right in the modeling tool, whether it is Rational Rose or Visual Modeler. Figure 19 shows the VFP page of the Class Specification dialog in Rational Rose.

This might surprise you, because after all, neither Rational Rose nor Visual Modeler are Visual FoxPro-specific tools. Fortunately, both tools are quite extensible, which allowed the Visual FoxPro team to modify the Class Specification dialog in a generic way. The additional options are stored in a property file (see below).

Understanding property files

Property (.pty) files allow you to add new properties to Rational Rose or Visual Modeler items. These properties are not properties in the Visual FoxPro sense of the word, but they are additional options that can be stored with any item.

Figure 19. Visual FoxPro-specific settings in the Class Specification dialog of Rational Rose.

There are three property files that ship with the Visual FoxPro Modeling Wizards: Rose.pty, Msvm.pty and VFP.pty. All three files are essentially the same because they contain additional options specific to Visual FoxPro. However, Rose.pty and Msvm.pty also have options for Visual Basic, and in the future might include options for other Visual Studio members. Other than their names, the files are identical. They're named differently so that Visual Modeler users won't have to use a file called "Rose" and vice versa. The VFP.pty file contains only Visual FoxPro options. If you plan to implement your app in Visual FoxPro only, you can use this property file.

To set a property file, open the Tools menu, select Model Properties and then Replace or Add. Now select the property file you want to use. In Visual Modeler, the menu item is confusingly called "Visual Basic Options."

Base class settings

One Visual FoxPro option you can set is the base class. The option is called "VFPBaseClass." When you click on this item, you'll see a combobox with all Visual FoxPro base classes. Simply select the base class on which you want the current class to be based.

You don't have to specify the VFP base class for every single class you use. Whenever a class is subclassed from another class in the model, it will automatically inherit the class's base class. Additional settings made in the options will be overwritten by inherited information. All base class settings you define in the model will overwrite defaults you specify in the Code Generation Wizard. This allows you to generate different kinds of classes.

You cannot specify your own classes in the model. If you need to do that, select a Visual FoxPro base class and base class substitutes in the Code Generation Wizard (see above).

Implementation-specific settings

You can also specify a couple of implementation-specific settings right in the model. Purists might point out that this kind of information shouldn't be stored in the model, and they have a point. However, keep in mind that this information is only in addition to the regular information and does not influence the implementation in other languages, tools, or any other aspect of the model. Typically, this information is added when the model is done, so it doesn't influence or clutter the actual design.

First of all, we can specify whether a class should be implemented in Visual FoxPro at all. This is done through the VFPImplementation property, which is either True (default) or False. If you specify that a class is not supposed to be implemented in Visual FoxPro, the wizard will ignore it. However, the class will still show up in step 2 and you could force the wizard to implement it. This might sound stupid, but sometimes it's important. A typical example would be a class that was incorrectly defined as a non-VFP class. Nevertheless, that class might have a number of subclasses that are supposed to be implemented, but obviously those classes would not work without their parent class, so the wizard (correctly) refuses to import them. This scenario might sound somewhat constructed, but I encounter it all the time. I'm glad I can simply overwrite the mistake made in the model.

If a class is supposed to be implemented in Visual FoxPro, you can specify a class library using the VFPClassLibrary property. Again, this setting overwrites all defaults specified in the Code Generation Wizard.

Updating existing libraries

Rome wasn't built in a day and neither are object models. However, customers seem to expect entire applications to be built in this timeframe, so in order to save time, people start to implement while they are modeling other areas of the system. That's fine.

Unfortunately, while continuing to model, you might also find that parts you've already implemented have changed. The Code Generation Wizard allows you to update existing source code, which might scare you. After all, an automated process is messing with your sources! Fortunately, there isn't a reason to be nervous. The wizard only adds new items to the system. It will not touch your actual code or remove parts that are not in the model. If it finds properties or methods that aren't in the model, it simply assumes they are implementation details and leaves them alone. Of course, this might leave things in the source code that were supposed to be deleted because the model changed. If so, you have to delete those items manually because the wizard will not do so. Another scenario it will not handle correctly is the relocation of classes. If you move classes to different libraries, the wizard will create new classes in new libraries, but it won't remove existing ones from their old locations. Again, this is a task you'll have to do manually. The danger of breaking existing code is simply too great.

Категории