` Printed Icetips Article

Icetips Article



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.