Making the Transition to the ABC Templates

Top  Previous  Next

This FAQ documents development issues that are necessary for Clarion developers familiar with the procedure based Clarion templates who are considering the use of the Clarion ABC template chain.

You now have a vastly improved development tool at your disposal: Clarion, with its Application Builder Class (ABC) Templates and ABC Library. These tools write Object-Oriented (OOP) code for you, using the same template interface that you've grown accustomed to in earlier versions of the Clarion templates. This article provides answers to the most common questions about making the move to ABC/OOP.

So, the first question you'll probably ask yourself (after doing the lessons in Getting Started and Learning Clarion to become familiar with the new features) is: "How can I leverage what I already know to get up to speed with Clarion ABC as fast as possible?" That's the overall question that this informal article answers. You'll probably be surprised at how much is still the same, how many resources are at your disposal, and how much more power Clarion has put in your hands with the change to OOP technology.

For those of you who don't write embedded code (or very little) and mostly let the templates handle all the coding, the answer to the question is: you're already leveraged, you already know it--just keep on working with Clarion as you always have. You may notice a reduction in the size of your EXEs and an increase in your applications' performance, but you don't really care how we achieve that, now do you! This article will be the most benefit to those of you who do a substantial amount of coding for yourselves in embed points.

 

I've heard that OOP is really hard to learn.

Like all generalities, this one has a grain of truth at its core. The fact is that, like all new concepts, it will certainly take some work to really "get" the OOP concepts firmly in place, but it really is not as difficult as it's commonly made out to be. It's said, "OOP only takes one minute to understand, but that one minute might not come for a couple of weeks." It just takes a bit of study and a bit of working with it for you to get to the essential "Ah Ha! That's what OOP is all about" bolt of enlightenment.

The biggest difference between writing OOP versus Procedural code is in how you think about the code you write. As one experienced developer is fond of pointing out, in Procedural code you normally think, "How can I perform this task on this thing?" while with OOP code the thought process should be, "I am a thing. How should I perform this task?" These are very different questions representing very different viewpoints.

For example, a Procedural coding thought might be, "How do I make a window refresh when I want it to?" while the corresponding OOP thought should be, "I am a window. How do I refresh myself when necessary?" You need to change your perspective from an external (doing things to objects) to an internal (each object does its own thing) viewpoint.

To help you learn the basic theoretical concepts of OOP, SoftVelocity has two articles in the Programmer's Guide (this book is on your Clarion CD in the C6PG.PDF file): "Easing into OOP" and "Object Oriented Programming." These two articles both explain the fundamental concepts of OOP theory and how they are implemented in the Clarion Language. The Language Reference documentation of the CLASS structure and its related components also covers this same ground in a more formal manner.

OOP, once you've learned the meaning behind all the "buzzwords," is actually pretty simple--it's just not very easy at first. The OOP concepts, while simple, are fundamentally different from Procedural coding concepts. That very difference is what makes OOP seem difficult at first, but it is also that basic difference that gives OOP its power. The result is worth the effort required to attain it.

 

I've heard that the ABC generated code looks very different.

Yes, that's certainly true. The ABC templates only generate a single line of code (GlobalResponse = ThisWindow.Run()) into a generated PROCEDURE. All the code to accomplish the functionality of the PROCEDURE is contained either in the ABC Library, or in overridden methods of the ABC Library. These overridden methods are specifically generated for you by the ABC Templates to implement the functionality you request when you fill in the template prompts.

For all the various types of procedures, the ABC template generated code gives you the same functionality the Clarion procedural templates give you (often more, and with more efficient execution). You can easily see this just by looking at the similarity in the template prompts in the Application Generator. This means that you can simply continue to choose the functionality your PROCEDURE should perform from the ABC Template prompts just as you did before--without changing the familiar way of working you're already accustomed to!

 

I've heard that writing embed code is very different in ABC.

This is both true and untrue. True, there are some new things to consider when you write your embed code, but quite often you can write your code just as you did before. In other words, where in the Clarion templates you might write a couple of lines of code into the EVENT:Accepted embed point of a control to set up some variables and call a procedure, or to enable/disable other controls on the same window, or to check the value entered by the user, or … In ABC you do exactly the same thing--no change at all. For the most part, you can write your event handling embed code in ABC just as you did with the Clarion templates.

We've added a new feature to the Clarion language specifically to enable you to keep coding your event handling embeds the same way: new scoping rules. In Clarion, PROCEDURE local variables and ROUTINEs are visible and available for use anywhere within that PROCEDURE and any overridden method of a CLASS declared within that PROCEDURE. This means you can still use local variables and call your ROUTINEs in your embed code exactly as you always have, despite the fact that they are actually in separate procedures.

So what are the new considerations to bear in mind? Here's the biggest one: Realize that your embed code is now being placed in a completely separate procedure--an ABC "method" (procedure) specifically overridden by the templates for the individual PROCEDURE you are creating.

There are a couple of implications to this that might not be obvious:

1.

Any implicit variables you use are in scope only within that one method. Using the "same" implicit variable in another embed (in another method) now creates a separate instance of that implicit variable unique to that method.

For example, in the Clarion templates if you assigned a value to X# in EVENT:Accepted for a BUTTON control, then tested the value of X# in EVENT:CloseWindow to see if the BUTTON was pressed, you would be referencing the same X# implicit variable in both statements and your code would work as expected. However, in Clarion ABC generated code, EVENT:Accepted is handled by the ThisWindow.TakeAccepted method and EVENT:CloseWindow is handled by the ThisWindow.TakeWindowEvent method. Since these methods are two separate procedures, you would end up with two different X# implicit variables (one in each method), and your code would definitely NOT work because the value of X# in ThisWindow.TakeWindowEvent would always be zero.

Therefore, where you once might have used implicit variables across multiple embed points, you should now explicitly declare local variables. The hidden benefit to this is that by explicitly declaring local variables you are letting the compiler catch any spelling mistakes you might have made in your code (a common problem when using implicit variables).

2.

In the Clarion templates you might have placed an OMIT statement in one embed and its terminator in another embed to "work around" template generated functionality that you wanted to override. This is very dangerous to do in the ABC templates, because you'll probably OMIT much more code than you intended to, breaking your application in ways that may not be obvious.

For example, in the Clarion templates if you placed an OMIT in the "EVENT:Accepted -- Before Generated Code" embed point for a control and its terminator in the "EVENT:Accepted – After Generated Code" embed point for the same control, you would simply be omitting template generated code for that one control. However, in Clarion ABC generated code, you would be omitting all the code (generated and embed code) for a number of controls along with the call to the PARENT.TakeAccepted method to handle all the standard EVENT:Accepted functionality.

Therefore, when you want to override any standard Template functionality in ABC, just override the appropriate methontentsod, issuing a RETURN before the call to the PARENT method, and do not use OMIT. The hidden benefit here is that your ABC generated OOP code is much more flexible and efficient, and you'll probably have less need to override standard template generated functionality.

 

What resources do I have to help me learn to convert my code to ABC?

Clarion gives you a tool to edit your embedded source: the Embeditor (in the Application Generator, RIGHT-CLICK and select Source from the popup menu). The Embeditor was specifically designed to show you all the possible embed points in your PROCEDURE within the context of template generated code. It is important to note here that the Embeditor does not show all the code that WILL be generated for your procedure, but all the code that COULD BE generated. Seeing your code in context makes it much easier to understand the new scoping issues.

 

What's with these new Embed Priorities?

The ABC Templates contain fewer named embed points than the Clarion templates do, so at first it may look like we've removed some capability. However, the new Embed Priorities allow each named embed point up to 10,000 logical embed points within the generated code. This can be pretty confusing until you use the Embeditor to edit your embedded source. Once you can see exactly where the embed point priorities lie in context, you will be able to clearly see where you need to place your code. The priority numbers themselves do not matter--what matters is where the embed point priority lies within the surrounding generated code, and that's why we gave you the Embeditor.

The ABC Templates have a new naming convention for the embed points which uses the names of the ABC Library method you're overriding when you place code into the embed point. These may at first seem unfamiliar since they are different than the names used in the Clarion templates. The easy way to learn the new embed points and their priorities in relation to the Clarion template embed points is to:

·

Choose Tools Application Options and from the Action for Legacy Embeds droplist, select Show all and generate all (you can do this while still in your app).

·

Use the Embeds dialog as you always have to write your embedded source.

·

Reset the Action for Legacy Embeds to Show filled and generate all (to highlight the difference between the embed points by labeling the Legacy embeds as such in the Embeditor).

·

Use the Embeditor to edit your source and move your code from the Legacy embeds to the appropriate new embed point (immediately above or below the Legacy embed).

Working this way, you'll find that you're still being productive while you are learning the new ABC embeds, and learning the new ABC Library methods at the same time!

Using this process, you will quickly learn the ABC equivalents for your more commonly used embed points, such as these:

 

Clarion template embed

Clarion Win32 ABC equivalent

Initialize the procedure

WindowManager Method Executable Code Section,

 

 

 

Init() - Priority: ~6500

 

 

After Opening the Window

WindowManager Method Executable Code Section,

 

 

 

Init() - Priority: ~8030

 

 

Beginning of procedure, After Opening Files

WindowManager Method Executable Code Section,

 

 

 

 

 

Init() - Priority: ~7600

 

 

Preparing to Process the Window

WindowManager Method Executable Code Section,

 

 

 

Ask() - Priority: FIRST

 

 

Before Closing the Window

WindowManager Method Executable Code Section,

 

 

 

Kill() - Priority: ~7300

 

 

End of procedure, Before Closing Files

WindowManager Method Executable Code Section,

 

 

 

Kill() - Priority: ~5600

 

 

Format an element of the Browse Queue

Browser Method Executable Code Section,

 

 

 

SetQueueRecord() - Priority: ~5500

 

 

Before Printing detail section

Process Manager Method Executable Code Section,

 

 

 

TakeRecord() - Priority: FIRST

 

 

Activity for each record (Process template)

Process Manager Method Executable Code Section,

 

 

 

TakeRecord() - Priority: LAST

 

 

Browser, Double Click Handler

Browser Method Executable Code Section,

 

 

 

TakeKey() - Priority: FIRST

 

 

 

IF RECORDS(SELF.ListQueue) AND KEYCODE() = MouseLeft2

!Place your code here (you must write the !surrounding IF structure, too)

END

 

 

Browser, no records found

Browser Method Executable Code Section,

 

 

 

ResetQueue(BYTE ResetMode) - Priority: LAST

 

 

 

IF NOT RECORDS(SELF.ListQueue)

!Place your code here (you must write the !surrounding IF structure, too)

END

 

 

 

Yeah, but I heard that writing File Handling code is very different in ABC.

OK, here's where there really is a fundamental difference. Since the ABC Templates generate their code using the ABC Library, you'll want to write your embedded code to use the ABC Library methods so that there's no possibility that your embedded code will "mess up" anything the template generated code is counting on. Naturally, this is going to be easier to do than you might think.

Here's a table of the ABC methods to use in place of the common Clarion language statements:

 

Clarion template code

Clarion Win32 ABC Library equivalent

 

 

 

 

OPEN(File)

Relate:File.Open()

!This ensures all related files are opened,

SHARE(File)

Relate:File.Open()

!as well as the named file, so Referential

CheckOpen(File)

Relate:File.Open()

!Integrity constraints can be enforced.

 

 

 

CLOSE(File)

Relate:File.Close()

!This ensures all related files are closed.

 

 

 

ADD(File)

Access:File.Insert()

!These ABC methods all do error handling

IF ERRORCODE THEN STOP(ERROR()).

 

!so the error check is unnecessary. Insert

!also handles autoinc and data validation.

 

 

 

PUT(File)

Relate:File.Update()

!The Relate: object !enforces RI constraints

IF ERRORCODE THEN STOP(ERROR()).

 

!in Update() and Delete() methods.

 

 

 

DELETE(File)

Relate:File.Delete(0)

!Parameter suppresses !the default confirm !dialog when 0.

IF ERRORCODE THEN STOP(ERROR()).

 

 

 

Another common file handling situation is the simple file processing LOOP. In the Clarion template embeds, you would write code like this:

 

SET(key,key)

LOOP

 NEXT(File)

 IF ERRORCODE() THEN BREAK.   !Break at end of file

 !Check range limits here

 !Process the record here

END

 

And here is the equivalent ABC code:

 

SaveState = Access:File.SaveFile() !Tell ABC to "bookmark" where it's at (just in case)

SET(key,key)              !Note there's no change here

LOOP

 IF Access:File.Next()<>Level:Benign THEN BREAK.

 !Breaks when it tries to read past end of file

 !Check range limits here

 !Process the record here

 END

Access:File.RestoreFile(SaveState) !Undo the "bookmark" (SaveState must be a USHORT)

 

As you can see, this is all pretty straightforward--only a couple of minor changes to learn.

Another common code construct is getting a record from a file. In the Clarion template embeds, you might write code like this:

 

IF File::used = 0

CheckOpen(File)

END

File::used += 1

CLEAR(FIL:record)

Fil:Code = 123

GET(File,FIL:CodeKey)

IF ERRORCODE() THEN CLEAR(FIL:Record).

File::Used -= 1

IF File::used = 0

  CLOSE(file)

END

 

And here is the equivalent ABC code:

 

Relate:File.Open()               !This handles all error conditions

CLEAR(FIL:record)

FIL:Code = 123

Access:File.Fetch(FIL:CodeKey)   !Fetch clears the record on errors

Relate:File.Close()

 

And of course, the file Open and Close method calls can be generated for you if you just add the file to the procedure's Data / Tables Pad. The ABC Library is smart enough to only open a file if it really needs to, making your program more efficient. Using Clarion's ABC Library methods you write less code to accomplish the same (or more) functionality.

 

How do I learn about all these new ABC methods?

The easiest way to become familiar with the ABC Library overall is to read the ABC Library Reference --specifically those sections which present an Overview of each Class. It's not necessary (at first) to read about every single method, just use the Overview to get an idea of what each Class is all about and what you can do with them. Then read the descriptions of the methods that look like they'll be immediately useful to you.

Method names have specific meaning in the ABC Library to indicate the type of functionality each method provides. All the classes consistently use these names:

 

AddItem

Adds an item to its object's datastore. The item may be a field, a key, a sort order, a range limit, another object, etc.--anything the object needs to do its job.

Ask[Information]

Interacts with the end user to get the Information.

Fetch

Retrieves data (usually from a file).

GetItem

Returns the value of the named item.

Init

Does whatever is required to initialize the object.

Kill

Does whatever is required to shut down the object, including freeing any memory allocated during its lifetime.

Reset[what or how]

Resets the object and its controls. This includes reloading data, resetting sort orders, redrawing window controls, etc.

SetItem

Sets the value of the named item, or makes the named item active so that other object methods can operate on the active item.

TakeItem

"Takes" the item from another method or object and continues processing it. The item may be a window event (Accepted, Rejected, OpenWindow, CloseWindow, Resize, etc.), a record, an error condition, etc.

Throw[Item]

"Throws" the item to another object or method for handling. The item is usually an error condition.

TryAction

Makes one attempt to carry out the Action. A return value of zero (0 or Level:Benign) indicates success; any other value indicates failure.

Knowing these consistent naming conventions will make it much easier to understand what an object's methods do, whether you've read the ABC Library Reference about that specific type of object or not!

In addition to the ABC Library Reference, Clarion also has a Class Viewer to show you the ABC Library properties and methods in a tree view. On any Classes tab, just press the button labeled "Application Builder Class Viewer" to view the ABC Library structure. The Class Viewer graphically shows you how the ABC Library classes are derived--which class inherits properties and methods from which Parent class.

The ABC Template set contains two Code Templates, which will help you learn more about using the ABC Library: CallABCMethod and SetABCProperty. These were specifically created to "walk you through" writing ABC Library code in any executable code embed point. These two Code Templates will write your method calls and object property assignments for you!

 

So how do I figure out which ABC method to use?

Here is a standard process you can use to accomplish any task using the ABC Templates and Library:

.1.

Determine if the ABC Templates can perform the task.

The ABC Templates do many things for you that the Clarion templates do not. See the ReadMe file for a list of the new template features (the Template Guide contains complete ABC Template documentation).

 

If the ABC Templates will perform the task for you, you're done. If they won't, continue on to Step 2.

.1.

Identify the A