Samstag, 30. August 2008

entwickler.com Magazine Konferenzen Akademie Entwickler-Forum Jobbörse Bücher
Software & Support Verlag




April 2006
aus Der Entwickler Ausgabe: 5.2002
Delphi goes .NET!
Auf der Borcon zeigt Borland den Weg zu Delphi for .NET
von Bernd Ua

Bereits Anfang des Jahres veröffentlichte Borland sein Commitment zur Unterstützung von Microsofts .NET-Plattform. Wie der Weg dahin aussehen sollte, war bis zur Borland Conference in Anaheim noch nebulös - man konnte nur raten, was Borland vor hatte. Inzwischen haben sich die Schleier etwas gelüftet und der Weg zur .NET-Unterstützung liegt offen. Wie Borland sich die .NET-Unterstützung durch Delphi vorstellt und was Sie als Entwickler erwartet, erfahren Sie in diesem Artikel.


Vorsicht! Bitte denken Sie daran, dass alle Aussagen, die auf der Borland-Konferenz zu Delphi for .NET und Delphi 7 gemacht wurden, immer von Safe Harbor Statements (can be subject to change without notice) begleitet wurden. Die Erfahrung zeigt, dass sich in einem halben Jahr noch viel ändern kann ...

Bereits in der Opening Keynote der Borcon wurde ein kleines Delphi-Programm gezeigt, das sowohl auf einem normalen Windows-Rechner als auch auf einem Handheld-PC lief. Allerdings fiel hier kein einziges Mal das Stichwort Delphi for .NET. Der eine oder andere Teilnehmer kam dann auch etwas verwirrt aus der Eröffnungssession und träumte von Delphi-Programmen für Handhelds mit Nicht-Microsoft-Betriebssystemen. Das wird wohl für die nahe Zukunft weiterhin ein Traum bleiben, sofern für das jeweilige Betriebssystem keine .NET-Umgebung zur Verfügung steht. Nativer Maschinencode für unterschiedliche Prozessoren ist die vorgebene Marschrichtung für den Borland C++ Compiler, der in seiner Architektur komplett überarbeitet wurde und durch eine dreischichtige Architektur leichter an andere Prozessoren wie Strong Arm angepasst werden kann. Um native Programme für Nokia-Handys zu schreiben, kommt man um C++ wohl leider nicht herum.

In der Keynote am ersten Tag, gehalten von Anders Hejlsberg, dem inzwischen zu Microsoft gewechselten Vater von Turbo Pascal und Delphi, war es dann so weit. Nach einer Einführung in .NET zeigte Hejlsberg ein bisschen Live Coding mit ASP.NET und Notepad als Entwicklungswerkzeug, das darin gipfelte, dass er Delphi als Script Processor im HTML-Code eintrug und eine Ereignisbehandlungsroutine im klassischen Pascal für die ASP-Seite programmierte. Besser hätte man die Integrationsmöglichkeiten, die .NET bietet, nicht zeigen können. Sicherlich ist es für einen Delphi-Entwickler gewöhnungsbedürftig zu sehen, wie Delphi als Scripting Engine bezeichnet und eingebunden wird. Überraschenderweise gab Hejlsberg als Microsoft-Mitarbeiter dann auch den .NET-Fahrplan und die Codenamen der nächsten Delphi-Versionen bekannt: In der zweiten Jahreshälfte erscheint zunächst Delphi 7 ( Codename Aurora ), das bereits Spracherweiterungen für .NET enthält, aber noch ein nativer Compiler ist. Mit im Paket ist ein Preview von Delphi for .NET, der wahrscheinlich aus dem Großteil des Frameworks und dem Kommandozeilencompiler besteht. Erst Anfang 2003 wird das richtige Delphi for .NET (Codename Galileo) als eigenes Produkt erscheinen. Delphi for .NET erzeugt dann keinen Maschinencode mehr sondern nur noch die Intermediate Language MSIL und ist damit eigentlich gar kein richtiger Native Code Compiler mehr. Der angekündigte Zeitplan war für die meisten anwesenden Delphi-Entwickler enttäuschend. Ein richtiges Delphi for .NET erst in einem Jahr ist ausgesprochen spät.

Sanfte Migration
Borland hat diesen Weg bewusst gewählt, um Delphi-Entwicklern eine sanfte Migration zu ermöglichen. Anders als das Microsoft Visual Basic-Entwicklern zugemutet hat bzw. zumuten musste, die zu Visual Basic .NET wechseln, sollen Delphi-Anwender mit möglichst überschaubarem Aufwand ihre Anwendungen portieren können. Diese größtmögliche Kompatibilität und Portabilität sei es, die diese Zeit benötigt, war die übereinstimmende Aussage aller Borland-Mitarbeiter. Danny Thorpe, Architekt des Delphi-Compilers sieht in Delphi 7 den nächsten großen Evolutionsschritt des Compilers, den er in eine Reihe stellt mit den grundlegenden Änderungen in Turbo Pascal 3 und 5.5 (Units und Objektorientierung) sowie Delphi 1 (Objektmodell mit RTTI). Die Common Language Specification von .NET erzwingt einige neue Sprachfeatures wie Namespaces, statics und Attributen in Klassen, die zum Teil auch Eingang finden sollen in den nativen Compilern unter Linux und Windows.

Änderungen für .NET
Zunächst erzeugen Sprachen, die .NET unterstützen, keinen nativen Code mehr, sondern CIL (Common Intermediate Language). Ein konkret erzeugtes Paket in CIL wird in .NET Syntax Assembly genannt. Vom Informationsgehalt sind die Assemblies vergleichbar mit Packages in Delphi, wenn man die Informationen der dcp-Datei mit denen der bpl-Datei kombiniert. Der CIL-Code enthält neben den Instruktionen noch Typinformationen und bleibt damit für den Just-In-Time Compiler (JIT) überprüfbar. Der JIT prüft bei der Kompilierung den CIL-Code auf Typsicherheit, Speicherbedarf und auch Rechte (so genannter Managed Code). Analog der Java Virtual Machine implementiert .NET Garbage Collection für verwendeten Speicher.

Jede Sprache, die .NET vollständig unterstützt, muss sich an den Sprachspezifikationen von Microsoft orientieren (Common Language Specification, CLS) und sich gegebenfalls den festgelegten Regeln der CLS unterwerfen. Ein Teil der CLS ist auch eine gemeinsame Grundlage von Datentypen, das so genannte Common Type System (CTS). Dank dieser gemeinsamen Grundlage sind Komponenten unterschiedlicher Sprachen miteinander verwendbar und können sich Klassenhierarchien über verschiedene Sprachen erstrecken. Alle .NET-Sprachen verwenden zudem ein gemeinsames Objektmodell und Basisobjekt, die Bestandteil der gemeinsamen Bibliothek sind (Common Language Runtime, CLR). Die Ausnahme von dieser Regel liefert Microsoft mit J#, welches auf dem Basisobjekt der CLR System.Object eine eigene Klassenhierarchie definiert. Jede Programmiersprache, die zu hundert Prozent kompatibel sein will, muss sich also etwas verbiegen, um sich an die vorhandenen Spezifikationen anzupassen. In gewisser Weise führt dies auch zu einer Nivellierung zwischen den Sprachen - seit Visual Basic.NET ist eben auch VB wirklich objektorientiert und versteht Vererbung.

Delphi Anpassungen
Damit Delphi sich nahtlos in das .NET-Framework einfügen kann, sind Änderungen an den Datentypen, Klassen und Bezeichnern unumgänglich. Ab Delphi 7 soll der Compiler beispielsweise Namespaces unterstützen. Bestehende Namespaces aus .NET werden wie Units eingebunden, sodass eine Uses-Anweisung in Delphi for .NET zum Beispiel so aussehen könnte:

Uses System.IO.Text, System.Web , System.Windows.Forms;

Für die bestehenden Klassen in Delphi werden eigene Namespaces geschaffen, die auf borland. basieren. Die Laufzeitroutinen werden sich wahrscheinlich im Namespace borland.delphi finden, VCL-Komponenten im Namespace borland.vcl und der Datenzugriff im Namespace borland.datasnap. Die Namespaces müssen nicht zwangsweise mit eigenen Units oder sogar Pfadnamen korrespondieren, sondern können als logischer Container gewählt werden. Damit nicht jede Uses-Anweisung überarbeitet werden muss, soll auch die Kurzangabe mit SysUtils statt borland.delphi.sysutils nach wie vor erlaubt sein. Geplant ist sowohl eine automatische Auflösung mit vorgegebener Suchreihenfolge als auch die Angabe von globalen Namespaces in der Projektdatei. Variablen oder Typen aus einem Namespace können im Programm qualifiziert angesprochen werden, wie dies zurzeit mit Bezeichnern in Units auch der Fall ist. Wenn es sich bei einem Bezeichner um ein in Delphi reserviertes Wort handelt, ist die Qualifizierung sogar zwingend erforderlich, damit der Compiler das reservierte Wort als Bezeichner akzeptiert. Die zulässigen Variablennamen in der CLS sind weit weniger restriktiv als die von Delphi und erlauben zudem reservierte Wörter aus Pascal als Bezeichner. Hier wird es aller Voraussicht nach einen Kompromiss geben, der Bezeichner mit dem Namen reservierter Wörter erlaubt, wenn ein Namespace vorangestellt ist. Gleiches gilt für Bezeichner in UniCode/UTF 8 die zurzeit in Delphi nicht erlaubt sind, aber in Zukunft erlaubt sein müssen.

Compiler Magic bei Klassen
Das Kennzeichen des Klassenmodells von Delphi, die Zwangsvererbung von Tobject, findet sich in dieser Form auch bei .NET. Alle Objekte stammen von System.Object ab. Die Klasse TObject von Delphi wird, wie einige andere Klassen auch, direkt auf diesen Typ aus der CLR gemappt, wie dies zur Zeit mit TWinControl und TWidgetControl oder IUnknown und IInterface der Fall ist. In der Unit System wird man bei Delphi für .NET den Quelltext von TObject nur noch als Einzeiler sehen :

type
TObject = System.Object;

Hier taucht allerdings eine Schwierigkeit auf.
System.Object hat lediglich die vier publizierten Methoden Equals, GetHashCode, ToString und GetType. Damit nach wie vor Code kompiliert, der auf Funktionen wie ClassName und ClassInfo zugreift, ist der Einsatz von Hilfsklassen geplant, die Aufrufe dieser Methoden automatisch umsetzen. Diese Hilfsklassen stellen lediglich eine Hilfe für den Compiler dar und ermitteln die benötigten Informationen über die von System.Object mit der Methode GetType bereitgestellten Typinformationen. Auch wenn das Konzept etwas unsauber wirkt, stellt es einen guten Kompromiss dar, der es möglich macht, ohne fundamentale Änderungen an bestehendem Sourcecode auszukommen. Der Borland-typische, ergebnisorientierte Pragmatismus eben. Langfristig sollten sich Delphi-Entwickler dann doch lieber mit der Reflection-Klasse aus dem .NET-System auseinandersetzen, zumal es unwahrscheinlich ist, dass die alten Methoden noch in der Programmierhilfe angezeigt werden. Für diverse weitere Basisklassen des Delphi-Laufzeitsystems gilt Ähnliches. Tabelle 1 gibt einen Überblick über das geplante Type-Mapping.

Neue Features in Klassen
Dank .NET finden auch einige Erweiterungen Eingang in das Objektmodell von Delphi, die bei einigen Entwicklern schon länger auf der Wunschliste stehen. Ab Delphi 7 wird es wahrscheinlich möglich sein, in Klassen sowohl Eigenschaften als auch Konstanten und statische Klassenmethoden zu definieren. Ebenso werden verschachtelte Klassendeklarationen (Nested Types) erlaubt sein:

type
TDelphi7Sample = class
class StaticData : Integer;
class property demo : String ...;
class static procedure Test;
type TNested = class
procedure Ping;
end;
end;

Für die zusätzliche Beschreibung von Eigenschaften, Methoden und Datenfeldern werden in .NET so genannte Attribute verwendet. Diese Attribute lassen sich zur Laufzeit ermitteln und auswerten und können beispielsweise angeben, ob es sich um eine Methode handelt, die als Web Service aufgerufen werden kann oder ob eine Eigenschaft serialisierbar ist.
Zusätzlich zu den vordefinierten Attributen können eigene Attribute definiert werden, die sich von der Basisklasse TCustomAttribute ableiten. Analog C# geben Sie Attribute auch in Delphi 7 in eckigen Klammern vor dem Bezeichner an:

type
TMyAttribute = Class(TCustomAttribute)
constructor Create(Name: String);
...
end;

[TMyAttribute ('Strange looking')]
TMyClass = class
[Datenattribut]
FData : Integer;
[WebMethod, DebuggerStepThrough]
function ProvideService: String;
end;

Auch das Eventhandling von Delphi wird überarbeitet. Die alte Syntax der Ereigniszuweisung mit dem Zuweisungsoperator bleibt funktionsfähig. Allerdings soll Delphi 7 standardmäßig auch die Zuordnung mehrerer Ereignisbehandlungsroutinen zu einem Ereignis unterstützen. Geplant ist die Erweiterung der Standardprozeduren Include und Exclude, die bisher lediglich mit Mengen gearbeitet haben. Mit Hilfe dieser Prozeduren sollen in Zukunft Ereignishandler zugefügt und entfernt werden können. Wie dies technisch genau realisiert wird, ließ Danny Thorpe allerdings im Dunkeln. Bleibt zu hoffen, dass das Delphi-Team nicht beim JBuilder abguckt und Listenerklassen in Prozedurparametern on the fly generiert.

Verlierer bei .NET
Von einigen Sprachelementen muss man sich allerdings bei Delphi for .NET (nicht unbedingt bei Delphi 7) verabschieden. Der aus aus Kompatibilitätsgründen zu Turbo Pascal bisher noch mitgeschleppte 6-Byte Gleitkommawert Real48 gehört ebenso dazu, wie das alte Schlüsselwort object für Borland Pascal-kompatible Objekte. Pointer, Speicherallokationen und unsichere Typecasts vertragen sich nicht mit safe und managed Code unter .NET. Entsprechend verschwinden der Operator @ , untypisierte Parameter, die Direktive absolute sowie die Prozeduren und Funktionen Addr, GetMem, FreeMem und ReallocMem. Als Workaround für den notorischen Byte-Fummler empfahl Danny Thorpe dynamische Arrays zu verwenden. Als Trostpflaster für diejenigen, die immer noch die alten Borland Pascal-Objekte einsetzen, können Erweiterungen für den Record in Pascal herhalten. In einer Record-Definition können demnächst auch statische Methoden enthalten sein:

TCustomer = record
CustNo : Integer;
Name : Integer;
procedure Rename( NewName: String);
end;

VCL oder Windows.Forms?
Delphi für .NET wird sowohl GUI-Design mit Microsoft-Klassen aus System.Windows.Forms als auch GUI-Design mit einer VCL-Variante anbieten. Welche Variante gewählt wird, hängt vom Einsatzzweck und den Vorlieben des Entwicklers ab. Für die Portierung einer bestehenden Anwendung wäre es sicherlich unsinnig, alles umzuschreiben. Bei einem neuen Projekt allerdings ist die Auswahl schon eine Überlegung wert. Das VCL-Framework für .NET setzt genauso wie System.Windows.Forms direkt auf der Windows-API auf und hat eine eigene Schnittstelle zum unmanaged Code der API. Es ist also kein zusätzlicher Wrapper für die bestehenden Klassen, sondern greift parallel auf die API zu. Änderungen in Aussehen und Funktion an den .NET-Klassen, die sich durch einen Wechsel des Systems/Service Packs oder Internet Explorers ergeben, lassen eine GUI-Anwendung, die auf VCL basiert, eher unbeeindruckt. Die Portierbarkeit auf andere Windows-Plattformen, wie beispielsweise PocketPC, ist schon bei Windows.Forms-basierenden Anwendungen nur eingeschränkt möglich und dürfte bei VCL-Anwendungen gänzlich unmöglich sein. Für die Weitergabe haben Anwendungen, die auf dem VCL-Framework basieren, zudem mehr Overhead, da in der Regel nur die Klassen für Windows.Forms installiert sind. Die Trennung zwischen Eigenschaftsdaten und Code in separaten Dateien wird für das VCL-Framework in jedem Fall beibehalten. Entwickler, die sich schon immer an der DFM-Datei gestört haben, werden eher zu Windows.Forms tendieren.

Das Package-Konzept wird im übrigen in ähnlicher Form beibehalten. Ein Assembly in .NET enthält zusätzlich zum Code in Intermediate Language die Symbolinformationen und entspricht damit in etwa einem Delphi-Package inklusive DCP-Datei. Fremde Komponenten in .NET-Assemblies bindet Delphi for .NET wie Packages ein. Für eigene Anwendungen und Delphi-Packages (bzw. Delphi-Assemblies) hat der Entwickler nach wie vor die Möglichkeit, mit oder ohne Laufzeit-Assemblies zu arbeiten. Entweder wird die Anwendung kleiner und benötigt auf dem Zielsystem die verwendeten Assemblies oder der Code aus einem Borland-Assembly wird direkt gelinkt, ohne dass auf dem Zielsystem die verwendeten Assemblies vorhanden sein müssen.

Datenbanken in Delphi für .NET?
Beim Thema Datenbankzugriff in Delphi für .NET waren die Informationen auf der Borland Conference noch sehr vage. Die Datenbankunterstützung wird über ADO.NET laufen. Es ist geplant, die bestehenden dbExpress-Treiber als Provider in ADO.NET einzubinden. Es ist wahrscheinlich, dass es einen zu den Borland-Datenbank-Komponenten kompatiblen Wrapper für die ADO.NET-Klassen geben wird.

Resümee
"Borland ist mal wieder zu langsam" oder "Das Delphi Team ist zu klein" dürften die ersten Resümees sein, die man aus dem Zeitplan ziehen kann. Notorische Schwarzseher denken auch gleich an das Ende von Delphi, nach dem Motto "Warum überhaupt noch Delphi for .NET einsetzen oder fast ein Jahr darauf warten". Der notorische Optimist kann sich damit trösten, dass JBuilder auch nur pures Java einsetzt und trotzdem die am weitesten verbreitete Java-IDE ist. Schon jetzt zeichnen sich doch so einige Unterschiede zu den Visual Studio Tools ab, die den Einsatz von Delphi rechtfertigen. Ganz ohne Quelltextänderungen wird auch keine Delphi-Anwendung nach .NET portierbar sein. Hält das Delphi-Team aber seine eingeschlagene Richtung bei, dürfte der Portierungs- und Lernaufwand für Delphi for .NET um Dimensionen geringer sein, als das beispielsweise bei Visual Basic der Fall war. Ein weiterer Vorteil ist die Kompatibilität mit anderen Sprachen. Es ist für einen Delphi-Entwickler in Zukunft nicht mehr nötig, Headerfiles von C zu übersetzen. Jedes .NET-Assembly, egal in welcher Sprache erstellt, kann von der IDE verwendet und eingebunden werden. Das vergrößert das Angebot bestehender Komponenten ungemein und eröffnet auch den Komponentenherstellern neue Dimensionen.


    Hat Ihnen dieser Artikel gefallen? Dann abonnieren Sie das Entwickler Magazin direkt über unser Online-Formular.



zur vorherigen Seite
zurück
an den Anfang der Seite
nach oben
Diesen Artikel drucken
drucken
Diesen Artikel weiterempfehlen
empfehlen
Software & Support Verlag GmbH