|TLMP is various things to various people. One will say it is a programing language, while another will say it is a component set. It is certainly a new tool to build and assemble programs and a very important tool to create re-usable components. And it comes with a framework of reusable components.|
Graphical representation of a program
A program can generally be presented as a graph. A function (main) is calling sub-functions, which in turn are calling other functions and so on.
While we can represent programs like this, we generally end up with a very large tree with various level of detail (important stuff mixed with very specific stuff). A solution is to create various trees. A main one show the general relation-ship between sub-trees providing independant functionalities. The reader can travel down the trees to better understand the details. NEW
A flat view ?
A program may be represented using either a flat view or a layered view. Imagine the following program:
We can organise logically the view into layers. Our original tree become simple with three modules: main, update, report. Then we produce a tree for update and another for report.
We can combine all trees together showing the layer relation.
A dead end
Program built this way are in general very clean. As you go to the right, modules become more specialised and more application independant. They are reusable in other applications. As you go to the left, you are getting more and more application dependant. Well this is the application itself.
One design philosophy is to get a module as specific as possible. Said differently, the module receives parameter on the left and process them and this is all it knows about the rest of the program. This can be simplified with the qsort() C library function. It knows what to sort from its argument and really do not care if the application is graphical or text base or a daemon. It is sorting and this is fine.
You find quite a lot of reusable function and component in the C and C++ libraries. They are generally at the far end of the tree.
One unfortunate conclusion outlined above is that reusability is getting worse while you move to the left of the graph. With large application you find you are too often on the left side and creating reusable components, framework components is difficult. NEW
With the design philosophy above, you are often trapped with the hierarchy. You have this report component (a sub-tree) which must be enhanced to print differently depending on some external factors. For example it can print to a printer, a fax or send the report by mail.
There are various way to enhance this report engine:
In many cases, you will end up with functions passing around information needed by sub-functions. For example, the fax and mail output requires an address, which is behond the scope of the report module. So if we want to play clean, the report module has to accept this new parameter, which is totally un-needed for the report itself so it can pass it down to the output selector which ultimatly will pass it properly to the output module. NEW
The first solution is relativly easy to achieve. But the report engine is kind of moving to the left of the graph a little bit more. Its reuseablity is a little compromised. All of a sudden, all application using it are enhanced. They can now send report to fax and mail but they all have to be modified. All of a sudden, the reusable component introduces a price. Not only the new parameter will have to be passed it will have to be queried (obtain from one source). Now if all reusable component start to include every enhancement required by every application needing them, you will end up with larger and larger components, with tons of options. Further, the requirement of one application will probably clash at some point with the requirement of others.
For sure, there must be a better way. NEW
This is a nice solution, powerful and flexible, yet a little expensive to use. Do not get me wrong here. OO (Object Orientation) is important (And I am using it every day and will continue).
The question with OO is not "May I express this solution using OO ?". Sure you can. The question is "Is this efficient ?". We are not talking about runtime efficiency. Oversimplifying one can say that if using OO to solve a given problem, we need more line to sub-class a generic class than the class itself, we are not winning.
Sub-classing introduce a lot of back and forth in the code. We have to create a new classes and defines various member functions and so on. Then in our application (lower in the source code if the new class is small), we use the new class instead of the generic one.
OO has been very successful in project with lots of little variations like widget sets for example. It is also very useful to make some components much more easier to use: You create the object, call various methods and destroy the object when you are done and you do not care about all the initialisation details.
When you move to the left of the graph, resuable OO framework are more difficult to express. NEW
Fiddling with function pointers
This is certainly a solution. Not easier to use. Further, with function pointer, you must find a way to carry context information. The function is called potentially from another function located at the far right of the graph, knowing almost nothing about the application.
One solution to the context problem is the "void pointer" that function pass around so it can be passed to the supplied function which can cast back to the proper type to get the information missing.
Using function pointers certainly work, but requires more care and it forces all the underlying components to pass around this "void *". NEW
Context oriented programming
Considering our new application printing to paper, fax and mail, we can come with a different graph representation, still 3D. The new graph fits as well the OO strategy. Understanding this graph is the key to understand TLMP...
We can now say the following things about the new graphs.
Sharing information within a level
Calling a function from a lower level
In the example, we see the report module calling the printing module. The printing module operates at the higher level. What does this means ? It means that while it receives arguments (function call) from the report module, it has access to information known at the same level. We call this the context. In this case, the context is the application. NEW
Definition of a level or a tree
The first level in our graph is made of 4 components: The main module the dialog module, the report module, and the printing module.
In fact, except for the main, none of the other modules are really part of the level. They are called in this level and play together but each of them is defined in its own tree, generally one or more level below.
So what is a level. The level is defined by the following components
At this point, we have mostly circle around the TLMP concept. One may reject this concept of level. In the example above, we have main calling report and report calling printing and that's it! Further, unless you play with OO or function pointers, the module report will always call the module printing.
Here is the trick; The report module is not calling the printing module. Its implementation is calling a generic interface to print. This interface is passed various parameters, only known to the report module.
Going higher in the application, the programmer is free to connect the module needed to this interface. In fact, the programmer is allowed to connect a solution made of several modules and some glue written in C.
OO programmers are using this technique on a regular basis. The report module is calling a virtual function and a sub-class is providing the definition for it. In this respect, TLMP is not different from OO programming (well, it generates OO code to achieve its goal). The major difference is in the implementation and code readability. NEW
Reusing modules in different context
So far so good, but what about TLMP. TLMP is a new programming scheme allowing to work on programs at the tree level, without having to rework the modules used. Using TLMP, one can create different programs reusing the same module set, but inter-connected differently without having to rewrite (even recompile) the modules.
Unlike everything else, with TLMP, the trees above are not a representation of something else, they are the program. Programmers operate directly on trees like this.
Table of content