Delphi Programming Tips

Grids and performance

I make extensive use of grids while developing applications. Currently I'm mainly making use of the DevExpress Quantumgrid. The grid is quite comprehensive, however I'm not very impressed with its performance when GridMode is set to False. We make use of Firebird as database server in combination with this grid. I found out that the Quantumgrid was quite slow when loading a lot of records (more than 10.000) with GridMode set to False.

I made a test application that loaded all these records and displayed them in a standard Delphi DBGrid that was connected via a DataSource to an IBOQuery component. Opening the query only took less than one second. When I did the same thing with a QuantumGrid not in GridMode it took much longer to open the query: around 10-15 seconds. In GridMode it was slightly slower than with the standard DBGrid.

I made another test with the same query connected to 4 QuantumGrids not in GridMode on the same form and then opening the query took more than 1 minute to my amazement. When GridMode was enabled for all grids, the QuantumGrid was faster, but still it took around 10 seconds to open the query. This slow performance is really not acceptable for our customers, so it becomes obvious to turn on GridMode always for all our QuantumGrids. However, whenever GridMode is enabled, then sorting, filtering and summaries are no longer possible with the grid. You'll have to program this manually.

The amount of columns that are displayed in the QuantumGrid are also influencing performance, however not very much (a few seconds faster when using less columns).

When GridMode is disabled, all records are loaded in the grid, in order to be able to sort and filter. That's why it's slow. I found out that before opening the query, setting the DataSource of the grid to nil and after opening the query assign the DataSource of the grid also affects speed drastically.

Because performance is key to our customers, I will be investigating in other grids that perform much better, while still offering good filtering and sorting possibilities.

The following grids are maybe worthwile, I have to figure out later on:

- BergSoft NextGrid
- TMSSoftware TDBAdvGrid
- XDBGrid
- InfoPower Studio
- DevArt
- Virtual Treeview
- SMDBGrid

Standard DBGrid links:

- Sorting a DBGrid
- Using DB aware controls in Delphi

Logging, import and export components

- Scalabium

Other components

- LMD Innovative

dbExpress

I'm so used to the Borland Database Engine, TQuery and the TIBOQuery component connected to a TIBODatabase component that's connecting to a Firebird database over the years, that I had to get used to the dbExpress way of doing things in the latest editions of Delphi. This video explains in detail how to use the dbExpress components. In dbExpress you need a connection component, a SQLDataSet component, a DataSetProvider, a ClientDataset and a DataSource just to make your data visible on your form. This is quite different from how it was done with the TIBOQuery.

Here you can find the DevArt Firebird dbExpress driver and here the Upscene Firebird dbExpress driver because this is not available in all Delphi editions.

I understand now that the dbExpres way of getting and updating data from a database is much more efficient.

DataSnap

DataSnap is an interesting technology allowing you to create a client and server module allowing part of your application to be executed on the server and part on the client. This technology is great for making thin client applications and separate presentation from business logic and storage. I'm trying to do my first DataSnap application, however I got some errors because the client can't reach the server (got socket error 10061). I thought that I had to start the Embarcadero scktsrvr.exe program first. This program is in the bin-folder under the Embarcadero Delphi installation folder.

Next I encountered a different socket problem (error 10048) stating that the address is already in use. I noticed that my DataSnap server application used portnumber 211, and that was not in use by any program as I concluded when I did the following:

Click on Start, go to Run and type:
cmd
then type:
netstat -a
or type:
netstat -n
or just run the amazing TCPView program.

However, not having started scktsrv.exe was not the cause of the problem and this scktsrvr.exe program should not be started. I found out that some time ago I had stopped the BlackFishSQL service under the Windows services. After I started this service again, my DataSnap application was running fine. I noticed that the server program made use of a connection to the BlackFishSQL databaseserver. So actually, it was just the example application that was looking for BlackFishSQL and this was causing the socket error because the database was not running. In order to work with DataSnap it's not essential to have BlackFishSQL running.

Nice to see the activity in the TCPView program. In case you encounter a similar problem: look at your virusscanner or firewall. Maybe they are blocking your TCP/IP traffic.

The following DataSnap article by Bob Swart is worth reading. It explains making a TDataSetProvider subclass (TB42DataSetProvider) that measures the amount of data that's transferred from server to client.

Delphi code examples

On the following sites you can find Delphi sourcecode examples:

http://docwiki.embarcadero.com/CodeExamples/XE4/en/Code_Examples_Index
http://docwiki.embarcadero.com/CodeExamples/XE4/en/Code_Examples_by_Functionalityhttp://capecodgunny.blogspot.nl/2013/07/complete-list-of-delphi-code-examples.html?goback=.gde_101829_member_259612557

Introduction to object orientation

I found an very good course about Object Oriented programming in Delphi here. Especially I like the chapters about patterns and the great documentation and examples of the Factory, Facade, Template Method, Strategy, Player-Role and Decorator patterns. What I also like about the course is that it makes extensive use of UML (the unified modeling language).

The Delphi 7 object hierarchy poster can be downloaded here as a pdf document. The FreePascal / Lazarus object hierarchy poster can be downloaded here.

Design patterns in Delphi

At http://delphipatterns.blog.com/ you can find information on how to develop design patterns in Delphi.

Lists and collections

The following webpage explains how to create lists and collections.

http://www.atug.com/andypatterns/collections.htm

Dependency injection and design patterns

Dependency injection is a technology (a design pattern) that's very useful in order to make a clean and loosely coupled software architecture, that's easier to test. In case you're already familiar with object orientation, then I think you can become a better programmer when you learn how to use dependency injection properly.

Martin Fowler explains about what is dependency injection (inversion of control) on this site.

Nick Hodges also has written a lot of excellent articles regarding dependency injection based upon Delphi and using the Delphi Spring Framework. Here are links to the specific pages: 1, 2, 3, 4, 5, 6, 7, 8, 9. Nick made a video (in .mp4 format) about dependency injection which you can download here after registering on the site of Embarcadero.

I was able to check out the Delphi Spring Framework with Subversion. It's also possible to just download the framework without Subversion. I experimented with it, following an example of Nick and also some examples that are available in the framework. I first tried it with Delphi 2010, however I got exceptions when I ran the executables. Under Delphi XE everything seems to be working as expected fortunately.

The framework itself consists of many units in different folders that I collected all and had it put into a single folder. This folder I added to my library path in Delphi. At first I tried to build the in the framework included .dpk package files, which resulted in .dcp and .bpl files, however I was not able to compile the examples with these only. That's why I have put all units (*.pas and *.inc) in one folder and added this folder to the library path (also upon advice from Nick).

Also have a look at this article about software flexibility.

The books below are essential reads in case you want to learn more about dependency injection, design patterns and UML.

Delphi code libraries

Visit Project Jedi for an extensive library which you can use in Delphi.

NativeXML: A native Delphi XML parser and writer

OmniXML: XML parser written in Delphi

Here's an example to use OmniXML to save settings of an application in an XML file. OmniXML can be used to (de)serialize objects.

Object Pascal style guide

This article and this one document a standard style for formatting Delphi code.

Tools

CNPack IDE Wizards (CnWizards) is a free plug-in toolset for Delphi/C++ Builder/CodeGear RAD Studio to improve development efficiency.
GExperts is a free set of very useful tools which can be integrated into the Delphi IDE. A guide explaining its use can be found here.
IDE fixpack is a collection of unofficial bug fixes and performance optimizations for Delphi / RAD Studio environments.
Modelmaker is another tool that is very useful e.g. for easily copying properties between sourcefiles.

Sending e-mail using Gmail and Indy components

Sooner or later I will have to investigate sending e-mail from a Delphi application using Gmail and the Indy IdSmtp component. Gmail makes use of SSL (secure sockets layer) and I think it is possible by using the IdSSLIOHandlerSocket Indy component in combination with the IdSmtp component. Here are some resources I've found that might be useful.

https://forums.embarcadero.com/thread.jspa?threadID=59924
http://forums2.atozed.com/viewtopic.php?f=7&t=26430

http://indy.fulgan.com/

By the way, Afterlogic also provides ActiveX mail components for Delphi.

 

 

Delphi Programming Tips • Richard Zwinkels