Delphi 2 - A Survival Guide to Migrating Applications to Delphi 2.0

By: Borland Staff

Abstract: In this article we will examine this porting process, pointing out pitfalls that should be avoided and giving guidance on finding the fastest, least painful way to your next release.

A Survival Guide to Migrating Applications to Delphi 2.0
By Illis Piter (Peter Illes)

NOTE: The views and information expressed in this document represent those of its author(s) who is solely responsible for its content. Borland does not make or give any representation or warranty with respect such content.

This symbol will indicate issues that are specific to Delphi 2.0. The rest is true for all development platforms.

    Abstract
    Introduction
    Part I: Managing the Porting Process Part II: Porting Issues
    Windows General Issues
    Delphi Common Issues
    Miscellaneous
    Conclusion
    References


    Abstract

    Delphi 2.0 is the most powerful RAD tool available today. The optimizing compiler produces first class Win32 code. The support for OLE Automation, the even faster scaleable database technology, native support for OLE controls (OCXs), the complete support for the Windows 95 user interface, and advanced features like multi-threading and MAPI, make it the choice of platform for many new and improved applications. Borland did a lot to assure that most of the Delphi 1.0 code simply recompiles. But - mainly due to the differences between Win16 and Win32 - it takes a little more than just recompiling to port your non-trivial ("legacy") code to this new platform. And even some sorcery to continue supporting Win16, and maybe MS-DOS for a while (one or two years) with the same code base. In this article we will examine this porting process, pointing out pitfalls that should be avoided and giving guidance on finding the fastest, least painful way to your next release.


    Introduction

    Delphi was a magnificent success in 1995 due to its combination of an established, easy to learn yet flexible object-oriented programming language (Object Pascal), a world-class Rapid Application Development environment, and its extensive support for Client/Server and database development. Meanwhile we have witnessed the dawn of the Win32 age by Microsoft's introduction of Windows 95. The successor of Windows 3.x is actually the third Win32 platform, but its predecessors (Win32s and Windows NT) could not achieve the critical mass that is necessary to transform the whole industry. The situation right now closely resembles the dawning of the Windows era. Many members of the industry (analysts, journalists, managers, and developers alike) were skeptical about Windows 3.0 and not willing to jump on the bandwagon. And in a year or so, most MS-DOS based applications became obsolete, and many companies lost their leadership positions because they didn't have a Windows version of their most popular apps. Now the industry is transforming again and it is time to start working on the Win32 version of our applications. That's why it is so important for us that Borland is introducing the second generation of its RAD product line, Delphi 2.0 - the most powerful Win32 RAD tool available today.

    Many of us have managed transformations like this before (at least from DOS to Windows) and still others will face this challenge the first time. To be successful in the porting process one should go on in an orderly fashion. We'll introduce an organized approach that will result in early success with a robust architecture for future refinements. In order to do so we'll define the starting points, target platforms, porting goals, and stages of porting in Part I. In Part II we're getting into details of general Win16 to Win32, and specific Borland Pascal and Delphi 1.x to Delphi 2.0 conversion issues. We will also visit critical Win32 concepts (processes, threads, flat memory, etc.) briefly in this part. We won't delve into some areas of porting (notably database issues) and won't touch stage 2 of the porting process and beyond (see Part I for an explanation of stages) in this article due to space constraints. For an extended explanation see our whitepaper, or other references included at the end of the article.

    You should be aware of the fact that most porting issues discussed here are rooted in the changes introduced by Win32. We could treat them in an abstract sense (independent of a development platform) but decided to show all issues with a Delphi perspective - so you can put them into practice right away.

    Let's introduce some notations before we go on. DOS stands for any incarnation of the old Disk Operating System used on IBM PC compatibles (MS-DOS, PC-DOS, DR-DOS, etc.). Win16 stands for Windows 3.0, 3.1x, and Windows for Workgroups 3.11. Win32 should denote the new 32 bit API. WinNT stands for Windows NT 3.51 or later and Win95 means Windows 95 build 950 (the August release) or later.

    Now, let's start our quest.


    Part I: Managing the Porting Process

    Where are You Coming From?
    Thanks to Borland's 13+ years of success with Pascal, you may come from different environments. Here are the most typical scenarios:

    • Real mode or Protected mode DOS - Turbo Pascal or Borland Pascal. Yes, there are still some of us out there who will make the Transition now. You'll have the most work to do, but you may be at an advantage as you don't have to learn the internals of Win16 and you can start exploiting the power of Win32 right away. You don't have to face the steep learning curve generally associated with Windows programming due to the fact that you are going to use a RAD tool that will hide most of these details. Many very useful applications can be created without digging deep into the Windows API. Most of your code may have to be re-written, but you can save the engine of your apps, and even your user interface architecture, if you were using an event-based approach (e.g. Turbo Vision). We were able to port a DOS (Protected mode) app's core with a functioning user interface (it was a CAD type app!) without architectural alterations in a month... You'll have to update your object oriented programming knowledge since it is a norm in Delphi, but you can get along easily with the Delphi manuals. You also need some good books on Win32 programming. Don't forget to study and implement user interface design principles, as your UI will be a major factor in your success or failure in this user-centric world. And Chapters 19, 20, and 21 (among the others) of Delphi Developer's Guide from Xavier Pacheco and Steve Teixeira is a must-read for you - it will have some detail on moving from DOS to Delphi that we cannot cover here due to space limitations. See the References section for sources of information.
    • Windows API or Windows OWL - Turbo Pascal or Borland Pascal for Windows. You have an established understanding of the Windows architecture, and the Win16 APIs, so you can focus on the differences between Win16 and Win32. With smart approaches you can save most of your work. The core of another CAD product of ours was ported from BP7/OWL to Delphi 2.0 in 2 weeks (if we omit the concept development of porting, doing the RTL70/Objects.Pas port, etc. - things that you don't have to repeat). Of course we have since spent a lot of time fine-tuning and re-implementing portions that can be done better now. But it did work. You may also find the Delphi Developer's Guide a valuable tool.
    • Windows VCL - Delphi 1.x. According to Borland, you have to do the following: Use File|Open to open your project and Project|Compile to have a 32 bit version. Period. Now the interesting thing is that it's basically true. If you have kept with Delphi 1.x without reverting to the Win16 API, assembly and inline programming, depending too much on the size of variables, etc. you will get a Win32 app right away (except some tiny changes). And if you did utilize features like that, you're still far ahead of the rest of us in getting into the 32 bit world - most of your code is Win32 ready. Borland did plan ahead in architecting Delphi 1.x so that the transition shouldn't be a big effort on your side (they have done most of the porting for you in Delphi 2.0 and the new VCL).
    No matter where you are coming from, you can be assured: you have the easiest job getting into the Win32 world. Delphi 2.0 is a unique opportunity for you.


    Where are You Going To, and How Far?

    32 bit Windows? Which one? Win95 or Windows NT? Do you want to just have your application run on these platforms, or to take full advantage of their new features?


    Where To? The 3 Versions of Win32
    Win32 does not denote an environment or operating system, it denotes an Application Programming Interface (API) specification, implemented by at least three platforms:

    • Win32s - the extension of Win16 with a minimal subset of the Win32 API. It is a set of DLLs and support files that can be freely distributed by software publishers to support their applications on Win16.
    • Windows NT - the full implementation of the Win32 API on many types of hardware, including x86, Alpha, and MIPS processors. It also supports multiple processors, that is, it can run "threads" (the unit of execution in Win32 parlance) simultaneously. It is a completely new, robust design from the ground up, but it requires hardware that won't get into mainstream usage for some more time, so many developers won't target it specifically in the short run.
    • Windows 95 - the mainstream implementation of Win32 for x86 processors, with most of the original Win32 API functionality plus some additions that will be introduced in the next release of Windows NT, too.
    Win32s is mostly considered obsolete now with the release of Windows 95. Its limitations are so numerous that it's best to forget it completely as a possible platform. Also, Delphi 2.0 does not support Win32s development: the RTL would require adjustments. So you should decide between Windows NT and Windows 95. Fortunately, in most cases this means that you don't have to decide at all, since you can have the same binary code running on both platforms (on x86 architectures). Windows 95 is the mainstream Win32 implementation, so if you develop consumer-type or (hardware) cost-sensitive applications, you should target this platform. If you are developing heavy duty applications, like high-end CAD, (client/)server databases, Internet server apps, etc., you should choose Windows NT for its robustness and power.

    Another question is: we have to hurry with the porting project, but how much? By the time of writing, there are only some hundred apps with the Windows 95 logo, and only some thousand apps that are for Win32 specifically. And there are tens of thousands of apps that are still for Windows 3.x. There are 10 million copies of Windows 95 sold, whilst there are 50+ million copies of Windows 3.x out there. But you should not be confused by these numbers. The major players no longer develop apps for Win16. 1996 will be the year of Win32 and you should act right now.

    A final word on platform selection: for some time you may have to support your Windows 3.x users (given the numbers above). That means that you will have to manage to keep either a common code base for both Win16 and Win32, or even worse, keep in sync two code bases. We will return to this question later.

    How Far? Three Stages of Porting
    There are three well separated stages of porting to any platform. In our particular case these are the following:

    • Stage 1: Run on the platform. This means that you can successfully compile you program with Delphi 2.0 and it runs as expected. The rest of this article will mostly deal with this problem.
    • Stage 2: Behave as a native application on the platform. In our case this means Windows 95 logo compliance, including: OLE support, Registry usage, using the right mouse button for context menus, etc.
    • Stage 3: Exploit the platform to achieve the best possible performance. This may include multithreading, overlapped I/O, Unicode, memory usage optimizations, etc.
    Of course, you don't have to precisely follow these stages. Go whichever way your application's needs lead you. This may mean that you re-design the data structures of your application at once to take advantage of the flat memory model, though this activity belongs to stage 3. You most probably will start using the common dialogs at once (Delphi will does this for you), though this is a stage 2 process.


    Key Elements of Successful Migration

    Our experience has shown that both managers and developers have roughly the following considerations when porting applications (some of these considerations apply only if you are not coming from Delphi 1.x - if you are, you are in a much better position):

    • Do it as fast as possible. This is an ever-lasting request from management. As competition is increasing in the industry, it is getting more-and-more important to be there before the competitors.
    • Save as much code as possible. This is the only way to satisfy the above point. By smart decisions you can spare a lot of time and coding. Without porting the RTL70 core we should have had to re-implement most of our old apps. And with minimal trickery around the OWL dispatch mechanism we saved parts of even the user interface code (we did re-create the user interface in Delphi, but were able to save the dispatch mechanism and architecture).
    • Have code that compiles as early as possible. This will please both management and the developers. You are dead if you have to wait 2 to 3 months (or more) for a complete rewrite before you can start compiling. Instead, compile with the necessary fixes in 3 or 4 days, then start building the skeleton anew in Delphi (while your whole app is still compiling!) and add the converted engines, dialogs, etc. step-by-step. You can compile-run-test-debug-compile-... whenever you want, to find design problems, etc. This approach will help you greatly. You will be able to split the conversion among many developers and test the new parts as soon as they are ready.
    • Have backward compatibility with versions of apps on older platforms (e.g. DOS, Win16). You have DOS and Windows 3.x apps. How do you make bug fixes in two (or three) different code bases? Have one engine code for all the target platforms. Engines typically don't exploit the features of an environment. So find the least common denominator (this may mean Delphi 1.x features, as it can compile DOS code too) and use it in your code wherever possible.
    • Become as fully compliant with the new environment as possible. You won't want to support OWL any longer, since Borland discontinued it for the Delphi product line. VCL is the future: Borland will continually add new features as they have demonstrated it with Delphi 2.0 (enhanced OLE, better database support, etc.). You'll definitely be in a better position to achieve a Stage 2 or 3 port (see the next section for an explanation of stages) with the support of the development environment. On the other hand you may be forced to use a mixed object model, as replacing old type objects with new ones is a difficult and error prone process if you have a more than trivial object architecture. Fortunately, Delphi 2.0 has a solid implementation of the old type objects.
    We will have detailed discussions about achieving the first three points, and will touch the latter two to a certain extent.

Server Response from: ETNASC04