|
The Joys of Reusable Code : Making your own Function Library
By Bruce Johnson
|
|
|
|
|
|
This article was first published in
Clarion Online Volume 1, issue 1 and is reproduced here with permission.In this column over the months we will explore the various ways in which
the Clarion environment promotes code reuse. Apart from the obvious way
of using templates, a route far too few developers take advantage of, there
are also the more traditional methods of function, and class, libraries.
The benefits of reusing code are obvious. For every application you do you
can reuse the generic functions that you created for the one before. This
saves time, improves the features in your program, and generally makes for
more cost-effective programming. As your libraries grow it becomes easier
and easier to lay the framework for more sophisticated applications, without
any effort at all. Most third party products employ this philosophy, but
in this column well explore how you can take advantage of these features.
And before you ask, no, you dont need to be a Clarion expert either.
In this first article I will walk through the steps youll need to
do in order to create your own function library. You can use this library
as the basis of your own libraries. In later articles well delve into
the various forms your library can take, and well even remove some
of the mysticism from the template language and get you going writing your
own templates.
There are different types of functions, and ideally, for convenience, you
should separate the different types of functions into separate libraries.
For example a library like Secwin contains only security-related functions.
Ezhelp contains only help related functions etc. In this article were
going to create a general-purpose library. You can use this as the basis
of as many libraries as you like. In my own personal library I include all
those simple functions that just dont seem to fit in anywhere else.
The first big decision to make is if a library should be stored as an APP
file, or as a project. Both have their advantages, but in essence an APP
file should be used for functions containing screens and/or files, and a
project should be used for the rest, which are essentially hand coded functions.
The advantage of projects is that excess code is kept to an absolute minimum.
However if the function uses a data file or screen then dont mess
around, go straight to an APP. By using an APP you can take advantage of
existing templates which certainly simplify things. If the size of the library
isnt critical (and these days very few are) then you can even include
source code functions in an App.
The second big decision to make is to document what youre doing. Now
like you Im not a big fan of writing documentation, but one thing
Ive learnt is that if you dont document your function, youll
never reuse it. I cannot emphasize enough the importance of this step. And
dont let it bog you down either - it doesnt need to be a big
deal. All you need to document is the function name, what parameters it
takes, what it returns and in a nutshell what it does.
Getting Started
Ok, well were ready to start. In this issue Im going to base my
library on an APP file. Next month well explore the methods and advantages
of making a Project function library.
Firstly make an empty directory and in it create a new APP file. Im
going to call mine CS (as in CapeSoft). I recommend using 3 or fewer letters,
the reason for which well discuss later. Avoid the names of existing
Clarion, or third party DLLs, for example RUN, CLA, DOS, TPS etc. Dont
select any dictionary for the app. Select the "Destination Type"
as "DLL". Well talk later about maintaining multiple versions
of the same library, but for now let's make it a 16-bit DLL.
Now youve got your empty application which proclaims a lonely ToDo called
Main. Before continuing click on Main and make it into a Source template.
Click its "Export this function" switch off. Were never going
to use this Main function, but we also dont want to export it.
Let's go ahead and add our first function. Im going to add a function
called Calendar, which predictable brings up a calendar on the screen and
allows the user to select a date. It in turn uses 2 other functions called
DaysInMonth and DayOfTheWeek. These functions might come in handy one day
in their own right so well export them as well.
As an aside, Ive lifted this function from my own function library and
one of the interesting things here is that although it uses a window I used
the Source template to write it and not the Window template. This makes it
harder to maintain but it does keep the code really small and tight. I have
to say that if I rewrote the function today Id go ahead and use the
Window template. When in doubt always go with the approach thats easiest
to maintain and change. The size of computers and hard drives today dont
require the sort of code hand tuning that was required 5 years ago.
The function itself isnt that important, its the concepts were
dealing with here. If youve got functions already in other apps that
you think might be useful to reuse then the easiest way to get them is to
use the "Import from Application" option which is in the File menu
of the Clarion IDE.
Theres one important step to note when creating (or importing) functions.
You must explicitly set the NAME attribute in the functions prototype.
For example the Calendar function takes a long, and returns a long. So its
prototype would normally be "(Long), Long". However when creating
a DLL you need to add the Name attribute to the end. So it becomes "(Long),
Long, Name (Calendar)". You need to do this to stop the compiler
"mangling" the name for you, which would make the function unusable
in this DLL. Also when we prototype the function in the application where
it will be used then we need to add the DLL attribute. Well see that
later.
Before we go ahead an compile the application theres one more item to
set. Go to the project settings, down to the bottom where it says "Target
Name". Remove the name thats there for you (in my case it was CS.DLL)
and add a name built up as follows; CW2<your app>16.DLL. So mine became
CW2CS16.DLL. Now you see the reason for keeping our original application name
to 3 characters. The point here is that we want to reuse this library which
almost certainly means well be compiling "Local" versions
as well as 32-bit versions. Ill talk about this more, later. Also were
going to port this library to later versions of Clarion (starting with the
impending Clarion 4) so we need some kind of naming standard. The simplest
thing to do is use the same standard Clarion does.
If you compile at this point ( go ahead try it ) youll get an error
saying something like "Make Error: File "CW2CS16.EXP" not found"
. This .EXP file is the Export file. Its from this file that Clarion
makes the Library that goes with your DLL. The library contains all the necessary
information for later applications to use the DLL. All however is not lost.
In fact this little step is a major bonus which well see in a minute.
Its also the reason we dont name our app originally as "CW2CS16.APP".
Load up the EXP file that is there (which has the name <yourapp>.EXP,
in my case CS.EXP) into the CW editor. Mine looks something like this (yours
will look similar):
LIBRARY CS
CODE MOVEABLE DISCARDABLE PRELOAD
DATA MOVEABLE SINGLE PRELOAD
HEAPSIZE 1024
SEGMENTS
ENTERCODE MOVEABLE DISCARDABLE PRELOAD
EXETYPE WINDOWS
EXPORTS
CALENDAR @1
DAYOFTHEWEEK @2
DAYSINMONTH @3
$GlobalRequest @4
$GlobalResponse @5
Now most of this we can ignore for now, but before we save this under a new
name we need to make 2 changes. Firstly change the top line to be the FULL
name of your DLL (without the extension). So in my case it becomes:
LIBRARY CW2CS16
Then delete the last two lines, and indeed any others which may be at the
end of the list starting with a "$".
Then save the file under its new name, which in my case is CW2CS16.EXP. For
me the file ended up looking like this:
LIBRARY CW2CS16
CODE MOVEABLE DISCARDABLE PRELOAD
DATA MOVEABLE SINGLE PRELOAD
HEAPSIZE 1024
SEGMENTS
ENTERCODE MOVEABLE DISCARDABLE PRELOAD
EXETYPE WINDOWS
EXPORTS
CALENDAR @1
DAYOFTHEWEEK @2
DAYSINMONTH @3
Now go ahead and compile, and if there are no errors in your code then youll
see those magic words "Made CW2CS16.DLL".
Now although weve successfully made a DLL we need to do a few more things
to make it really useful. Remember a little time spent here will make using
the DLL that much easier, which means it will get used. If youre like
me then simplicity is the name of the game. If its too hard to use I
simply dont use it.
OK, so 2 things left to do. The first is to document your functions, and the
second is create a simple template to use them. There, in one sentence Ive
managed to capture the two things Clarion programmers would prefer to ignore.
Keep reading though, it really isnt as hard as you think.
Theres not much I can do about the first except to give you these tips.
Use a simple Windows editor to store your documentation. That means for Windows
3.1 users, use Write and for Windows 95 users use WordPad (or even better
- use Write. You can copy Write from your old copy of Windows, put it in your
\Windows directory, create a shortcut to it, and it works just fine). The
main reason for this is size and portability. Sure youve got that Word
95 just sitting there looking at you but Word takes oodles of RAM to load,
which means less for Clarion when youre compiling. So save Word for
those long manuals. Also you may need to distribute your library to others
and Write and WordPad provide the most portable ways of doing this.
Be brief in each functions description. Capture the function name, the
parameters it takes, what it returns, and what it does. Keep it short and
to the point. Write down anything special about the function, but dont
spend too long detailing the obvious.
There is much that could be said about writing templates, but the idea here
is to keep it simple. The more time you spend writing the template the more
you save later. However the effort of learning the template language can often
offset the benefit gained. Well explore the templates in a later column
but for now lets concentrate on the basics. Remember we dont need
the template for compiling the DLL, we need it for the applications that will
eventually use the DLL.
Using templates we can simplify the use of the DLL in the following ways:
- Prototyping our DLL functions in our app
- Adding the required libraries to the project
- Creating small "code" or "control" templates that
make it easier to use the new function.
For the purposes of this article we will deal with only the first 2 parts.
The third will be discussed in a later article. In the meantime the first
2 will be sufficient and will allow you to use your new functions in any embedded
source code.
Firstly our template file needs a name. No big deal here, Im going to
call mine CS.TPL. In it Im going to create a single Global Extension
Template. By adding the global extension to any application the functions
in our library (as detailed in the template) will be added to the application.
Dont worry if youre not a template expert (or even if youve
never seen template code before). You should be able to edit my example file
sufficiently for your purposes.
#TEMPLATE (CapeSoft, 'Common Library functions')
#!==========================================================
#EXTENSION Activate_CapeSoft,'Activate Common Library'),APPLICATION
#!----------------------
#AT(%CustomGlobalDeclarations)
#IF(%Target32)
#PROJECT('Cw2Cs32.Lib')
#ELSE
#PROJECT('Cw2Cs16.Lib')
#ENDIF
#ENDAT
#!------------
#AT(%GlobalMap)
Module('CS')
Calendar (Long), Long, Name ('Calendar'), DLL(dll_mode)
DayOfTheWeek (Long), Long , Name ('DayOfTheWeek'), DLL(dll_mode)
DaysInMonth (Long, Long ), Long , Name ('DaysInMonth'), DLL(dll_mode)
End
#ENDAT
#!---------
Thats it, thats the whole file.
There are only two parts that might need changing. The name of your DLL as
mentioned in the first part (although note that even a DLL gets a .LIB extension
in a project). The second part is the prototypes of all the functions. As
you can see Ive grouped them together in one module. The name of the
module itself is not used, so I prefer the name of the original app. Dont
use the Cw2Cs16 construction here. The prototypes themselves I cribbed from
the main source code file of my DLL app (Cs.Clw) with one addition.
The DLL attribute is required for 32-bit programs. It wont matter too
much if you leave it out and youre only compiling your application in
16-bit, but any template should be sufficient for both 16 and 32-bit programs.
This makes it easy to change your application from 16 to 32-bit later.
Dont forget to save this file in your \cw20\template directory and also
to register the new template in your template registry. Also remember to copy
your new DLL from your development directory to your \cw20\bin directory.
As you might have spotted in the above template file, the template allows
for a 16 and 32-bit version of your DLL. To recompile your DLL as a 32-bit
DLL requires just four changes:
- In the Project settings change the "Project Generator" properties
to 32-bit.
- Again on the project settings remove the "Target" file and
add a 32-bit name in its place. In my case this would be "Cw2Cs32.DLL"
- Create an EXP file as you did for the 16-bit version. Set the library
name to be the same as the 32-bit DLL. Save it with the same name as the
new DLL.
- Compile and copy your new 32-bit DLL to your \cw20\bin directory.
When you add a new function to your library youll need to do the following:
- Add the function to the library application.
- Add the function name to BOTH EXP files.
- Add the new function name to the prototype section of the template.
- Copy the new DLLs to your \cw20\bin directory
Now you can use your functions in embedded or source code just as if they
were part of the Clarion language without having to worry about including
the correct libraries or prototyping the functions correctly. All you do is
add your new global extension to your application and code away!
Weve now covered all the basic information you need to know to make
and maintain your own function library. Remember the basics: write the code,
document it and then do the template. It really will make your coding life
that much easier.
© 1997 Online Publications, Inc. Reproduced
with permission.
© 2012 CapeSoft Software CC
|