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.
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.
|
Connect with Us