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.  

Wednesday 7 December 2016

4 space indent vs 2 space indent

Some developers like 4 spaces for the indent and some like 2 spaces. Originally I preferred 2 spaces, but ended up working for a company that insisted on 4 spaces, which is understandable to keep code consistent. And after using a 4 space indent for 5 years I actually prefer it for the following reasons:
  1. I find it makes the code more readable.
  2. Highlights when there is a lot of nested code, that might or should be refactored.
  3. It is consistent with C#, I know you can also change the number of spaces for tabs in C#, but 2 spaces in C# looks wrong to me.
I think this also raises the question on whether to use tabs or spaces, personally I don't mind and the fact that in Delphi you can set the number of spaces for tabs seems to get around the argument that people have that tabs take 1 key press. In reality I think that if a developer is actually pressing the space bar twice to indent or even 4 times, they are making life hard for themselves and should think about pressing 'CTRL' + 'D' to automatically format the code. I cannot see any argument for not using the auto format as long as all the developers on the team have the same configuration, else it does become a bit of a nightmare with source control.

Monday 31 October 2016

Solution to Delphi IDE Freezing Problem

Over the last few years I've been using Delphi XE, and on quite a few occasions the IDE can just freeze for what seems to be no reason. It does not appear to be an issue with small projects, but mainly larger projects and might relate to code insight and how I have it configured. When this problem occurred I use to 'End Task' in task manager, which meant potentially losing some work, but the best solution for when this happens to to find the directory that contains all the 'dcu' files and delete them.

Tuesday 25 October 2016

ADO Stored Procedure Blank Record Issue Fixed

I recently had an issue where I had an ADO stored procedure (TADOStoredProc) that returned a single record from a SQL Server database and the first time it was open it worked fine, however the second time it appeared to return a blank record. After some investigation it appeared the record count was 1, but the recno value was -1.

It appears that when you 'open' the stored procedure it is not guaranteed to position the record pointer on the first record. The solution is to simply call 'first' just after calling 'open'.

Wednesday 28 September 2016

TCategoryPanel refresh issue solved

I have a form with a TCategoryPanelGroup on it with several TCategoryPanels, on one of the category panels is a combox and when the user changes a selected value in the combobox it changes a label caption on the same category panel.

One issue I have had is that when I change the caption of the label it does not refresh correctly and it looks like the caption overwrites the previous caption. I tried various refresh, repaint and invalidates on the label, category panel and category panel group, but nothing worked. The only way I've found to solve the issue is to set the 'DoubleBuffered' property of the form to true.

Friday 2 September 2016

Delphi Vs Visual Studio

This is a comparison between developing software in Delphi XE+ vs Visual Studio 2015 (C#). I’ve decided not to go to in-depth with regards to syntax or run time dependencies of executables. I have experience in both although I have mainly developed web service and WCF services in C#, and mainly developed desktop applications in Delph, so that might affect some of my opinions.

Delphi Pros

  •          Quick and easy to develop desktop applications.
  •          I prefer the form designer, because I find it easier to use.
  •          Quick to compile projects.
  •          I like the code structure of interface and implementation in the same file.
  •          You can develop mobile apps.


Delphi Cons

  •          Code insight is slow and could be significantly improved.
  •          Some areas of the IDE look dated and it needs investment to keep it up to date with its competitors.
  •          Find declaration does not always work, finding the function or procedure is more time consuming than Visual Studio.
  •          Hard to employ developers as there are not many about.
  •          Code insight is slow to update, for example add a new property to a class and sometimes you need to compile to make that property available for code insight.
  •         Unit testing using DUnit feels old and there has been little development of it over the years.

  

Visual Studio Pros


  •          IDE has a more modern interface, like the option for a dark color theme.
  •          Code IntelliSense is great, and I like the ‘potential fixes’ option which is very useful for adding directive or assembly reference.
  •         Unit testing is easy and integrated into the IDE, making it easy to run tests while you are developing.
  •          Debugging services is easier than when I have developed services in Delphi, this might have changed recently in later versions of Delphi.
  •         Peek definition is a nice feature.

Visual Studio Cons


  •         Slow to start-up.
  •          Sometimes freezes and it is best just to wait.

Tuesday 21 June 2016

Delphi error XML document must have a top level element. line 0

I have a Delphi application written in XE that consumes a WCF service written in C#, I have been receiving the following error message with one of the methods

XML document must have a top level element. line 0

I managed to fix the issue by making the method in the WCF Service return a value (boolean) if successful. It is possible Delphi does not like WCF Service methods that are one way ([OperationContract(IsOneWay = true)]).