`
OOP: Better OOP part 4 2003-04-13 -- Dan Pressnell Newsgroups: comp.lang.clarion,topspeed.topic.oop March 5, 2006: Note that the code is now available at: http://www.icetips.com/downloadfile.php?FileID=59 If you have already downloaded the sample OOP app at http://toolwares.com/oop_sample.ZIP , download it again, because I made some changes. The samples in the app show several things. First, it shows using a template to create a "procedure" where you can enter your code that ends up in the INC and CLW files that your class declaration and definition reside in. Take a look at the properties of the Classes:1 procedure. You can see a place to enter the name of the INC, CLW, and INT files that are generated. You get an embed point for each that you specify a file name for. In the "Class Declarations" embed, I've declared two classes. In the "Class Definitions" embed, I've put the executable code for the classes declared. There is also a check box where you can instruct the template to read the generated INC file and add the needed class prototypes to the Export file at generation time. Take a look at the TeamClassType declaration embed. There is a data queue, and a variable (called "property" in Class lingo). And there are some procedures ("methods") for the class. Below the class declaration, note the structure of the typed queue. The class contains the queue named Q, and it is declared as a reference to that queue type. This is because you cannot declare a queue in place--you must declare a reference to a queue, and NEW the queue at some point. Besides a constructor and destructor, there are methods to GetData() and ExportToCSV(). The GetData method will fill the data queue. The ExportToCSV method will export the contents of the data queue to a CSV file (and for the purpose of this demo, display the contents of that file with NotePad). Before looking at the executable code for this TeamClassType class, let's see how it's used, to get the big picture. SHOWTEAMS procedure =================== The ShowTeams procedure is a "browse" although it is created using the Source Template. Take a look at it. Notice that in the Window structure, the list control has no FROM attribute. When using a queue contained in a class for a list box, you must not use a FROM attribute. Instead, you set prop:from for the list box after the window is opened, as shown in the code. In the procedure there is an instance of the TeamClassType declared, called "tc". The data for the list box is retrieved with the one liner: tc.getdata() After that there is a simple accept loop for window processing. If you click on the "Print" button, the code will call the PrintTeams procedure, passing the class (tc) as a parameter. This supplies the class and the data that is in the class to the PrintTeams procedure, which can use the data that is already retrieved. If you click on the "Export" button, the code will call a method in the tc class, ExportToCSV, like this: tc.exporttocsv('myteams.csv') The important thing to note here is that the ShowTeams procedure knows nothing about how the data is retrieved, and it knows nothing about how it is exported. The class knows, and ShowTeams relies on the class to do its work. To use the functionality of the class, you only have to know how to communicate with it, not how it works. This is the key to reusability with classes. PRINTTEAMS procedure ==================== Notice how the ShowTeams procedure calls the PrintTeams procedure, passing one parameter, the class. The PrintTeams procedure is prototyped like this: PrintTeams PROCEDURE (*TeamClassType pClass) Remember that you can pass an instance of a class around in your program simply by passing the class as a parameter. That is what was done here. The PrintTeams procedure, by receiving the class as a paramter, has access to the class's data as well. This simplifies coding the report code, because the data has already been retrieved. By the way, the PrintTeams procedure show how you can use the ABC PrintPreviewClass easily in your hand coded reports. It also shows how to print from a queue, and the techniqueue I prefer of using a derived GROUP to serve as the source for the report's data, allowing you to specify your own prefix. Similar to the ShowTeams procedure, the PrintTeams procedure doesn't care how the data was retrieved. It knows about the data, because it is contained in the class that is passed, but it knows nothing about the mechanics of the data retrieval, or even the source of the data. PRINTTEAMSENTRY procedure ========================== What if you want to call the PrintTeams procedure on a newly started thread? There is a problem. It is prototyped as having one parameter, a pointer to a class. Clarion will not allow you to use START() with such a procedure. There are tricks with using a STRING as the parameter to pass a class reference to a started procedure on another thread, but then you run into problems with the duration of the class instance and possible GPFs, if the class goes out of scope while it is still supposed to be used. To simplify things, I've made another procedure, the PRINTTEAMSENTRY procedure, which solves this cleanly. The PRINTTEAMSENTRY procedure declares an instance of the TeamClassType class, retrieves the data (with a user selectable sort order), and then calls PrintTeams, just as the ShowTeams calls PrintTeams. CsvExportClassType =============== Go back to the procedure Classes:1, and take a look at the declaration embed where the CsvExportClassType class is declared. The purpose of this class is to export to a CSV file any queue you give it. It can be handy for debugging purposes. (Especially if you load the CSV file in a spreadsheet program. And if you use one of the free Excel packages, you can export directly to Excel and use ShellExecute to open the spreadsheets generated!) Examine the code for the TeamClassType.ExportToCSV method in the Definitions embed. In the data section for that method, a local instance of the CsvExportClassType is declared. That local instance of the class is primed and called to perform the export. Remember that the ShowTeams procedure called a method of the TeamClassType to export to CSV. The ShowTeams procedure knows nothing about the CsvExportClassType, and relies on the TeamClassType to do the work here, too. This is a (perhaps trivial) example of classes working together. (As I previously said, you have small objects, which are assembed into bigger things, which in turn are assembled into even larger things.) To summarize what OOP does for the sample app, functionality is provided in various places that depends on classes. The classes are reusable, which reduces coding, minimizes maintenance and bugs, provides a coherent structure for expansion. As the program expands, any parts that again need the functionality of the TeamClassType do not need to be concerned with how to get the data--they use the class already written for that purpose. Using the TeamsClassType, the program easily displays the data in a browse box, prints a report, and exports the data to a CSV file. That type of flexibility and reusability is what OOP is designed to provide to you if you are willing to make the very small effort to learn it. Also, note that because major functionality is isolated in classes, the class declarations themselves go a long way toward self-documentation. And I haven't had to talk about horses, ducks, cars, or airplanes. :) Next I'll discuss the importance of queues in classes. Dan Printed November 21, 2024, 12:03 pm This article has been viewed/printed 35411 times. Google search has resulted in 45 hits on this article since January 25, 2004. |