Wiki copymirror

This is a mirror of the wiki at pascal.chat. Editing, history and sign-in are there.

The Power of Proper Planning and Practices

English · Français · Português

Plan for cross-platform up front

See also:

There are several advantages to doing your development in a cross-platform way. Probably the most important advantage is that it can result in better, more reliable software. This is because cross-platform development requires that you spend more time planning your software before you start writing code. It also forces you to develop good programming habits, to test your software more, and to develop a more disciplined approach toward what you're doing. These things (planning, testing, discipline) tend to spill over into other aspects of your development, resulting in still more improvements in design and reliability.

Another advantage to cross-platform development is that it exposes you to other platforms. For example, many Windows developers and probably all Linux developers could benefit from some time spent simply using a Mac as a way of developing an appreciation for software ease of use and aesthetics. And many Windows developers could benefit from seeing how Linux tends to use text files and scripts for many things, without any loss of application performance.

A third advantage to cross-platform development is that it is by definition inclusive, which forces you to consider your users more than most single-platform programmers do.

The best way to make an application cross-platform is to design it to be cross-platform. If you plan on adding cross-platform support to your finished application later, you may find that you'll have to rewrite parts of it or, worse, find yourself in a Windows-only cul-de-sac that makes adding cross-platform support difficult or impossible.

If you've already developed an application for Windows with Delphi, it's possible in some situations to convert it to cross-platform app without starting over. If you want to do a one-way conversion of your Delphi code and forms to Lazarus, you can use some of the conversion commands on the Lazarus Tools menu. You can also convert your Delphi app to Lazarus, but retain Delphi compatibility (see this [[XDev Toolkit|link] for more information).

Separate code into UI and non-UI units

See also:

Probably one of the most important programming practices you can employ with any application, whether cross-platform or not, is to divide your code into user interface (UI) units and non-user interface (non-UI) units. In general, this means that your non-UI units should not implement any of the program's user interface and your UI units should not contain any of the computational or database parts of the program. In practice, a good way to enforce this separation is to require that the units you develop only use units that are appropriate to their side of this "divide". For example:

Follow the example of the Free Pascal and Lazarus units themselves, where general-purpose units like SysUtils, Classes, Variants and LazUtils don't use any LCL units and LCL units like Forms and Controls don't supply any general-purpose routines.

There are several advantages to dividing up your code like this. For example, it means that you will be able to use your non-UI units in any type of program, whether a GUI app, library, console app, even a Web app, without making any changes to the code. And it also means that if necessary you could develop a completely different user interface for your program or switch to a different UI library or control without changing the underlying non-UI code. It's also critical that this partitioning be done in large projects so that multiple developers can work on different parts of the program without stepping on each other's toes.

You may also find it helpful to further subdivide your non-UI code. For example, you might want to put all database access code in one set of units and all business logic and number-crunching code in another set of units. In addition, you might want to put all platform-dependent code (shelling, registry, clipboard, etc.) in its own set of units to isolate that code and make it easier to port to other platforms.

Use batch files and shell files

Even though Lazarus allows you to edit and compile code and set most compiler switches without ever leaving the IDE, you'll probably find it useful to create several batch files for each project. Batch files are just special text files containing console commands; you create them with a text editor. With Windows, batch files have a .bat or .cmd extension; with OS X and Linux, batch files have an .sh extension. You typically run a batch file by entering its name in a console window, as follows:

With Windows:

text
 mybatch.bat

Note that you can omit the .bat extension if there's no .exe file with the same name.

With Unix:

text
 ./mybatch.sh

There are many way that batch files can be used in development. For example, you might have one set of compiler options that you use during development and another set that you use to create the executable that you distribute. Here's an example of a command you can put in a batch file that runs the Free Pascal compiler.

On Windows:

dos
c:\lazarus\pp\bin\i386-win32\fpc.exe -Sda -Cirot -gl %1

On Unix/Linux:

bash
/usr/local/bin/fpc -Sda -Cirot -gl $@

The above command compiles the unit or non-GUI program specified on the command line with Delphi compatibility, assertions, I/O checking, range checking, overflow checking, stack checking, and line number tracing turned on. Note that you can add additional pre- and post-compile commands to a batch file. For example, you could run the strip.exe utility to shrink the size of your executable or copy the executable to a different folder for testing.

Here's a similar command that you can put in a batch file to compile a GUI program that you specify on the command line:

Note: The examples below directly call the FPC compiler. It may be easier to use lazbuild which will let you compile Lazarus projects for you without any need to set include paths etc

On Windows (all on one line):

dos
c:\lazarus\pp\bin\i386-win32\fpc.exe -dLCL -WG -Sda -Cirot -gl -Fuc:\lazarus\lcl\units\i386-win32;c:\lazarus\lcl\units\i386-win32\win32 %1

On OS X:

bash
/usr/local/bin/fpc -dLCL -WG -Sda -Cirot -gl \
-Fu/usr/local/share/lazarus/lcl/units/powerpc-darwin \
-Fu/usr/local/share/lazarus/lcl/units/powerpc-darwin/gtk \
-Fl/usr/X11R6/lib/ -Fl/sw/lib/ $@

How to avoid using a debugger

See also:

Using a debugger is rarely much fun. It often means that you've given up trying to figure out what's wrong with your program and have turned to the debugger as a last resort. Here are some simple techniques that you can employ that will help minimize your use of a debugger:

pascal
try
  raise Exception.Create('Exception here');  
except
  // Handle exception here.
  {$IFDEF FPC}
    WriteLn(BackTraceStrFunc(ExceptAddr));
  {$ENDIF}
end;

The {$IFDEF} and {$ENDIF} lines ensure that you can compile this code with Delphi too.

How to avoid disappointing your users

See also


From the Free Pascal wiki, page "The Power of Proper Planning and Practices", as it stood on 2020-04-08 after a change by Jwdietrich, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's Licensing page. If you have concerns about this material, message the admin.

Revision 2, last changed by WikiArchive .