menu
  Home  ==>  papers  ==>  delphi  ==>  delphi_in_perspective   

Delphi in Perspective - Felix John COLIBRI.
Delphi's 25 the Anniversary




1 - The first Delphi Demonstration

In 1995, I was quietly continuing my usual Pascal life when Eric WYSS from Borland invited me to the presentation of a new product at the Borland Paris office. I met Zack URLOCKER for the first time and he presented me Delphi.

I could not understand what he was showing me. the Form, the Tool Palette, the Object Inspector, the OnClick event. How could have been so unprepared ?




2 - Here comes Delphi !

2.1 - Object Oriented Programming

It all started with the Object Oriented Programming revolution. The BYTE magazine had published in August 1981 a special edition about Smalltalk and object programming. Adele GOLDBERG.

08_1981_2

But since we did not have this construct in the Apple ][ UCSD Pascal, this was a pure abstract concept I did not fully understand the implications at the time. However the writing was on the wall.



Then, in January 1984, came the MacIntosh with Object Oriented Programming and the event programming paradigm. I purchased a Mac and even a Lisa, which was required to program the Mac. I also started to read the 3 "Inside MacIntosh" Addison Wesley books about the MacIntosh programming. But I did not finish the whole thing. MacIntosh was not for me: mainly a user audience, but no programming books, magazines, examples. Wonderfull tools for publishing (PageMaker was the buzz of the day) but nobody to buy books, attend training sessions or buy inventory or order processing software, which was my primary customer base. So I sold the Mac and the Lisa after 6 months, and still believe it was the right decision.

Nevertheless, the object concept was still very much discussed in our Pascal User Group. To finally understand the concept, I wrote and published in our Pascalissime magazine a Pascal pre-processor enabling the writing of object oriented code. Basically the pre-processor was building a VMT (Virtual Method Table: an Array of procedure pointers), thereby allowing inheritance and polymorphism. At that time the syntax was still unclear: should the method be implemented in the same bloc as the definition (as in C++ or Object Pascal) or separately in the Interface part, as was finally decided by Borland.

In 1989 Turbo Pascal 5.5 came out. 5.5 tells it all: so urgent as to require a new edition before the launch of "Turbo 6". I still remember David Intersimmone as he presented this version in Paris. It is also the first time Borland included in the documentation a tutorial to explain the object concept. I was told that even Philip KAHN presented this at conferences. He presented hierarchies showing pictures of plants and animals, fish and mammals, horses, cats and dogs. He then was frustrated that after the conference people did not talk about encapsulation or inheritance but only remembered that he had a dog !



2.2 - Turbo Vision

Turbo Pascal 6 came in 1991. The existence of objects allowed Borland to rolled out Turbo Vision: a DOS framework with windows, menus, "controls", all within an object layer. I personnally never really programmed in Turbo Vision. I could code whatever I needed using my own DOS menus, formulars, with input areas using some home cooked libraries. And was somehow too lazy to learn this new framework.

In addition the syntax was also a little bit "academic". To present 3 radiobuttons:

turbo vision

you had to write

R.Assign( , , , );

B := New 
      (PRadioButtons
        Init(R,
          NewSltem('-S-olid' ,
            NewSltem('-R-unny' ,
              NewSltem('-M-elted' ,
              Nil
      )))));

Insert(B

Even Lisp had come up with some shortcut notation avoiding the 5 closing parentheses !

However there is little doubt that the writing of this library helped the Borland team gain much experience in writing such big object oriented framework.



2.3 - Windows 3.1

A couple of years later, in 1992, Windows 3.1 came out. As ususal, Borland quickly offered a versions of Turbo Pascal enabling Window Programming. I immediately purchased the PETZOLD book, read the full book and then went thru all the examples and translated them in Pascal.

Using Windows basic APIs, to create a window, you had to

  • first register a new class for each window kind:

    (* -- définit une nouvelle classe si c'est le premier appel *)
    If g_instance_precedente = 0
      Then enregistre_classe(cs_vRedraw Or cs_hRedraw,
              @f_traite_message,
              k_pas_octets_classek_pas_octets_fenetre,
              g_instance,
              LoadIcon(k_icone_en_stockidi_Application),
              LoadCursor(k_curseur_en_stockidc_Arrow),
              GetStockObject(White_Brush),
              k_pas_ressource_menuk_nom_classe);

  • the procedure being:

    Procedure enregistre_classe(p_style_classeWordp_pt_fonction_messagesTFarProc;
        p_octets_classep_octets_fenetreIntegerp_poignee_instancetHandle;
        p_poignee_iconehIconp_poignee_curseurhCursorp_poignee_brossehBrush;
        p_nom_ressource_menupCharp_nom_classepChar);
      Var l_classetWndClass;
      Begin
        With l_classe Do
        Begin
          (* -- style: quand doit redessiner etc. *)
          style:= p_style_classe;
          (* -- la procédure de traitement des messages *)
          lpfnWndProc:= p_pt_fonction_messages;
          (* -- place supplémentaire dans la classe ou la fenêtre *)
          cbClsExtra:= p_octets_classecbWndExtra:= p_octets_fenetre;
          (* -- poignée de l'instance qui a enregistre la classe, pour pouvoir détruire *)
          hInstance:= p_poignee_instance;
          (* -- poignées de l'icône, du curseur et du fond *)
          hIcon:= p_poignee_iconehCursor:= p_poignee_curseurhBrBackGround:= p_poignee_brosse;
          lpszMenuName:= p_nom_ressource_menu;
          lpszClassName:= p_nom_classe;
        End(* with l_classe *)

        If Not RegisterClass(l_classe)
          Then Halt(255);
      End(* enregistre_classe *)

  • then you had to create a window (meaning the main window, a Label, a Button etc), with 14 parameters. Yes, 14:

    Var l_poignee_fenetreHWnd;
        l_messageTMsg;

      l_poignee_fenetre := CreateWindow(
          (* -- le nom identifiant la classe *)
          k_nom_classe,
          (* -- titre affiché *)
          k_titre_fenetre,
          (* -- le style *)
          ws_Overlapped Or ws_Caption Or ws_SysMenu Or ws_ThickFrame
              Or ws_MinimizeBox Or ws_MaximizeBox,
          (* -- la fenêtre par défaut *)
          cw_UseDefaultcw_UseDefaultcw_UseDefaultcw_UseDefault,
          (* -- la poignée de la mère *)
          k_sans_parent,
          (* -- poignée du menu *)
          k_poignee_menu,
          (* -- le numéro de cette instance *)
          g_instance,
          (* -- parametre de création *)
          k_pas_parametre_de_creation);

  • and, to react to the events, you had, for each window, to create a special WinProc procedure with the code for each of the events you wanted to handle:

    Function f_traite_message(p_poignee_fenetreHWnd;
        p_code_messagep_w_paramWordp_l_paramLongint): LongintExport;
      Var l_appeler_defautboolean;
          l_resultatlongint;

      Const ls_largeur_caractereWord= 0;
            ls_hauteur_caractereWord= 0;

      Procedure traite_wm_create(p_pt_create_structurepCreateStruct);
        Var l_poignee_contexte_ecranhDC;
            l_metriquetTextMetric;
        Begin
          l_poignee_contexte_ecran:= GetDC(p_poignee_fenetre);

          SelectObject(l_poignee_contexte_ecranGetStockObject(System_Fixed_Font));
          GetTextMetrics(l_poignee_contexte_ecranl_metrique);
          With l_metrique Do
          Begin
            ls_largeur_caractere:= tmAveCharWidth;
            ls_hauteur_caractere:= tmHeight;
          End(* with l_metrique *)

          ReleaseDC(p_poignee_fenetrel_poignee_contexte_ecran);
        End(* traite_wm_create *)

      Procedure traite_wm_l_button_down(p_bouton_ou_toucheWord;
            p_xp_yinteger);
          (* -- p_bouton_ou_touche (p_w_param): indique les touches / boutons enfoncés *)
        Var l_poignee_contexte_ecranhDC;
            l_ligneWord;

        Procedure affiche(p_rougep_vertp_bleup_rouge_fondp_vert_fondp_bleu_fondByte;
            p_texteString);
          Begin
            SetTextColor(l_poignee_contexte_ecranRGB(p_rougep_vertp_bleu));
            SetBkColor(l_poignee_contexte_ecranRGB(p_rouge_fondp_vert_fondp_bleu_fond));
            affiche_chaine(l_poignee_contexte_ecran, 0, l_lignep_texte, 20);

            SetTextColor(l_poignee_contexte_ecranRGB(p_rouge_fondp_vert_fondp_bleu_fond));
            SetBkColor(l_poignee_contexte_ecranRGB(p_rougep_vertp_bleu));

            affiche_entier(l_poignee_contexte_ecran, 21* ls_largeur_caracterel_lignep_rouge, 5);
            affiche_entier(l_poignee_contexte_ecran, 26* ls_largeur_caracterel_lignep_vert, 5);
            affiche_entier(l_poignee_contexte_ecran, 31* ls_largeur_caracterel_lignep_bleu, 5);

            inc(l_lignels_hauteur_caractere);
          End(* affiche *)

        Begin (* traite_wm_l_button_down *)
          l_poignee_contexte_ecran:= GetDC(p_poignee_fenetre);

          SelectObject(l_poignee_contexte_ecranGetStockObject(System_Fixed_Font));
          l_ligne:= 0;

          affiche(0, 0, 0,    255, 255, 255, 'noir / blanc');
          affiche(255, 0, 0,    0, 255, 0, 'rouge / vert');
          affiche(0, 0, 255,    0, 255, 255, 'bleu / bleu-vert');
          affiche(255, 0, 255,  255, 255, 0 ,'violet / jaune');

          ReleaseDC(p_poignee_fenetrel_poignee_contexte_ecran);
        End(* traite_wm_l_button_down *)

      Procedure traite_wm_destroy;
        Begin
          (* -- demande à Windows d'envoyer wm_Quit à notre instance *)
          PostQuitMessage(0);
        End(* traite_wmDestroy *)

      Begin (* f_traite_message *)
        (* -- par défaut, si traite un message, retourne 0 à Windows *)
        l_resultat:= 0;
        (* -- par défaut, si traite un message, il ne faut pas appeler DefWindowProc *)
        l_appeler_defaut:= false;

        Case p_code_message Of
          wm_Create : traite_wm_create(Pointer(p_l_param));
          wm_lButtonDowntraite_wm_l_button_down(p_w_param,
              t_long_integer(p_l_param).lot_long_integer(p_l_param).hi);
          wm_Destroytraite_wm_destroy;
          Else (* -- pour toutes les commandes non traitées dans le case: *)
            l_appeler_defaut:= true;
        End(* case p_message *)

        (* -- traite ici les messages non traités dans le CASE *)
        If l_appeler_defaut
          Then f_traite_message:= DefWindowProc(p_poignee_fenetrep_code_message,
              p_w_paramp_l_param)
          Else f_traite_message:= l_resultat;
      End(* f_traite_message *)

  • now you could see the window:

    (* -- affiche la fenêtre en effaçant la zone client *)
    ShowWindow(l_poignee_fenetreg_allure_initiale);
    (* -- envoie wm_Paint pour redessiner la zone client *)
    UpdateWindow(l_poignee_fenetre);

  • and you had to write your own event polling loop:

    (* -- la boucle de recuperation et de ventilation des messages *)
    While GetMessage(l_messagek_toutes_fenetresk_message_mink_message_maxDo
      (* -- appelle la procédure de traitement *)
      DispatchMessage(l_message);



Just imagine a window with 10 or 20 labels, edits, buttons and you get an idea of the magnitude of the task.



From a teaching point of view, I was quite a happy man though: this thing was so new and convoluted that my Pascal Windows Api programming book was selling reasonably well, and my training were a success. I had up to 20 persons in our little training room.



2.4 - Visual Basic

At the same time, there were rumors of a Visual Basic thingy. Any feller could have a window with a couple of controls and some code in 15 minutes sharp. With Pascal, to explain the window creation and the WinProc to my students took me about 3 hours. Just to display Hello ! Obviously the Visual Basic folks had come up with a revolutionary concept. We assumed Borland would sometime follow up.



2.5 - Delphi

And the answer was Delphi !

Just after the first presentation by Zak, I ran to the nearest store and purchased a Visual Basic edition to understand the concept. Unsurprisingly I did not like the untyped language, but could grasp what the Form - Palette - Object Inspector were all about.

Shorlty after that Eric WYSS sent me the beta version discs (I thing there were 10 or 15 of those 3 1/2" floppies) to install the product. There was no documentation, so I decompiled the Help, printed the whole thing and was jumping up and down in our training room to reorder the pages and assemble some kind of manual.




3 - Delphi in retrospect

The concept was clearly the Visual Basic one. In addition, Delphi added
  • a compiled mode (VB was interpreted)
  • the possibility to write components in the language (VB required the use of C or C++)
  • the full source code of the VCL to start the component movement rolling
The first beta was called VBK : Visual Basic Killer. It did not kill Visual Basic, but I could not care less: we had a wonderfull product.



Behind the scenes, some more subtle concepts

  • all data was dynamic. This is a must for any windowing system. Lets take a simple menu: how many columns: it depends. How many lines in each column: impossible to tell. So dynamic data is necessary. In Pascal parlance, this means pointers. However pointers were taught in the last chapter of all books, being advertised as difficult to program. Since Borland wanted to capture the Visual Basic market, pushing pointers at the forefront seemed too frightening. I believe that pointers, explained correctly, are quite easy to use. Additionnally, VB programmers could have managed the shock. Anyway, Borland decided to hide the pointers, and presented the "reference model": Button1 is the pointer, Button1.Left is the pointed Left field (instead of Button1^.Left) And all data was encapsulated in objects. This certainly added some derived contortions, like using Assign to test if an object is not Nil, but this is a small price to pay in exchange of a single "all objects are pointers" model.

  • Borland did a superb job at hiding the complexity. The first thing the programmer sees ("File | New | Vcl Form") is a tForm:

    Unit Unit1;
      Interface
        Uses WindowsMessagesSysUtilsVariantsClassesGraphicsControlsForms,
            Dialogs;

        Type
             TForm1 =
                 Class(TForm)
                 End// tForm1

        Var Form1TForm1;

      Implementation

        {$R *.dfm}

      End.

    Right from the start you have

    • Units which are already a kind of abstract type with the Interface / Implementation separation
    • libraries (Uses)
    • objects (Class),
    • inheritance (tForm1= Class(tForm) )

    and yet I never encountered any difficulties to present this as the first contact with Delphi .

  • if you follow the Window organization, or the Turbo Vision framework, each control should be a separate Class. So a single button should be a descendent of the basic ancestor tButton

    Unit Unit2;
      Interface
      Uses  WindowsMessagesSysUtilsVariantsClassesGraphicsControls,
          FormsDialogs;

      Type
          TButton1=
            Class(tButton)
              ClickOverride;
            End// TButton1

          TForm2 =
            Class(TForm)
              Button1TButton1;
            End// TForm2

        Var Form2TForm2;

        Implementation

        {$R *.dfm}

        Procedure TButton1.Click;
          Begin

          End// Click

      End.

    In fact, the fields of Button1 are static (usually not changed during the execution), and the only differences between tButton and tButton1 are the events. Hence the "event delegation": tButton 1 delegates the OnClick event to the tForm1, and the Sender parameter enables to test who triggered the event, should you decide to share the event:

    Unit Unit1;
      Interface
        Uses WindowsMessagesSysUtilsVariantsClassesGraphicsControlsForms,
            Dialogs;

        Type
             TForm1 =
                 Class(TForm)
                   Button2TButton;
                   Procedure Button1Click(SenderTObject);
                 End// tForm1

        Var Form1TForm1;

      Implementation

        {$R *.dfm}

        Procedure TForm1.Button1Click(SenderTObject);
          Begin

          End// Button1Click

      End.

    Just imagine our forms today with 50 or 100 controls: the "traditional" solutions would overpopulate your Unit with 50 or 100 Classes with just one or two events (versus a single tForm Class with 50 OnClick events).

    Anders HELJSBERG brought this concept with him when he left Borland to join Microsoft an create C#. To the disappointment of the Java community where each new button should be a descendent of the bacic tButton

    Also take the time to compare the current Delphi solution to print Hello ! to the Windows API solution presented before !

  • on the marketing front, the main decision was to include database access.

    When Philip KAHN launched Turbo Pascal, the price was $ 49.95. This was more than double the JRT Pascal (19.95 ), but which was compiling on disc and way too buggy. UCSD was over $ 1.000. However at $ 49.95 apiece, increasing the company turnover was not that easy. Adding add-ons, like a small worksheet, games, numeric libraries or a Logo compiler, each below $ 100, did not help much. At the same time Mich KAPOR was selling $ 800 Lotus packages.

    Visicalc is the software which made the Apple ][ a success. All those Californian execs which had to wait monthes for the central data processing department to add this other column or that additional field in their monthly reporting system. With Visicalc and some typing they could get whatever data massaging they needed within a couple of hours.

    PowerBuilder was a very popular Windows product at the time: "non programmer" could build a small business application (invoicing, inventory management, accounting etc)

    Therefore integrating database access in the product really was a fabulous decision.

    Borland had already purchased Paradox, acquired the dBase product (which was struggling because they could not build an SQL engine) and integrated Interbase. The gathering of those became the BDE with access to all popular databases thanks to ODBC.

    We could still write Text Editors (like the one I am using to write books, .PDF letters, or the articles of this web site), assemblers and interpreters of all kinds, scientific software, drilling machine controllers etc. But it is on the business side that the money is: budgeting, payrolls, factory scheduling, etc.

    The bank robber Willie Sutton was may times arrested, and someone asked him one day: "why do you continue to attack banks over and over again ?" and he answered "but that's where the mouney is !"




4 - The Delphi evolution

We hardly started to get familiar with Delphi, and already Borland had Delphi 2 in the pipeline. In fact the 32 bit version was developed at the same time as Delphi 1. Windows 95 allowed 32 bit programming, and we could get rid of the Windows over DOS solution.

Delphi 3 to 7 continued to follow the market evolution, mainly with the introduction of Sockets, Internet, SOAP Web Services and XML. Some people still believe that Delphi 7 was an improvement over its predecessors and is better then its successors !

Around 2005, Delphi tried to follow the C# revolution. Delphi 8 allowed some compilation, Delphi 2006 and following added C#, Vcl Net, Asp Net. But with the coming years those were gradually dropped from the product.

Then in 2009, came the Unicode breaking change. This was a mixed blessing. People had to migrate their application. We wrote a couple of papers about Unicode and the migration process. And we still have an active market with the migration business. But on the same time it forced many companies which were quite happy with Delphi 7 to upgrade their tool. One must understand that Borland, or CodeGear, Embarcadero, Idera for that matter basically must sell products each and every year. So the Unicode change somehow forced this purchase. The new trend to subscription systems will hopefully alleviate the problem.

Then came the phone revolution. I certainly did not anticipate this one. In retrospect, it is fascinating to see how they managed the whole process :

  • for Delphi 2011, nothing much new. Some external tools were added (Beyond Compare, Aqtime, CodeSite etc). I guess those were thrown in to keep the community buying the new version, as the phone framework was not yet fully complete
  • then in 2012, FireMonkey with iOs and iPhone
  • after that gradually Android
Other features were added, some of which I am not to familiar with (the Cloud, BAAS, IOT etc)

However the addition of the Interface concept and the inclusion of unit tests remain two key points of the last 10 years.

There are two other points I consider important:

  • UML and Object Oriented analysis and conception : this does not depend on the Delphi framework, but is an evolution compared to the first step "do it all in the main form" trials we all used in the beginning. Together is a reasonable UML tool, has a very nice Design Pattern generation feature and was helpful when the ECO (Enterprise Core Object) object persistence framework was included in Delphi. But I am not sure UML is still used by many Delphi developers
  • REST allows web services, but the main point is microservices, which is a step beyond Service Oriented Programming. Micro services can be implemented using REST, and many Delphi frameworks or simply Indy (or any other HTTP library) can be used.


4.1 - Some Mishaps

Of course, along the road, there were some mishaps
  • the Kylix Linux version
  • the gradual dropping of the .Net features
  • the BlackFish in memory database
  • then ECO framework (the Borland adaptation of the BOLD object persistence library)



5 - The Delphi Future

Since 1990, people keep asking me what the future of Borland / Delphi will be. I have no idea. As Niels BOHR is supposed to have said "prediction is difficult, especially the future"

If Delphi were to disappear have we, or have I other alternatives ?



5.1 - C++

Some still advertise C++ as THE solid professional language. The same propaganda we had in the early Pascal days.

Well just a short story. I had to build a Delphi interface to the MORPHO (now IDEMIA) framework, which offers fingerprint capturing devices. The whole system offers C++ DLLs containing C++ Classes. So I used the very nice articles by the late and very much regretted Rudy VELTHUIS explaining how to access C++ classes from Delphi, either flattening the Classes or building a COM wrapper. I first used Borland  C++. Encountering mistakes, I assume the DLL was not compiled with the Borland C++. I tried to translate the .LIBs (obj format differences) or adding .DEFs (taking care of name mangling). Just imagine: the business of a C++ compiler is to mangle names. Then you have to unmangle thoser if you use another compiler (or perhaps remangle them differently before dismangling them). At the end I had to accept that interfacing C++ objects in a DLL built with another C++ compier from Borland C++ builder is next to impossible (at least for me). I finally downloaded the free Visual Studio, and it took me a full week to get this thing working. Incompatibility between compilers, gadzillion of files, all kind of macros to avoid double compilation, add prefixes, qualifiers and what not. Boy am I happy to now manage this thing in Delphi !



5.2 - PHP, perhaps ?

My book printer hired a student to build his on-line catalog. When this student started to slowly stop answering his update requests, I tried to help him. This would a good opportunity to look at PHP. Well, it took me over an hour to find out how to write "next week". In Delphi : my_date_time +7

This taught me that Delphi proficiency is not only concepts (OOP, REST etc), syntax and grammar, but also the memory of a huge run time library. Using another system will require some effort to learn the way we can accomplish some mundane tasks as "in a week"



5.3 - Or Python, maybe ?

Python is another possibility.

Many advertise Python as a quick prototyping system. In 10 lines of code you can try new concepts, like Deep Learning.

I tried. You can find loads of examples of how to recognize images or forecast the stock market. GitHub is full of them. Now to make those work, you often have to add huge libraries to your basic Python system. Fair enough. At this stage, Python is just a thin scripting layer calling many scientific libraries like TensorFlow. But installing some additional library can ruin your current Python installation. So they invented Docker: you save Python and the library for project  1, then save Python and some other library for project 2 and so on.

This makes me think of the people who invented the Lint or the Debuggers to be able to run some C programs: the compiler does not check anything because, being a C system programmer, you surely will not do any mistakes. But if things go wrong, just use Lint or the debugger to find out (what a simple Pascal compiler would have detected in the first place). The Compiler won't let you shoot yourself in the foot !

However, Deep learning still looks like an immense opportunity. There already are some Delphi projects allowing to create CNNs (Convolutional Neural Networks) LSTMs (Long Term Short Term Memory), and some attempts to interface with TensorFlow.

But would it not be wonderful if Delphi integrated such functionalities ? Sure this is not in the current "general framework" positioning of the product. But this is a gigantic market, and it is the future. I have a dream ...



5.4 - Conclusion

40 years in the business allow me to draw some conclusions:
  • Pascal and Delphi are the right tools for me. Meandering in untyped languages with all kind of behind the scenes second guessing and inferencing leave me profoundly unhappy.
  • Delphi is the most productive tool I know, covering the full spectrum from assembler to design patterns
  • from a commercial point of view, selling a Delphi development might still be an uphill battle. But if you are convinced of the quality of the tool, it is easy to explain the benefit of using Delphi to your customer
  • hiring Delphi developper, or even convincing Java developers to work on Delphi project still remains difficult today. The free community edition, or even the "Best Delphi App" competitions certainly are steps in the right direction. Writing books, publishing a magazine, and now writing articles is my small contribution to help bring more people aboard



6 - Some Links

Here are some references and links

And on our side
  • Pascalissime our French Pascal / Delphi magazine
  • Pascal and Delphi Books : some of the books I wrote
  • Unicode Migration : explaining Unicode and the Delphi 2009 Unicode migration steps
  • Rest Web Services OAuth2 Tutorial : Delphi DropBox Rest Service Client using the OAuth2 protocol. Implemented with the tRestClient Delphi components or Indy tIdHttp component. Get the DropBox token, list the files, download and upload files
  • Delphi Mobile Point of Sale Software : Android tablet or smartphone point of sale application using a WIFI connection to a DataSnap REST Server connected with FireDac to a FireBird database



7 - The author

Felix John COLIBRI works at the Pascal Institute. Starting with Pascal in 1979, he then became involved with Object Oriented Programming, Delphi, Sql, Tcp/Ip, Html, UML. Currently, he is mainly active in the area of custom software development (new projects, maintenance, audits, BDE migration, Delphi Xe_n migrations, refactoring), Delphi Consulting and Delph training. His web site features tutorials, technical papers about programming with full downloadable source code, and the description and calendar of forthcoming Delphi, FireBird, Tcp/IP, Web Services, OOP  /  UML, Design Patterns, Unit Testing training sessions.
Created: feb-20. Last updated: feb-2020 - 105 articles, 240 .ZIP sources, 1295 figures
Contact : Felix COLIBRI - Phone: (33)1.42.83.69.36 / 06.87.88.23.91 - email:fcolibri@felix-colibri.com
Copyright © Felix J. Colibri   http://www.felix-colibri.com 2004 - 2020. All rigths reserved
Back:    Home  Papers  Training  Delphi developments  Links  Download
the Pascal Institute

Felix J COLIBRI

+ Home
  + articles_with_sources
    + database
    + web_internet_sockets
    + rest_services
    + oop_components
    + uml_design_patterns
    + debug_and_test
    + graphic
    + controls
    + colibri_utilities
    + colibri_helpers
    + delphi
      – rad_studio_resources
      – the_turbo_pascal_story
      – induc_a_virus_anatomy
      – firemonkey_styles
      – delphi_xe3_info
      – ios_preview_summary
      + conference_reports
      – delphi_in_perspective
    + IDE
    + firemonkey
    + compilers
    + vcl
  + delphi_training
  + delphi_developments
  + sweet_home
  – download_zip_sources
  + links
Contacts
Site Map
– search :

RSS feed  
Blog