Thursday, 25 May 2017

Frame Inheritance - TabOrder: Property does not exist - Issue Fixed

I've been working on an application recently and it has a few frames (TFrame), I noticed that there were common properties and methods to all the frames, so I decided that they should derive from a base class. I created the base frame class and then in code derived the other frames from the base frame. It all seemed to work fine a build and ran OK, however after closing the project and then coming back to it a few days later, when I tried to open a frame I received an error stating the TabOrder property does not exist, I ignored it and received more property does not exist errors (I did not save any changes). The solution to this problem was simple, in the .dfm file at the top was:

object TestFrame: TTestFrame 

This needed to be changed to:

inherited TestFrame: TTestFrame

The ideal way to do this is at design time when designing the structure of the application, if there is an abstract or concrete frame class then this should be added to the repository so when a developer needs to create a new frame, they can simply inherit the frame from the one in the repository.

This is a very similar problem to inheriting datamodules, I've also had to do something similar. 

Wednesday, 19 April 2017

Only use ShowMessage() function for debugging

I always use the ShowMessage function for debugging while doing development and always exclude it from release code for the following reasons:


  1. MessageDlg or MessageBox functions are much better as a popup dialog than ShowMessage, they have more options and the presentation is better giving the user a visual icon categorising the meaning of the popup.
  2. It is easy to search through all the code and check there is no 'ShowMessage' operational before checking in the code. I had a customer call me once saying they have a popup (ShowMessage) which just says 'Hello', this was because the developer forgot to remove or comment out the ShowMessage before checking in.
  3. Because there is no icon with a ShowMessage, some testers and end users assume the popup is an error dialog. I have had the same but to a lesser extent with MessageDlg, the icon helps to show when it is information, warning or confirmation.
Some developers seem to use ShowMessage to quickly display information to the user, they are using ShowMessage because they think it is quicker to use, but in GExperts there is a Message Dialog tool that creates the code based on the options the developer sets.

There is the argument not to use these popup at all, and in some applications they cause issues. I think that popups can be annoying to the user if used too much, but I do not have a problem with them if they are used sparingly and they do not cause problems with the operation of the application.

I imagine some developers might say you should never use ShowMessage to debug and use breakpoints while debugging, which in most cases is the true, but there are occasions when some testing by the developer might be done in a non-development environment, in which case you cannot use the debugger. 

Wednesday, 15 March 2017

Why are semi-colons sometimes not required?

Over the 20 years I've been developing commercial software one question I still have with the Delphi language is why was the language designed so semi-colons are not required at the end of methods? For example:

function DoSomething: boolean;
begin
  if FDoSomethingElse then
  begin
    DoSomethingElse;
  end
end; 

I believe the reason why the compiler does not complain about this, is because the semi-colon in Delphi is a statement separator and not a terminator. If I modify this function for example:

function DoSomething: boolean;
begin
  if FDoSomethingElse then
  begin
    DoSomethingElse;
  end;
  DoOtherStuff
end;

I obviously need to now add in the semi-colon, but I do not need to add in the semi-colon after 'DoOtherStuff'. I currently cannot see any benefit of leaving the semi-colon out. I would not normally code this way and always add in the semi-colon for 2 reasons:

  1. Adding the semi-colon makes the code more consistent.
  2. It means later on when the code is modified the semi-colon does not have to be added.
I have come across Delphi developers who will not put in the semi-colon if it is not required, but cannot see any real benefit from leaving it out. Maybe I have answered my own question, and that is the semi-colon is a separator and when the language was developed they did not see any pros or cons of just allowing the semi-colon not to be there.


Thursday, 23 February 2017

Strict Private Problem with Code Completion

Some time ago I noticed something annoying in Delphi XE with 'Strict Private' and code completion.

Here is an example:

TMyClass = class(TObject)
strict private

public
    property Test: string read FTest write FTest;
end;

When I do CTRL + Shift + C to add the private member to the class it does the following:

TMyClass = class(TObject)
strict private

private
    FTest: string;

published

public
    property Test: string read FTest write FTest;
end;

It adds FTest to the private section of the class and also adds the published section, which is not what I want, but if I remove 'strict' it does not add the 'published' section. Because of this I develop my classes  as 'private' and then once I have added all the require properties then I add 'strict' if required. I am not sure if this behaviour is some setting somewhere that I am not aware of, or whether this is something that might have changed in more recent versions of Delphi. Is there a valid reason to have a 'published' section when there is a 'strict private' section?

Friday, 27 January 2017

Should constants be uppercase?

In a recent blog someone pointed out to me that boolean values true and false should be uppercase because they are constants. This made me think, usually I put constants in uppercase, however when I code true and false they are always lowercase, so it raises a question about my code style, should all constants be uppercase? If so then true, false and nil should also always be uppercase, but for me this does not look correct. Should constants not be uppercase? One reason why constants are uppercase is so they stand out from variables, but is this the only reason?

When I develop in C#, I follow the recommendation for constants not to be uppercase, so I am starting to feel that maybe this should be the same in Delphi and constants should be camel case for local constants and pascal case for public ones.

Thursday, 22 December 2016

Reasons why I dislike dangling begins

Recently I've been writing a coding standards document and some Delphi developers seem to like the dangling begin format (Egyptian style) of begin/ends, here is an example of what this is:

function DoSomething: boolean;
begin
    Result := False;
    if FDone then begin
        Result := True;
    end;
end;

The 'begin' is at the end of the line rather than on a line of its own. I believe the original reason for this was to reduce the number of lines of code, this helped save paper when printing out code at schools and universities.

This format I personally cannot stand and cannot see a modern valid argument for doing this. I have not printed out code for years and think the argument that it saves some paper to be a very weak one compared to the improved readability of the 'begin' being in-line with the end.  

This is how I would write the function:

function DoSomething: boolean;
begin
    Result := False;
    if FDone then 
    begin
        Result := True;
    end;
end;

As you can see the 'begin' and 'end' are in-line and it is more readable. But why is it more readable? I have been trying to understand why I think it is more readable and here are some reasons:

  • The begin/end is in-line so the eye can naturally move vertically down to see the end of the code block. 
  • It matches the function and procedure begin/end pattern, therefore is more consistent. The begin/end of a function or procedure is usually in-line, although I have seen code where this is not the case.
  • The 'begin' is visually linked to the 'end', consider the Gestalt principle of proximity and continuity (see diagrams below).

The diagram above shows squares to represent the 'begin' and 'ends', the first group uses the dangling begins and the second puts the 'begin' on a new line making the 'begin' and 'ends' in-line. It seems easier to link the second group because they are in-line.




I have seen recently that Apple's Swift language uses the 'Egyptian' style,  for example:

func tableView(tableView: UITableView) -> Int {
   return 10
}

Using this format in Delphi the function would look like this:

function DoSomething: boolean; begin
    Result := false;
    if FDone then begin
        Result := true;
    end;
end;

This would make the begin/ends more consistent, however I like this even less.

It is a matter of personal preference, and I prefer the in-line begin/ends and in-line curly brackets in C#, I cannot see how I will ever change my opinion on this.   

Saturday, 10 December 2016

When to use FreeAndNil

I've worked with numerous Delphi developers over the years and worked with a lot of other developers code. I've found that some developers seem happy just to free an object once it is no longer required and some always use FreeAndNil.

My rule on using .Free and FreeAndNil is always use FreeAndNil except when the object is in local scope. For example the only time I use .Free is:

procedure DoSomething;
var 
    productList: TStringList;
begin
    productList := TStringList.Create();
    try
        // Do something...

    finally
        productList.Free;
    end;
end;

I consider the above to be fine, however recently I was speaking to a developer who said they always use FreeAndNil because what would happen if some other developer added to the procedure and tried to use the object, but check that is was assigned first. In the example above if someone added some code that checked for the assignment and then a block of code that  used 'productList'. An error would not occur however the block of code would never be executed. The question here is what is better, the block of code never to execute or an error to occur and the bug is fixed. It is possible that the unit test would detect both early on, and apparently a code coverage tool would also detect that the block of code was never executed (can anyone suggest code coverage tools for Delphi?).

The other argument my colleague had for always using FreeAndNil was if another developer came along and changed the scope of productList and made it into a private or public variable. I consider this to be a weak argument because if a developer did this without reviewing the code then they should not be a Delphi developer.