Sunday 30 November 2008

Delphi for i386, PowerPC, s390, Arm, Mips, x86-64, Itanium...

The people at CodeGear have done something cool: They now officially support the mono project, which supports a wide range of CPU architectures.

I was one of those that evaluated the Kylix product, and actually used it for production code (non-GUI, server side), which still runs. Kylix's main problem was, that it only supported i386, and the basic concept in Kylix did not indicate that this would change any time soon. It was really cool to use Kylix for non-GUI apps on Linux, because the apps were fast, the tool was productive, and everything worked with Unicode (utf-8). However, it was clear from the start that the concept was flawed, and I only used Kylix because there was no realistic alternative for that very special project.

Now, CodeGear delivers cross platform technology, supporting both Microsoft and Open Source platforms. This means that the king of GUI development now supports many kinds of server-side and embedded development, and that CodeGear has a cool platform for things to come. We can even make our source code run on a Mac or Nintendo Wii now.

This should not be considered to be a minor product. In order to exploit a business opportunity, you need to be in a position from where you can do it, and Delphi Prism seems to provide a good position for Embarcadero.

Friday 28 November 2008

The smallest Hello, World in Delphi

This is the source code:
{$APPTYPE CONSOLE}
program p;
begin
Writeln ('Hello, World');
end.

Program info (Delphi 2009):

* Code size 14284 bytes
* Data size 12988 bytes
* Initial stack size 16384 bytes
* File size 21504 bytes

Benchmark:

* Using a standard .cmd batch file, this application can be started 10000 times in 77 seconds on a standard Core 2 laptop using Windows XP. That means 7,7 milliseconds per run.

A minimal GUI app:

program p;
uses
Windows;
begin
MessageBox (0,'Message','Hello, World',MB_OK);
end.

Program info (Delphi 2009):

* Code size 11744 bytes
* Data size 12984 bytes
* Initial stack size 16384 bytes
* File size 18432 bytes

Both run on:

* Windows 95 and later
* Windows NT 3 and later
* Linux using Wine

In order to understand the relation to other languages, you can have a look at this article about Java (translations tools here).

Thursday 13 November 2008

In-band vs. out-of-band signaling in programming

In telecommunications, you need to transmit data, but also signals that indicate information about connections - signals like "create a connection", "close a connection" etc. This information can be transferred in multiple ways: inside the data channel, or outside. This is usually called "in-band signaling" or "out-of-band signaling". DTMF is a good example of in-band signaling. You press a number on your phone, the phone generates a sound, and the sound can be heard in the other end. This is different from HTTP, where the protocol wraps the content, so that the content cannot change the HTTP information.

In programming, we have something similar. Out-of-band signaling looks like this:
procedure StringToInt (s:string;var i:integer; 
var error:boolean);

Here, the error code is delivered separately from the return value. An in-band signaling type example is:
function StringToInt (s:string):integer;
// Returns 0 if s is not a valid integer

Here, a default value is returned, if the string is not readable. In other words, the return value can be an error code or a value, and the error code could strictly be interpreted as a value.

The basic properties of in-band signalling are:

* A sends at least 2 kinds of communication to B through system C
* System C cannot distinguish the different kinds of communication

A good example is the utf-8 character encoding system. Most ISO-8859-1 applications can handle utf-8, even though they were not designed for it. Kylix was not designed for utf-8, but you could write utf-8 source code, and create utf-8 applications using Kylix, fully unicode enabled. Also, many text-file command-line tools that were designed for ISO-8859-1, work perfectly with utf-8, unmodified.

XML is another good example. XML files can be transported, filtered, stored, reformatted and handled in many ways, without specifying what kinds of information the XML file actually contains. You can transmit different kinds of XML files through a generic XML communications channel, and only the sender and the receiver understand the difference.

One of the oldest and most well known examples is probably ASCII. The character A is a letter, with the code 65. Ringing the bell has code 7, and returning the carriage has code 13. All you need is to transmit a 7-bit code, and you can make the remote device make sounds, feed paper, print multiple characters on top of each other etc.

Does in-band signaling make sense? Yes. Many of the most successful data formats use in-band signaling. Does it always make sense? No. I can mention lots of reasons why, but the list is too long to mention here. One is very important, though: In-band signaling is often mentioned as a security problem - think of SQL injection.

Try to imagine programming, where a string could not contain multiple lines. How would programming have evolved? We wouldn't have TStrings.Text, we wouldn't have the ability to save multiline texts in a string field. Maybe we had solved this differently. Or not.

Tuesday 11 November 2008

Corrections to "Working with Delphi 2009"

My article about "Working with Delphi 2009" contained 2 serious flaws that need a correcting article.

First, I mentioned that #0 would not be stored in a unicodestring/string. That's not correct. I did have a problem related to the #0, but I identified the wrong cause. I haven't identified the correct cause, yet. Thanks to Andreas Hausladen for reporting this.

Second, I mentioned that insert(), delete() did not exist in ansistring versions. This is actually what delphi reports inside the IDE, but it is not correct. If you try to use them with ansistring, they will compile and work. Thanks to "PhiS" for reporting this one.

A search in system.pas reveals, that insert() works with shortstring, ansistring, widestring, unicodestring, but not RawByteString. However, I have tried all kinds of combinations with utf8string, ansistring and other kinds of strings, and it seems to work backwards-compatible in all cases. A utf8string does not get converted to local character set when used as an ansistring var-parameter to insert(). It's not logical, but it works.

Sunday 9 November 2008

Anders Hejlsberg and Delphi's future

Anders Hejlsberg made a nice presentation during his latest visit to Denmark, see it here. He said a lot of things, but one of his points actually explains the power in Delphi: When you look at the amount of learning that a new programmer has to do, the tools and libraries are now much bigger than the language. Delphi has good tools and libraries, and that's important.

Anders Hejlsberg also mentioned, that most languages will be static and dynamic in the future. I totally disagree. The main reason why Python and PHP are so popular, is that the learning curve is not steep. If python would become a .net language, it's tools and library would explode in size, and if static typing would be applied, language complexity would increase, making it unsuitable for a part of its audience. It seems that Anders Hejlsberg has forgotten usability - it also applies to programming languages. There is a need for entry-level languages.

Anders also mentions that we're working towards an ever increasing level of abstractions, and that we need to continuously invent new programming languages to test new methods. That's fine with me, as long as I don't need to invest in source code based on these obviously temporary languages. Adding more and more features to C# makes it bloated. In other words, Microsoft is facing the choice between bloat or many languages, and seems to pick both, just to be safe.

Anders's presentation is tainted by his employment at Microsoft. Therefore, we need to remember the background for his presentation. The world of general-purpose programming languages today largely consists of these groups (based on the TIOBE index):

* Open Source compilers: C, C++, Java
* Microsoft .net: C#, VB
* Delphi
* Low performance scripting languages

In order to really understand the difference between these groups, you need to look at the forces behind.

Open Source compilers will preserve backwards compatibility. They are cross-platform which makes some things more complicated (Write once test anywhere). You can do anything you want with C and C++, but development costs are huge. Java is very strong and probably the most widely used today. However, Java also has problems.

Microsoft compilers always face the threat, that Microsoft can earn more money by not being loyal to their programmers. They have done that multiple time in the past, and every time it meant big expenses for developers.

Delphi is owned by Embarcadero, and Delphi is one of their main products. They need to make Delphi good and be loyal to developers. And yes, we can still compile 25 year old Turbo Pascal code.

Saturday 8 November 2008

Working with Delphi 2009

My main work is with Delphi 2006, but more and more of our source code now compiles with Delphi 2009, and I also created some tools with Delphi 2009.

Converting existing source code is extremely simple, as long as the source code is written nicely, and is about databases, user interfaces etc. However, direct Windows API calls need to be checked - especially where you have an "array of char" and pass the sizeof(array) as parameter and similar constructs... the char is now widechar and sizeof(array) is no longer the character count. Often, you will find this kind of code in 3rd party components or small code snippets that you get from other people. Sometimes you can fix things by replacing char with ansichar, sometimes you want to use the Unicode API and therefore need to replace sizeof(array) with length(array).

CodeGear has done a lot of make simple I/O simple. Many things just work, but some things don't. TStream.Write (str[1],length(str)) will fail, because the second parameter is the byte count. Rewrite to TStream.Write (str[1], sizeof(char)*length(str)) or make str an ansistring. In other words, you will need to fix Windows API calls and advanced I/O.

If you have previously created an application, that handled unicode, you may have stored utf-8 encoded stuff in TStrings objects, and used various character sets in various parts of your program. You can still do that, but some functions now only work with string and not ansistring, and the easiest solution is often to make everything use unicode, and convert to/from unicode at I/O and APIs. When fixing all this, it feels really good - it's like cleaning up your desk and the source code gets simpler.

You may think: I can just replace all "string" with "ansistring". No, you cannot. Many functions like copy(), insert() etc. will no longer work with ansistring. Delphi will convert your ansistring to string first, assumping that your ansistring contains text in the local character set, and that assumption is not always correct.

Also, there is one special character that has stopped working in string types: #0

If you assign s:='Hello'#0'World', then s will contain 'Hello'. The reason is, that string is now strictly for text purposes, and #0 is not text - it's a binary code. This was probably the most tricky problem that I have encountered, because I had to convert some code that did this. Fortunately, it only took about 5 minutes to fix. If you're searching for a replacement code, consider #12 (Form feed). I don't think anybody uses that code today, and it gets converted nicely between character sets. However note, that TCharacter.IsWhitespace() will treat it as whitespace, and that #12 is not the end of a PChar string, in case you're doing complicated byte gymnastics.

It's not plug & play to use old source code in Delphi 2009, but conversion is fairly easy, and normally you will not need to be familiar with source code in order to convert it easily. This is good, because it means that you can easily take another person's source code, and convert it.

When writing new apps in Delphi 2009, it feels really, really good. The quick startup feels good, texts and raw binary data is automatically separated into different datatypes, and mixing these up unintentionally gives nice warnings. It feels as if Delphi is helping you more now, than before. If you need advanced ways to save data, the new Generics features can make the source code much more readable than in previous versions. Simply derive from TList in the Generics.Collections unit:

type
TPairTitleId=
class
ComboBoxTitle:string;
DatabaseId:integer;
end;
TPairTitleIdList=Generics.Collections.TList<TPairTitleId>;


Now you can refer to things like:

function dummy (list:TPairTitleIdList);
var
i:integer;
begin
i:=list.Items[3].DatabaseId;
end;


It is a significant productivity enhancement if used wisely. There is no need to use the familiar "TStrings.Objects[i] as TMyClass" any more.

Delphi 2009 is a significant step forward. It does everything your old Delphi does, but significantly better and easier.

Friday 7 November 2008

C# - C Doublecross

I wonder how many English-language people actually know what C# is in other languages. In Danish, you could either adopt the Microsoft-English "C Sharp" version, or use the normal localized word for # and get "C havelåge", which basically means "C garden gate".

I have no clue how you can make the symbol "#" become "Sharp" - to me, it looks more like a pillow. Based on various languages, it could also be:

* C garden fence (from German)
* C pig's fence
* C Carpet
* C Gnarl

But why not just call the symbol what it is? C doublecross.

Wednesday 5 November 2008

New PO file editor: Gorm

In case you are using PO files for internationalizing your applications, there is now a new Open Source editor around: Gorm. Features include:

* Labelling/tagging of translations, so that you can make a translator translate a subset instead of everything
* Automatic error discovery (like when format-string translations are not correct or when the translation has different spacing than the original)
* Spaces are shown using dots
* Display of secondary translation when writing texts for other translations. This is very useful if one person knows 3 languages, and wants to cross-check, or if the translation of one application should be a guide for the translation of another application.
* Integrates with Google Translate
* Text filtering of items
* Separate display of source code position and programmer comments
* No installation required at translator - the exe file runs directly when double-clicking it.
* Focus on usability for non-programmers.
* Tag-based statistics

The application is still under development, but ready for production use. Because it is still under development, you need to go to the GNU gettext for Delphi forum to get information about it.

Gorm was named after Gorm the Old, King of Denmark 900-940 A.D., father of Harold Bluetooth, whose name got famous when it was used for the Bluetooth technology in mobile telephones.

Gorm was made using Delphi 2009, which made Unicode easy.

Tuesday 4 November 2008

Layers in programming

I just got inspired by David Intersimone's latest blog posts about the history of Delphi:

Modern programming is like Onions. It stinks? Yes. No. They make you cry? Yes. NO. Layers. Onions have layers. Modern programming has layers. Onions have layers. You get it?

(Which reminds me that I need to buy the latest Shrek movie)

When adding layers, always remember that layers add latency.

Monday 3 November 2008

Delphi bigger than C#? The TComPort history

Just a few years back Delphi's future was uncertain, Borland focused on other products and Delphi was on its way down. Now, the TIOBE index for November indicates that Delphi is number 8, just slightly below C#. Is that really correct?

The TIOBE index is basically a web search index, and some may argue that it basically reflects a very strong Delphi community. However, there are many other signs of a new strength in Delphi.

One of them is the comport project, a 3rd party component for RS232 for Delphi. Originally developed by Dejan Crnila, he eventually moved on in his life, abandoning his original project, and stopped paying for the hosting of his project homepage. Like many other 3rd party components in Delphi, the source code was available, and I asked Dejan if I could move it to SourceForge and save it for those that were still using it.

I moved it, and everything was very quiet for a very long time. Then, the company TurboPower was bought by another company who wanted the developers, abandoning their products. They made really good 3rd party components, and this seemed like a real problem for many, but the good and clever guys at TurboPower managed to Open Source the components. TurboPower Async Pro was one of them, and it did almost the same as the Comport component. I started to recommend the use of Async Pro, in order to avoid spending more time on this - but I kept the sourceforge project page up in order to help out existing projects.

Then, something happened. CodeGear was split off, and put up for sale. Focus on Delphi reemerged. I started to receive e-mails about the comport component. Embarcardero bought CodeGear, and Embarcardero is a company that keeps focusing on Delphi as a product. The number of e-mails about the comport component is continuing to go up. Why would anybody use an old, abandoned component, where the maintainer recommends another product? The reasons seem to be: It's simple, it works, it's free. It solves real-life problems. And even more important: The programmers are starting up new projects based on Delphi.

We now have a new maintainer on the comport component, and a 4.0 beta release.