chtlogo001.gif

hndclassbasedembedding.gif

Background: Class-Based Embedding

This is the third paper in a series of "Best Practice" embedding discussions. It uses the concepts illustrated in the the first two papers and moves forward to describe a new "Best Practice" embedding template introduced in CHT's 18A.02.00 Build of March 2014.

For background, the first two papers may be found here:

Paper 1: Clarion Embedding Best Practice   
Paper 2: Clarion Embedding Best Practice - Further Explorations

 

Best Practice Embedding: Point One

Best Practice Embedding puts as little code as possible in the ACCEPT event loop of the application.

When an event such as a button push or a field alert needs to trigger some hand-written code, the most obvious thing we all do is put the code into the relevant event slot for that control. Fine, if an embed is one or two lines of code. But what if it takes several hundred lines of code? Such large, often structureless embeds are messy, and difficult to debug once they're in place. And the more of them there are, the messier your embedded procedure becomes. It all gets to be a bit too much to untangle for someone having to work after the fact with your applications.

When that "someone" is you, two or three years down the line, and you have to fix, advance, improve, and debug, reams of embed code, the practice of procedure-enhancement through embedding calls out for a Best Practice that helps to solve once and for all, some of the counter-productive issues that arise with procedure code-embedding.

Best Practice Embedding: Point Two

Best Practice Embedding reduces the chances of significant code loss through embed orphaning.

Embed orphaning is almost unavoidable in "dynamic" applications that are maintained over a long period of time, as the interface evolves and functionality changes with end-user requirements. But it stands to reason that the shorter your average piece of embedded code, the less code you'll stand to lose should the inevitable happen, and some embeds become orphaned due to the removal of a control or a template.

If your average in-line embed is one or two lines of code that merely calls into a local class function where the "actual" code resides, then you really haven't lost any functional code at all. Only your event-hook -- that button or menu you intentionally or unintentionally removed -- is lost and can be restored with one line of function-evoking code placed under some other control or in some other event slot.

Best Practice Embedding: Point Three

Best Practice Embedding improves code design, reliability and re-use, while reducing the amount for repetetive code.

When functional code is placed in-line into an ACCEPTED event slot under a window control or into an ALERT or WINDOW event slot it becomes difficult to call that code from some other event slot or from elsewhere in your code. Yes, you can POST an event to the window or to the control harbouring this in-line code, but in a busy window there's no absolute guarantee that your event code is going to execute in some required order, before or after other code that also must run, due to an interdependency. Such is the nature of the beast. Inevitably, for this reason, when hand-embedding, highly similar in-line event code with slight variations, tends to be repeated from one event-slot to the next.

You may tend to counter this particular point with the notion that you always place reusable code into a local routine and then abstract your routine code enough to handle minor functional variances based upon which event invokes the routine. That's certainly an improvement over in-line embed code from the standpoint of code reuse, but it's far from perfect, especially when your routine is operating on procedure-wide variables.

And most routines do this, because routines dont take input parameters. So the same reasoning surrounding the difficulty of controlling the order of window events, can be used to diminish the suitability of routines, because you're not able to absolutely control the values in your procedure-wide input variables in the context of multiple-cascading events.

Best Practice Embedding: Point Four

Best Practice Embedding improves code legibility by sponsoring the use of meaningful, consistent entity names, without having to compulsively hunt through myriad template interfaces to rename template-generated objects and controls.

To ensure uniqueness, templates tend to name things generically with template instance numbers attached. A classic example of this is BRW3, BRW5...BRW12. And of course, we've all silently cursed QUEUE:Browse:3, QUEUE:Browse:5 under our collective breaths.

But let's be realistic. As long as only template-generated code is referencing and using these names, there's absolutely nothing wrong with these names. The code will always work because the template knows which object or queue or control it's referring to. There's no real motivation to rename these things meaningfully, unless you like to spend a lot of time reading template-generated code over which you have little or no control.

Unfortunately, as soon as you begin having to address these generically named OOP objects, data entities and window controls, inside your embed code, the guess-work starts. Since YOU DO have to be able to read embed code, both now as you're writing it, and in the future as you're revising it for the third or fourth time, names DO MATTER.

Many Clarion developers, myself included, counter this particular point by changing template generated generic entity names where possible. Some do this passionately, religiously, obsessive-compulsively, everywhere. I tend to do it only where it impacts my ability to easily read and understand my hand-embedded code. When only template generated code is present, I tend to LET IT BE.

Why so little passion on my part, with this issue? Well, keep in mind, the prime motivation for our having derived a need to rename things more meaningfully in the first place, is to make OUR embed-code more readable and ultimately more maintainable. Generated code can take care of itself.

Best Practice Embedding: Point Five

Best Practice Embedding improves code development speed.

It stands to reason, that a major benefit deriving from points 1 through 4, is increased code development speed. So this fifth point, while true and valid in its own right, really derives from my previous four points.

• In-line embed code is kept short -- often only one line of code -- and can be placed into a given embed point in seconds.

• Critical embed code is less likely to be lost to orphaning, and can be re-attached into the procedure event structure with no great effort or expenditure of time.

• When embed code can more readily be reused by different event triggers inside the procedure it stands to reason you'll be writing less code, reading less code and in the long run, maintaining less code.

• When embed code is clear, concise, structured and uses good naming methodology that eliminates frequent name-hunting trips to the window structure and to the various template interfaces attached to the procedure, coding will proceed more smoothly and quickly.

So What's The Trick?

No trick at all, really.

Best Practice Class-Based embedding uses a generated, intra-procedure class in a slightly new way than you've seen it used in the past.

Let me first define by what I mean by generated, intra-procedure class. Aren't the classes attached to my procedures by various ABC and third-party templates also generated intra-procedure classes? Well, no, not really, not exactly, anyway.

ABC-compliant templates generate intra-procedure derivatives of external, pre-existing, classes into your procedure. External classes -- or Library classes, if you will -- like the ABC classes in \libsrc\win\, the HND classes in \libsrc\win\ and numerous others, exist with pre-built functionality in them. The code in these library clases is pre-written and often highly abstracted. properties and methods are latched into your procedure

Cheers...

Gus Creces
The Clarion Handy Tools Page
www.cwhandy.com
gcreces@gmail.com

 


chtcopyrightgray.gif