The Power of Proper Planning and Practices

From Lazarus wiki
Jump to navigationJump to search

Planejar diretamente para cross-plataforma

Existem muitas vantagens em fazer o seu desenvolvimento de maneira cross-plataforma. Provavelmente a mais importante é que pode dar um resultado melhor e mais confiável. Isto acontece porque o desenvolvimento cross-plataforma requer que você gaste mais tempo planejando o seu software antes de começar a escrevê-lo. Também o força a desenvolver bons hábitos de progrmação para testar mais o seu software e desenvolver uma abordagem mais disciplinada em relação ao que você está fazendo. Estas coisas (planejar, testar, disciplina) tendem a contagiar outros aspectos do seu desenvolvimento, resultando em um ainda melhor design e confiabilidade.

Outra vantagem do desenvolvimento cross-plataforma é que ele o expõe a outras plataformas. Por exemplo, muitos desennvolvedores para Windows e provavelmente todos os desenvolvedore para Linux poderiam se beneficiar de algum tempo gasto simplesmente usando o Mac como modo de desenvolver uma apreciação para software em facilidade de uso e estética. E muitos desenvolvedores Windows poderiam se beneficiar de como o Linux tende a usar arquivos-texto e scripts para muitas coisas sem perda de performance nas aplicações.

Uma terceira vantagem do desenvolvimento cross-plataforma é que ela é por definição inclusiva, o que o força a considerar seus usuários mais que a maioria dos programadores de plataforma única fazem.

A melhor maneira de fazer uma aplicação cross-plataforma é desenhá-la para ser assim. Se você planejar para adicionar suporte cross-plataforma mais tarde, você pode precisar reescrever partes do programa ou, pior, encontrar-se em um beco-sem-saída "Windows-only" que torne o suporte cross-plataforma difícil ou impossível.

Se você já desenvolveu uma aplicação para Windows com Delphi, é possível em algumas situações convertê-la para cross-plataforma sem recomeçar. Se você quiser fazer uma conversão de mão-única do seu código e formulários Delphi para Lazarus, você pode usar alguns dos comandos de conversão do menu Ferramentas do Lazarus. Se você também quer converter para Lazrus, mas reter a compatibilidade com Delphi, [discussion needed].

Código separado para unidades UI e não-UI

Provavelmente uma das mais importantes práticas de programação que você pode empregar com qualquer aplicação, seja cross-plataforma ou não, é dividir seu código entre unidades de interface de usuário (UI) e não-interface-de-usuário. Em geral, isto quer dizer que as suas unidades não-usuário não devem implementar algo da interface de usuário e as unidades de interface de usuário não devem conter nada da parte computacional ou de banco de dados do programa. Na prática , uma boa forma de forçar esta separação é requerer que as unidades que você desenvolve somente use unidades do seu próprio lado desta divisão. Por exemplo, suas unidades não-usuário não devem usar unidades da LCL ou unidades como Forms, Dialogs, StdCtrls, Button, Graphics, Controls, LMessages, etc, ou qualquer das suas unidades que usem essas unidades. E suas unidades-usuário não devem usar unidades como Math, Dbf, MySQLDB4, etc. Siga o exemplo do Free Pascal e do Lazarus, em que unidades de propósito geral como SysUtils, Classes e Variants não usam unidades LCL e unidades LCL como Forms e Controls não provêem rotinas de propósito geral.

Existem muitas vantagens de dividir o seu código assim. Por exemplo, isso significa que você será capaz de usar as suas unidades não-usuário em qualquer tipo de programa, biblioteca, console, até uma aplcação Web, sem fazer qualquer modificação no código. E isto também significa que você pode desenvolver uma interface de usuário completamente diferente se necessário ou mudar para uma biblioteca ou controle sem modificar o código não-usuário remanescente. 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:

 mybatch.bat

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

With Unix:

 ./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:

With Windows:

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

With Unix:

 /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:

With Windows (all on one line):

 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

With OS X (all on one line):

 /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

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:

  • Develop with all run-time checks turned on. You can turn off some or all checks when you create an executable for distribution, although the code-size and performance improvements of turning checks off are pretty negligible. Plus, leaving checks turned on can help you locate bugs that turn up later.
  • Use assertions. Like run-time checks, assertions can be turned off later, although leaving them on can help you diagnose bugs that your users encounter.
  • Compile with line number tracing turned on. You can turn this off when you release your program to shrink the size of the executable.
  • If your code handles exceptions, you can still determine the line number and source file name of where the exception occurred using line number tracing and the FPC BackTraceStrFunc function, as in this example code:
   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.

  • Initialize variables. Although both Delphi and FPC initialize global variables and object fields, variables local to routines are not initialized. It's a good idea to initialize all variables just to be clear about what their initial values are.
  • Turn on compiler warnings and pay attention to them.
  • Use "with" sparingly. Although the Pascal with statement can save you a lot of typing, it can also hide incorrect field references if you use nested with statements or if a field with the same name as a field in your with's target is added someday to an ancestor class.
  • Run your code through multiple compilers. There will always be differences in how different compilers process your code. Sometimes these differences are dictated by the underlying operating system or hardware. Try to compile your program (or at least the non-UI units) with two or three compilers. For example, if your code compiles and runs correctly with Delphi and on at least two of FPC's platforms, you'll be that much closer not only to a stable cross-platform app but also to having a program that you know will work.