Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Really you have two options: You can browse it in the embed list or in the embeditor, or you can use a tool to extract just the embeds so you can look at them without the distraction of the generated code.

About TXAs

As far as I know, there's only one way to programmatically extract the embed code from an APP. First, you have to export a TXA, which is an import/export text version of the information contained in an APP file. And second, you to parse the TXA to get the embeds, which can be a bit of a pain as the TXA format isn't documented.

...

What I had in mind for my new utility was something more along the lines of Figure 1.

Image Modified
Figure 1. A utility to display and write the embed list

My original parser's functionality was overkill for this new app; I really didn't need to build up an elaborate database of applications, procedures, and embed points. I just needed a list of embed points. But obviously I needed all of the parsing capabilities, gnarly though the code might be.

...

And there are other problems. Because my original app was tied to a particular data store (a PostgreSQL database), any re-use of that code would have to know the table definitions. Since Clarion only supports one dictionary per app, any apps that used this procedure would either need to use the dictionary or import the tables from that dictionary.

Class or procedure?

So what's the answer? If it's not a template, and not a multi-purpose generated procedure and not INCLUDEd source, what's left? Procedures and classes, that's what. But not just any procedures or classes. You want to write code that has as few dependencies as possible.

...

I'm not going to go into all the details of how to create a class; I'll cover that in following articles. For now, just keep your eye on the transformation of the embedded code into a class, and don't worry excessively about exactly how it was done.

The class

The first decision I have to make is how to store the embed data. Originally I used a SQL database, but this now appears to be a liability. My parser should use something more transient, which can be converted to a permanent store or just discarded after use. An in-memory data store, in the form of nested queues, fits the bill:

...

I now have a Write method that dumps my embeds to a text file, but I could also create another Write method that would dump the embeds out to a database. I'd have to do this by passing in file and field references, and perhaps FileManager references, but it could be done, and it would l ensure the code remained portable between not just apps but also dictionaries.

Automated testing!

Perhaps more interesting to me than simple reuse is that by moving my code into a class I've made it testable. But what does testing really mean, in the Clarion world? Usually it means writing some code in an embed point, running the app, clicking some clicks and watching what happens. That's useful, but it doesn't necessarily tell you what you need to know about the reliability of your core code. And it's tedious.

...

Automated testing is a bit more awkward in a language like Clarion, but still possible, as Figure 2 shows.

Image Modified
Figure 2. Testing the parser class

Testing the parser

Figure 2 is a demostration of two applications, neither of which I've yet discussed. The application that you see running is called (tentatively) CTest, and is a Clarion test runner. CTest's job is to load up a specified DLL, search it for test procedures, run those test procedures and report on the results. It's very loosely patterned on the kinds of unit testing applications readily available to .NET developers. I'll have an article describing the inner workings of CTest next month.

...

Obviously, this kind of code extraction works best with code that isn't tied to the UI and isn't dependent on a particular database, although in most cases, and with TPS files in particular, you can still run automated tests more easily against a database than you can against a user interface. But that's also my point: the code that really gives you application value is almost always code that doesn't depend on the UI or on a particular physical database. It may depend on a certain data structure, but that structure seldom has to be just a TPS file or only a SQL table or whatever specific implementation you currently use.

Embed code reduction in the embed utility

So what's the end result of refactoring my parser into a class? After exporting the TXA from my ListEmbeds.app utility, I ran that utility against the TXA and got this output:

...

There's still a bit of embed code there, but now none of it contains any significant business logic. All the critical bits are inside my parser class.

There is a template that does this already, you know

Even back when I wrote the original parser I was pretty sure there was a template that would extract embed points, and Steve Parker finally pointed it out to me: Bo Schmitz' free BoTpl utility can extract embed points from applications. Bo's excellent template does this by exporting a TXA and parsing the result. Sound familiar?

As useful as Bo's template is (and I highly recommend you get it and use it) I think it also points out the value of putting business logic into classes rather than into templates. Source code can be easily tested, and even debugged with the rudimentary Clarion debugger; templates are much more difficult to test and there is no true template debugger, only logging tools.

No, I'm not done yet

As has often happened to me, in the course of writing my tests I discovered some new features I wanted to implement, and also a bug or two that my initial set of tests hadn't uncovered. I'll explore these issues another time; at some point I'll also detour into an explanation of the CTest test runner app, and then it'll be on to the semi-real-world example of the Invoice app.

...

  • CTest - the test runner application
  • Embeds - the original embed application from the article series (doesn't extract embed source)
  • ListEmbeds - the new app to list embed source
  • TxaParser - a hand coded project containing the TXA parser class and supporting code
  • TxaParserTest - an app containing unit test procedures for the TXA parser
Image Modified
Figure 3. The solution

As well there are libsrc and template directories containing supporting templates and classes you may want to copy to your libsrc and template directories.

...