Please enable JavaScript to view this site.

KOL/MCK - User Guide

Analysis of the reasons for the cumbersome application size. KOL architectural concepts

 

Small spool but precious.

(Russian folk saying)

 

But before starting, I analyzed more carefully the possible reasons for the increase in the size of the code, and thought about various ways to prevent this situation in my library. The main reason for the cumbersome size of programs in which classes are used is the fact that some classes use others, those, in turn, others, and so on, and so on, to such an extent that it is no longer possible to break the links. You specify in uses a link to the Forms unit, or to Dialogs, and that's all - your 350-400 Kilobytes are added to the program. This means that you need to create your own class hierarchy, in which you only use TObject as an ancestor for all your classes, and in no case address all the goodness that is ready for use in the VCL.

 

I decided to go even further and "remember" the very basics of Object Pascal. ("Remember" is in quotation marks, because I myself did not have to write in Object Pascal, as I mentioned above, I came to Delphi from C / C ++, and before that I took Pascal only exams at the university, and I strongly scolded this wonderful language, just not understanding its benefits). So, in Object Pascal there is the word object, which means nothing more than "structure" + "set of methods". This is what the classes were later born from. My experiments have shown that a simple object created using the word object saves program size (and most importantly, if classes are not used at all, but only objects, then a few more kilobytes of code from system modules are saved from the very beginning) of course.

 

hmtoggle_plus0First When destroying an object, unlike an instance of a class, you have to manually write code to destroy objects, strings, dynamic arrays that are fields of this object. It's not very convenient, but saving code is more expensive than having to do some manual work.

 

hmtoggle_plus0Secondly The construction of such objects looked very unusual. In order not to get confused in the future, writing something like new (List, Create); , I decided to make all the "constructors" of objects global functions of the form NewTypename (parameters): PTypename. (Just in case, I also made "constructors" inside the TControl object to create various kinds of visual objects, but apparently no one uses them, including myself).

 

hmtoggle_plus0Thirdly Unfortunately, thirdly, that is, about compatibility, I learned much later: in another Pascal compiler, Free Pascal, the word object was not initially supported. But there were people who, for the sake of being able to compile KOL programs in this popular, and what is important - free - compiler, forced, persuaded - I don’t know exactly how to say, finally did some work themselves, and from version 2.10 Free Pascal began to fully support object. Although it is a bit late, and by this time a solution had already been found: in the automatic conversion of KOL to classes, and KOL programs compiled perfectly in Free Pascal, even without the support of primitive objects in it.

 

 

pointing-up-finger

 

Another side of this incompatibility is that there are some problems when viewing the values ​​of object properties in the Watch List when performing step-by-step debugging. Delphi can show anything as the property value instead of the true value. The solution to this problem is to specify the internal name of the field instead of a property when possible (fCount instead of Count, for example).

 

There are still a number of differences in the use of objects versus classes: namely, since object is just a structure in memory, in order to organize a pointer to some object, it is necessary for each object type to provide a corresponding pointer type. (This is not required for classes, since the type of the class is already equivalent to the type of the pointer, i.e. the type of the class representative is the same as the type of the class itself). For the same reason, in object methods, unlike class methods, the Self variable is not a pointer, but the structure of the object's fields, and to get a pointer, you need to use the operation of taking the @ address, writing @ Self wherever you need to pass or use a pointer the object itself for which this method is written. (In the implementation, this operation does not require additional code, since Self is passed to the method by reference,

 

So, I have become firmly established in the decision not to use classes (classes), but only objects (objects). My further research and experiments showed that, firstly, too many different object types, and any too branched tree of the inheritance hierarchy are unacceptable if you need to save code size. And secondly, splitting the code into modules also increases the size of the program. Although, in the second case - and not a lot, but saving means saving, and I decided to cram the entire library into one large source file, which was named so: KOL.pas. *

 

With the problem of reducing the tree of the inheritance hierarchy, I decided to fight the most radical means, namely: all visual objects are represented by the same TControl object type, directly derived from the TObj object type, which I created as the base type for my hierarchy. The constructors are used differently, the sets of methods sometimes overlap, sometimes quite dramatically differ from one kind of visual object to another, but in any case, the same object type is used. As a result, they all use the same copy of the virtual method table (vmt), less code duplication, and less virtual methods are required.

 

And I also used one very important technical trick that I invented while building XCL (at least for something my first library came in handy, although no, of course, without XCL and KOL there would not have been). Namely, when initializing objects, in no case should you initialize all possible fields (which, in turn, are objects). This operation should be postponed "for later" if possible. For example, when creating a visual object in KOL, the font for the window of this object is initialized to the smallest possible amount. That is, the font is "inherited" from the parent window object, while, in fact, a stub is called - a pointer to a function, which begins to point to a valid function only if at least one font parameter has been modified in the program. Of course, the likelihood that in his application the programmer will change the default font, in the usual case is great. But the case when a programmer uses KOL is unusual in itself: he says that the programmer does not want to add extra code to the program. And this means that the decision to initialize the fields should be postponed until the moment when such code is required in the application. Naturally, if there is such an opportunity.

 

In fact, the above technique would not have been possible without using a compiler that has the ability not to insert procedures and functions into the program code that are not referenced in the project (even if these procedures and functions are present in connected modules, involved classes / objects - if only they weren't virtual). This is exactly the ability Delphi has (Free Pascal too, but at the moment when I started KOL, there was no question of compatibility with Free Pascal, and there was no such compiler then - if I'm not mistaken). In Delphi, this ability is called smart-linking.

 

Unfortunately, this trick, as mentioned, does not work for virtual methods. As far as I understand this problem (and Delphi experts offered their understanding, and it sometimes differed), the reason is banally simple: since the reference to all virtual methods is already present in the vmt table of virtual methods of the class / object type, the method is counted as used, even if in reality, it is never addressed. For example, if another class "B" is inherited from class "A", in which this method is completely overridden, and there is no call to this method of the ancestor "A", and only instances of this inherited class "B" are created in the project modules. Anyway, since the link is already in the vmt table, the method will be "credited". So I decided to use the virtual method mechanism with great care.

 

KOL / MCK User Guide - Created by Carl Peeraer - Diamant Soft, based on the work of Vladimir Kladov - Artwerp.be

  

Keyboard Navigation

F7 for caret browsing
Hold ALT and press letter

This Info: ALT+q
Nav Header: ALT+n
Page Header: ALT+h
Topic Header: ALT+t
Topic Body: ALT+b
Exit Menu/Up: ESC