Delphi Programming
Advertisement

Here are some useful notes about certain (good or bad) keywords/other used.

Keywords[]

Goto[]

This is a statement which allows jumping between different parts of a program.

  • Pros:
    • It allows you to jump from one part of a program to another.
    • Can be used to exit out of large nested loops. (this is also slightly faster, a reason where it is used a lot in codecs and compression code)
    • Useful for "bail out" stages of a function when a condition/error occurs so any memory/objects can be cleaned up just before the function returns
    • It can be used to create a State Machine.
  • Cons:
    • It can create what they call Spaghetti Code, which drive up maintenance costs.
    • It does not allow passing of arguments or returning to the caller like a function or procedure does.
    • Jumping into loops has unknown effects.
    • Many more...

Conclusion:

The disadvantages far outweigh the advantages of goto in normal business code, it is not recommended to be used in structured programming today, as it is an extremely bad practice, many other modern languages have removed goto statements from their syntax.

Variant[]

A Variant is a variable that can hold almost any type of data.

  • Pros:
    • It allows one to assign any type of data to one, including overwriting data that is not of the same type.
    • A type of variant can be distinguished/shown at runtime.
  • Cons:
    • There is a large performance penalty when using variants compared to other data types.
    • Code clarity can be reduced when using them.
    • There is a possibility of introducing runtime errors, because a typing mismatch can only be found runtime.

Conclusion:

Variants should be used with care, especially with programs that are designed to be of a high performance nature, they can be very useful for database programming however.

With[]

The With statement allows one to access the members or variables of a record or class, without typing the class name.

  • Pros:
    • It makes it easier to add information to a record, eg: rather than typing record1.var2
    • Multiple records can be added, eg: with record1, record2 do.
    • Prompts the compiler to optimize access to the fields (same thing can be accomplished with a local variable).
  • Cons:
    • Can make code harder to read, maintain etc, Nesting them isn't recommended either in this context.
    • It can be dangerous, especially with local and global variables, subroutine parameters etc.
    • Code completion doesn't work.
    • Many well-known Delphi developers describe the "with" statement using terms such as "Spawn of Satan" and "evil". Using the "with" statement could cause a reduction of respect among peers. If a line of code is too long, simply declare a short but descriptive local variable.

Conclusion: Generally, you should avoid this keyword at all costs, especially for large complex applications. This statement was used a lot in earlier delphi programming and should be avoided by newbies, the bad effect on code clarity can rise significantly with this statement.

Other[]

Global variables[]

These provide a useful way of allowing all or most routines in an application to access data of some form, they exist in most programming languages.

  • Pros:
    • They can provide a useful way to keep a "configuration" of the program running.
    • Can be used to create a state between 2 or more functions, without passing parameters.
  • Cons:
    • Code clarity can be reduced by using them.
    • Program security could be slightly reduced.
    • Can be bad in multithreaded applications.

Conclusion:

Most programmers these days try to avoid them, but there may be instances where one or two may be needed from time to time, they are not too bad, but not recommended for applications where security is an issue. However note that a lot of the solutions to avoid them, (singleton classes e.g.) share all the cons. To resolve the cons, one really needs to resolve the ownership-of-the-data problem, not merely avoid the language construct.

Integer types[]

Using Cardinal and Integer can provide a way that the size of both these values will be changed from compiler to compiler.

  • Pros:
    • They provide a unique way to increase the limit on more modern compilers, like 64bit ones.
    • According to Delphi's help file, they are better for the underlying operating system in terms of performance.
  • Cons:
    • As above, these values change, which is also not a good thing, as they can have serious affects on older applications, especially ones that write binary data out to a stream of some sort.

Conclusion:

For backwards compatibility, its always better to use the fixed types, such as Shortint, Smallint, LongInt, Int64, Byte, Word, LongWord. If you won't be changing compilers for a while/require "better" performance/have code that can adapt to size changes in integers, use Cardinal and Integer instead.

Boolean types[]

There are 4 boolean types in delphi, Boolean, ByteBool, WordBool and LongBool. The most common/prefered one is Boolean. Information on the data types is listed below:

Name Bytes Used
Boolean 1
ByteBool 1
WordBool 2
LongBool 4


For all Boolean types, you can't assign a integer value to it to make it either true or false. (you can if you cast it, though)

Another downside to the Boolean type compared to say, LongBool, is that it only occupies 1 byte of storage, this is bad architecture-wise if the CPU of the current OS is 32bit (4 bytes), the compiler will pad things out if its uneven. (same thing goes for records, which is also bad if reading directly into one from a stream of some sort)

Good coding practice[]

Code layout[]

It's a good idea to always indent your code, this helps make it more readable to yourself and other programmers, indentation is usually prefered by using the space character rather than tab (delphi can convert tab characters into spaces, the option is Tools->Editor->Use tab character, Uncheck this), a typical indent level is usually 4 or 2, sometimes 8, choose what you prefer.

Also, its preferable to use spaces between blocks of code. one space will usually do.

Un-indented, Un-spaced code:

function MyFunc(val1: String): String;
var
somevar: Integer;
begin
Result := ;
if (Length(val1) > 0) then
begin
for somevar := 1 to Length(val1) do
begin
Result := Result + val1[1];
end;
end;
end;

An example of indented, spaced code.

function MyFunc(val1: String): String;
var
    somevar: Integer;
begin
    Result := ;

    if (Length(val1) > 0) then
    begin
        for somevar := 0 to Length(val1) do
        begin

            Result := Result + val1[i];
        end;
    end;
end;

There are many automated code formatters out there that can do this for you, it would be a better idea to use one if you have a project that contains a lot of source code. Such code formatters can be found at the end of this article.

Comments[]

Sometimes you may write a piece of code that you may forget how it works in future, this is usually due to lack of comments. Comments provide a valuable way to document your code, that will be understood by you and other programmers. Here are some hints on writing good comments:

  • Indent comments (see above)
  • Use clear, simple, meaningful words, eg: "write data to file" as opposed to "release data to descriptor"
  • Write how it works in actual human understandable format, rather than code/pseudocode/similiar
  • Avoid too simplistic comments, such as "Add 1 to i", it is fairly obvious what it does.
  • If you find yourself writing a comment, consider whether using descriptive names for functions, methods, classes, parameters and variables may make this comment obsolete. If yes, forget the comment and concentrate on better names. The BDS refactoring functionality helps a lot here.
  • The same applies to the code structure. Computing time is cheap, developer time is expensive. So, rather than optimizing some code to save a few cpu cycles concentrate on making it readable and easily understandable to other developers (and yourself a year later). There are only very few exceptions to this rule where runtime performance really matters. So, if restructuring the code makes a comment obsolete, do not comment, restructure. (You do have unit tests in place to ensure that you don't break the code, don't you?)
  • Consider using some source code documenting system, A list of these can be found at the bottom of this article.

Delphi provides three ways to write comments, these are //, (* *) and { } keywords, here is an example:

function MyFunc: String;
begin
    // A Single line comment

    Result := ;

    {
        A Multi-line comment
        Which appears on 2 lines or more
    }

    (*
        Another
        Multi-line
        Comment
    *)

    Result := 'Hello World!';
end;

Code Case[]

While the Object Pascal language supports functions/keywords/whatever else in multiple case (unlike C/C++, which is case-sensitive), setlength() and SetLength() are exactly the same, its a good idea to choose one OR another, not both. It's also a good idea not to mix case, eg SeTlEnGtH() as this will make your code less readable (especially to someone coming from a language like C!)

Again, a source code formatter might help to reduce the work here, See the External Links section of this article for such tools.

Miscellaneous[]

Things that you, as a programmer, should avoid.

  • Magic Numbers - These should be put into consts, otherwise they can make code harder to read. If you find you are using them, try replacing them with enums.
  • Hungarian Notation - This can be just plain annoying to some programmers, as it can make code hard to read, companies like Microsoft have removed it from the .NET framework. Also, see the Wikipedia article on this topic because today's understanding of Hungarian Notation is not what it was meant to be. The original idea was actually quite reasonable.
  • Extremely long function names - Try to truncate these (eg: from OpenTheFilesForTCPDataTransfer to OpenFilesForSending if possible), but try not to make it ambiguous to read/understand! Also if writing classes, use the F prefix for fields and no prefix at all for methods.

External Links[]

Advertisement