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 we’ll explore how you can take advantage of these features. And before you ask, no, you don’t need to be a Clarion expert either.

In this first article I will walk through the steps you’ll 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 we’ll delve into the various forms your library can take, and we’ll 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 we’re 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 don’t 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 don’t 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 isn’t 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 you’re doing. Now like you I’m not a big fan of writing documentation, but one thing I’ve learnt is that if you don’t document your function, you’ll never reuse it. I cannot emphasize enough the importance of this step. And don’t let it bog you down either - it doesn’t 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 we’re ready to start. In this issue I’m going to base my library on an APP file. Next month we’ll explore the methods and advantages of making a Project function library.

Firstly make an empty directory and in it create a new APP file. I’m going to call mine CS (as in CapeSoft). I recommend using 3 or fewer letters, the reason for which we’ll discuss later. Avoid the names of existing Clarion, or third party DLL’s, for example RUN, CLA, DOS, TPS etc. Don’t select any dictionary for the app. Select the "Destination Type" as "DLL". We’ll talk later about maintaining multiple versions of the same library, but for now let's make it a 16-bit DLL.

Now you’ve 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. We’re never going to use this Main function, but we also don’t want to export it.

Let's go ahead and add our first function. I’m 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 we’ll export them as well.

As an aside, I’ve 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 I’d go ahead and use the Window template. When in doubt always go with the approach that’s easiest to maintain and change. The size of computers and hard drives today don’t require the sort of code hand tuning that was required 5 years ago.

The function itself isn’t that important, it’s the concepts we’re dealing with here. If you’ve 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.

There’s one important step to note when creating (or importing) functions. You must explicitly set the NAME attribute in the function’s 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. We’ll see that later.

Before we go ahead an compile the application there’s one more item to set. Go to the project settings, down to the bottom where it says "Target Name". Remove the name that’s 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 we’ll be compiling "Local" versions as well as 32-bit versions. I’ll talk about this more, later. Also we’re 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 ) you’ll get an error saying something like "Make Error: File "CW2CS16.EXP" not found" . This .EXP file is the Export file. It’s 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 we’ll see in a minute. It’s also the reason we don’t 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 you’ll see those magic words "Made CW2CS16.DLL".

Now although we’ve 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 you’re like me then simplicity is the name of the game. If it’s too hard to use I simply don’t 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 I’ve managed to capture the two things Clarion programmers would prefer to ignore. Keep reading though, it really isn’t as hard as you think.

There’s 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 you’ve got that Word 95 just sitting there looking at you but Word takes oodles of RAM to load, which means less for Clarion when you’re 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 function’s 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 don’t 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. We’ll explore the templates in a later column but for now let’s concentrate on the basics. Remember we don’t 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: 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, I’m going to call mine CS.TPL. In it I’m 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. Don’t worry if you’re not a template expert (or even if you’ve 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
#!---------
That’s it, that’s 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 I’ve grouped them together in one module. The name of the module itself is not used, so I prefer the name of the original app. Don’t 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 won’t matter too much if you leave it out and you’re 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.

Don’t 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:
  1. In the Project settings change the "Project Generator" properties to 32-bit.
  2. Again on the project settings remove the "Target" file and add a 32-bit name in it’s place. In my case this would be "Cw2Cs32.DLL"
  3. 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.
  4. Compile and copy your new 32-bit DLL to your \cw20\bin directory.
When you add a new function to your library you’ll need to do the following: 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!

We’ve 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