![]() |
|
Published 1999-02-08 Printer-friendly version
The introduction of the Application Builder Class (ABC) templates in Clarion 4 radically altered the business of creating applications with Clarion. I believe ABC is as important to Clarion as the first Windows version, or the introduction of client-server database drivers. At first glance, however, it may not be immediately apparent that ABC represents any dramatic shift.
Has the AppGen's feature list expanded dramatically? On the surface it hasn't. There are some nice new features available in the ABC templates (like expanded edit-in-place support, and better browse sorting and filtering, but in its first and second incarnations, ABC mainly recreates the legacy templates (although it does improve significantly on legacy's handling of SQL databases).
At the same time, because embeds are handled somewhat differently, and some template options are organized differently, you will need to relearn a few things. There are costs to ABC as well as benefits, and for most of us the short term cost may (and probably will) exceed the short term benefit. If you have a lot of legacy code, you may find it difficult to migrate some of that code to ABC.
So where's the payoff? Where's the dramatic change?
Software development, as an industry, is forever evolving. We're not using the tools we used five or ten years ago (at least most of us aren't), and chances are not many of us will be using the tools we have now five years into the future. Change is a given, though it doesn't necessarily happen continuously. Often we'll use the same tools, or the same programming approach, for a period of time, until our own needs, or the solutions being provided by our competitors, force us to adopt some new way of development.
Most of us do AppGen-based development, which means we rely largely on whatever TopSpeed's templates provide. (To my knowledge there are no complete template chain replacements commercially available.) The templates determine the feature set and, for many of us, the look and feel of our applications.
The real value in ABC is that while the current template feature set has increased modestly, the potential for what the AppGen can create has increased rather dramatically.
In the legacy templates, the template files themselves contain a mix of template language statements and Clarion language statements. The template language statements control the generation of the Clarion language statements. As you choose options in the AppGen, code is generated or not generated as needed.
While this has been an effective way to create Clarion applications for a number of years, some of the code has become extraordinarily complex and difficult to read. The browse templates, in particular, have been straining at the perimeter of maintainability for some time. Bruce Barrington recently responded to this question in the TS newsgroups, saying the legacy templates "represent the end of a development path. Even the author was afraid to change them for fear of unpredictable side effects."
Many of us purchased the now-defunct PowerBrowse because it added many features that weren't readily available in the standard browse, but sadly even PowerBrowse became too expensive to maintain over the long haul.
A key problem with the legacy approach to Clarion code generation is readability. Templates often use switches, such as the #IF...#ENDIF structure, to determine when to generate code, as in Listing 1.
#AT(%BrowseBoxPopupRecords)
#IF(%Control=%ListControl AND %EditViaPopup)
#SET(%ValueConstruct,'')
#IF(%DeleteControl)
#SET(%ValueConstruct,%DeleteText)
#ENDIF
#IF(%ChangeControl)
#IF(%ValueConstruct)
#SET(%ValueConstruct,%ChangeText & '|' &
%ValueConstruct)
#ELSE
#SET(%ValueConstruct,%ChangeText)
#ENDIF
#ENDIF
#IF(%InsertControl)
#IF(%ValueConstruct)
#SET(%ValueConstruct,%InsertText & '|' &
%ValueConstruct)
#ELSE
#SET(%ValueConstruct,%InsertText)
#ENDIF
#ENDIF
#IF(%ValueConstruct)
IF %InstancePrefix:PopupText
%InstancePrefix:PopupText = '%ValueConstruct|-|' &
%InstancePrefix:PopupText
ELSE
%InstancePrefix:PopupText = '%ValueConstruct'
END
#ENDIF
#ENDIF
#ENDAT
Note that although the template code statements (those prefixed with #) are indented and the Clarion code statements are indented, the indentations have little if any relationship to each other. It's often difficult to visualize the generated source simply by looking at the template.
Templates also often contain generated code in temporary variables. The string variable %ValueConstruct is commonly used for this task. Listing 2 shows some code used to create a popup menu string.
#AT(%BrowseBoxPopupRecords)
#IF(%Control=%ListControl AND %EditViaPopup)
#SET(%ValueConstruct,'')
#IF(%DeleteControl)
#SET(%ValueConstruct,%DeleteText)
#ENDIF
#IF(%ChangeControl)
#IF(%ValueConstruct)
#SET(%ValueConstruct,%ChangeText & '|' &
%ValueConstruct)
#ELSE
#SET(%ValueConstruct,%ChangeText)
#ENDIF
#ENDIF
#IF(%InsertControl)
#IF(%ValueConstruct)
#SET(%ValueConstruct,%InsertText & '|' &
%ValueConstruct)
#ELSE
#SET(%ValueConstruct,%InsertText)
#ENDIF
#ENDIF
#IF(%ValueConstruct)
IF %InstancePrefix:PopupText
%InstancePrefix:PopupText = '%ValueConstruct|-|' &
%InstancePrefix:PopupText
ELSE
%InstancePrefix:PopupText = '%ValueConstruct'
END
#ENDIF
#ENDIF
#ENDAT
The actual generated code for this block may look like listing 3:
IF BRW1::PopupText
BRW1::PopupText = '&Insert|~&Change|~&Delete|-|' &
BRW1::PopupText
ELSE
BRW1::PopupText = '&Insert|~&Change|~&Delete'
END
Templates, like programs, often need to reuse the same code. In a template, the #GROUP statement (not to be confused with the Clarion language GROUP statement) defines a block of template code which can be used much the way a procedure is used in an application, except that the job of the #GROUP, like the rest of the templates, is really to generate Clarion code. #GROUPs can even take parameters, like procedures.
Listing 4 shows a #GROUP (from STANDARD.TPW) that formats a filter.
#GROUP(%StandardWriteViewFilter,%ConstructedFilter)
#IF(%ConstructedFilter)
%ListView{Prop:Filter} = |
#SET(%ValueConstruct,%ConstructedFilter)
#SET(%HoldConstruct,'')
#LOOP
#IF(LEN(%ValueConstruct) > 70)
#SET(%HoldConstruct,SUB(%ValueConstruct,71,
LEN(%ValueConstruct)-70))
#SET(%ValueConstruct,SUB(%ValueConstruct,1,70))
#ENDIF
#IF(%HoldConstruct)
'%'ValueConstruct' & |
#SET(%ValueConstruct,%HoldConstruct)
#SET(%HoldConstruct,'')
#ELSE
'%'ValueConstruct'
#BREAK
#ENDIF
#ENDLOOP
#ELSE
%ListView{Prop:Filter} = ''
#ENDIF
Any place you wish to use this code, you reference the group as follows (in this case, the #GROUP is used with a file drop control):
#INSERT(%StandardWriteViewFilter,%DropViewFilter)
In order to read and understand templates, then, you will need to be adept at differentiating between template lines and generated code lines; you should keep in mind the expected contents of calculated string variables; and you should know, or be able to determine, what code any given #GROUP is capable of generating. This is, to say the least, a daunting task.
Additionally, there are no visual development tools available for the template language, except for the limited default window and report editing which can be done in the template registry.
There's no doubt that templates have made for tremendous productivity gains. The problem is that the template language, in the legacy templates, was increasingly being asked to do a job it isn't ideally suited to do.
The ABC templates address the weaknesses of the legacy templates by putting the template language back in its proper place, and relying on a class library for the tricky Clarion source code.
If the templates aren't there to generate complicated Clarion source, then what's their purpose? Ideally, to give the AppGen intelligence. The AppGen isn't so much a program as an interpreter of templates, in the same way that the old DOS BASIC program is an interpreter of BASIC language statements. The vast majority of what the AppGen does, it does under the control of the templates.
A good portion of the templates is made up of statements like #PROMPT, #TAB, #BUTTON, and others, all of which present information to the user and/or accept input. There are a few built-in features, such as the procedure properties form and the global prompts, but by and large what you see in the AppGen isn't the AppGen itself, but the result of the templates you're using.
The real role of the templates is to translate the visual AppGen interface into your final code and to do so in the most efficient way possible.
One of the reasons ABC is so important is because it splits the responsibility for creating your application between the ABC templates and the ABC class library proper. Template code isn't the most efficient way to write programs, for the reasons already explained. That's better done with Clarion source code. Ideally, you'd write as much of your browse code or your form code in Clarion only, and then have the templates create such calls as were needed into that library of code. In this way, the core functionality of, say, a browse procedure, is all Clarion code and much easier to debug and maintain.
That's not to say you can't write a generic browse with procedural code. In fact, the predecessor to PowerBrowse, a product called Power Windows, did just this for Clarion 2.x. One drawback to using Power Windows was that you needed to pass up to 40 parameters to the generic browse procedure! This was a complex enough task that the product came with a program that asked you to fill in the fields on a form and generated the procedure call based on your responses.
Perhaps the greatest difficulty in using a procedure library to perform generic, yet complex, processing, is that you have only one point of entry into a given procedure. If your generic browse is one procedure, you have to pass it all of the information it needs to work (like PowerBrowse) or you have to rely on global variables, which is generally not a good idea.
If you aren't going to use a single procedure, then you have to break up the logic into numerous procedures, and you may have to determine at run time which of these sub-procedures you're going to call. Now you're probably looking at using procedure pointers. Why not just get out a C compiler and shoot yourself in the foot properly?
Happily, object-oriented code is much better suited to this kind of task than procedural code. The core unit of object-oriented programming is the class, which is made up of blocks of code called methods (which are analogous to procedures), and data, which the methods share. It's possible to build a class which models quite complex behaviour, and even to combine several classes into a functioning unit.
In the ABC templates, most of the core functionality of your application is contained in the Application Builder Classes, for which the ABC template chain is named. As a result, the templates no longer have to generate the same kind of complex code that the legacy templates generate.
In ABC, the role of the templates has changed significantly. Instead of creating the majority of the source code for your application, the templates manage the interface to the ABC class library.
Class libraries are like other code libraries - they're collections of commonly-used code. In the case of ABC, the library contains code to open and display windows, to load browses with data, to manage scrolling, to update records, and so forth. But ABC, because it's totally generic, has no specific knowledge of your application's data, or what you might want to do with your application.
Something like a browse procedure now takes a lot less code than it did with the legacy templates because most of the functionality exists in the class library. In order to use that library, however, you have to know which class methods to call.
That's where the templates come in. After you choose (in the AppGen) what options or properties you want your browse, or form, or other window or control to have, the templates create the necessary calls into ABC. There is still some generated code, but it's a lot less than it used to be. More importantly, the core logic is in self-contained, generic classes which can be tested and debugged independently of the templates.
You could, if you wished, create quite large applications entirely with hand code and the ABC library, omitting the templates and the AppGen entirely. It would be work, but a lot less work than creating the same application without ABC.
Additionally, more and more of us seem to feel the need to create larger, more complex procedures, particularly those populated with browse boxes. This isn't always a problem with 32 bit code, but if you're writing 16 bit apps you've probably bumped up against the 64k segment size limitation. Because much of the code in an ABC app is in the class library, the generated code, and therefore the procedure size, is much smaller than in legacy apps.
In the long run, ABC is the logical choice. Unless some white knight takes over the legacy templates, there will be no significant development done in that area anymore. And even if someone does take on this task, it will be a maintenance effort at best. You won't see many ABC-type features being added to the legacy templates, because they're just too difficult to implement.
Switching to ABC does require new skills, but you don't necessarily have to be an OOP expert to become productive. Your required level of OOP knowledge will to some extent parallel your current procedural programming expertise. If you write lots and lots of embed code, you're obviously familiar with the Clarion language. To get the most out of your embed code in ABC, you'll need to know something about the ABC library and OOP in general. If you really just use the AppGen and the templates, and don't write much of your own code, then not a lot is going to change for you.
Whatever your current level of proficiency, you achieved it at some cost. You had to invest in your own skill set. ABC represents a significant technological step forward, and as such it demands a new investment in software development skills.
If you have the option, starting out with a small ABC project is preferable to overhauling a large legacy code base. Unless you're already fully conversant with OOP and have a good grasp of the ABC library, there's a good chance you'll want to rethink a large system redesign once or twice anyway. ABC offers a number of interesting opportunities for large system redesign, some of which I'll be addressing in later articles.
The move to ABC has eased the pressure on the template language by moving most of the core code into the class library. That code is also more extensible than the legacy code. The key principle of object-oriented programming is reusability, and OO languages have a number of mechanism available to make it easier to add new features to a class library without breaking old functionality.
Although ABC in its first and second incarnations mainly duplicates the functionality of the legacy templates, it does provide some new features (such as edit-in-place and query-by-example, in C5), and more importantly lays the groundwork for changes to come.
I expect ABC's impact to parallel that of the Clarion for Windows 1.0 templates, particularly in the third party market. Those templates were the first that allowed users and vendors to easily plug their templates into Clarion's templates. It took a year or two before the full import of this was realized, but as any glance at the Accessories catalog will tell you, the vast majority of third party products are sold as templates.
In the same way, as users and vendors realize the power of ABC, new products emerge, and old products are released with new capabilities. Templates themselves won't go away, because templates are still the ideal way to manage classes in the AppGen environment. The impact of the move to OOP, however, will be at least as big as it was for CW templates.
David Harms is an independent software developer and the editor and publisher of Clarion Magazine. He is also co-author with Ross Santos of Developing Clarion for Windows Applications, published by SAMS (1995), and has written or co-written several Java books. David is a member of the American Society of Journalists and Authors (ASJA).
Copyright © 1999-2008 by CoveComm Inc. All Rights Reserved. Reproduction in any form without the express written consent of CoveComm Inc., except as described in the subscription agreement, is prohibited.
Clarion Magazine ISSN 1718-9942
One year: $159
(reg $189, save $30)
(includes all back issues since '99)
Renewals from $109
Two years: $249
(reg $289, save $40)
Renewals from $199