Dynamic programming tips
- Last Updated: January 16, 2024
- 5 minute read
- OpenEdge
- Version 12.8
- Documentation
This topic provides some advice on programming with dynamic objects.
Dynamic versus static programming
- Generally, dynamic constructs execute more slowly than their static equivalents. This is logical because, at compile time, ABL cannot anticipate what the procedure does at run time and so cannot set up the structures to support the procedure. More of the work is done at run time, when the interpreter looks at the values of the dynamic procedure elements, just in time to prepare and execute them.
- Dynamic programming is more difficult than static programming. Code that is full of dynamic references is usually more difficult to understand at first glance. Since important values are stored in variables rather than hard-coded into the source procedures, it is less clear what is going on when you first look at the source code. Also, the use of handles and other devices that provide you with a level of indirection makes it harder to follow what a procedure is doing without studying it carefully. It is especially important here that you provide good internal documentation in the form of comments.
- You will usually want to write your business logic in static form, with specific references to the tables and fields (or their temp-table equivalents). Your business logic is likely to be unique to a single situation, rather than something repeated many times throughout your application. You cannot write static business logic against dynamically defined objects.
So consider the power of dynamic programming for those situations where your application is doing the same thing in many places. Rather than writing many variations on the same source procedure or creating many compiled versions of the same procedure using include files or preprocessors, you can create a single procedure that does the same general job for every part of your application that needs it. This is why dynamic constructs exist. Consider their cost and the responsibility of having to clean up after yourself when you use them. Where they are the right thing to use, they can add tremendous flexibility to your application and dramatically reduce the number of different procedures you have to maintain.
Reuse dynamic objects
Memory management in ABL discusses ABL memory management and emphasizes that you must delete any dynamic objects you create. It is important to keep in mind, however, that if you are going to create another dynamic object of the same type, especially inside a loop that is executed many times, it is much more efficient to reuse the same dynamic object rather than deleting it and re-creating it. This is true even if you change all the attributes of the object. Then you must simply remember to delete it after you are completely done with it.
- A record for each table is stored in a table called _file.
- The name of the file is in a field called _file-name.
- Each table has a number called the _file-num.
- There are special tables in the database that have file numbers either less than zero or greater than 32K, so the procedure skips those.
|
For each database table, the code creates a dynamic query and a dynamic buffer, and sets the query’s buffer to the dynamic buffer handle. Then the code prepares a default query for the table, opens it, gets the first record, and closes it. It then deletes the dynamic query and the dynamic buffer. To show the effect of the performance more dramatically, this is all done inside a loop 100 times. The following figure shows how long it took for one sample run.
There is a more efficient way to do this. If you move the CREATE QUERY
hQuery statement before the DO block and the
FOR EACH block, and you move the DELETE OBJECT
hQuery statement after the end of those blocks, the procedure runs
somewhat faster. Even though you are resetting the query’s buffer and re-preparing
it for a completely different buffer, it is still faster to reuse the same dynamic
object:
|
The following figure shows the result:
Just be sure you do not forget to delete the object when you are done with it! Unless you are reusing the object a large number of times, the difference in performance is not dramatic, so it is not worth the risk of forgetting to delete a dynamic object unless you are reusing it many times in succession.
Note that you cannot reuse the dynamic buffer in the same way. When you use the
CREATE BUFFER statement, you must name the table the buffer
will be for. This name can be an expression, as it is here, so that the buffer name
can be assigned dynamically at run time, but you cannot then reuse that same dynamic
buffer object for a different buffer. So you have to create it and delete it inside
the loop.