4. Wieso ist es also so schwer von VB6 zu Visual Basic .NET zu wechseln?
Wieso ist es also so, dass viele der Anwendungen immer noch unter Visual Basic 6 im Einsatz sind, und es nicht längst eine Migration von VB6 zu VB.NET gegeben hat – schließlich gibt es doch ein neues Basic, das genau für diese Zielgruppe gedacht war? Dazu muss man wissen:
Die Namensgebung von Visual Basic .NET ist eine Mogelpackung – es hätte fairerweise B# (B-Sharp) heißen müssen.
Die Namensgebung von Visual Basic .NET ist Grunde genommen eine Mogelpackung, und hätte lieber B# heißen sollen, um von vorneherein deutlich zu machen, dass es sich sehr vom Vorläufer unterscheidet. Zwar verwendet VB.NET im Gegensatz zu VB6 viele der Schlüsselwörter und Strukturen des Visual Basic-Vorgängers – es ist aber C# viel ähnlicher als C++ zu C#. Sehr viel ähnlicher. C#-Entwickler sind über diese Tatsache oft sehr verwundert – für Visual Basic 6-Entwickler ist das beim Erstkontakt ein regelrechter Schock, und auch die Erklärung: VB6-Code läuft schlicht nicht unter oder als VB.NET. So seltsam es auch klingt, vielleicht auch weil das Wort „Migration“ ein wenig negativ behaftet ist: einer Migration der eigentlichen Software muss im Falle von Visual Basic deswegen auch immer erst eine Migration des Entwicklungs-Teams voran gehen. Für Visual Basic 6-Entwickler entsteht dabei oft eine lange, teils schmerzhafte Phase des Abschiednehmens von alten Gewohnheiten und dem Neuerlernen von modernen Vorgehensweisen, deswegen sollte – ganz wichtig – die Teamleitung ausreichend Zeit für die Einarbeitung lassen und vor allen Dingen nach Möglichkeit ganze Tage einrichten, an denen die Entwickler wirklich Luft und einen freien Kopf zum Experimentieren und Lernen haben. Denn zu Lernen gibt es eine ganze Menge:
Be sharp, learn VB. Again.
Nicht nur gibt es viele Datentypen in .NET nicht mehr (Variant) oder unter neuem Namen (Currency wird zu Decimal) – bei Datentypen ändern sich Eigenschaften von einer Version zur anderen auch komplett: Integer unter VB6 ist 16 Bit breit, unter .NET sind es 32 Bit. Long unter VB6 ist 32bittig, unter .NET selbstverständlich wie in C# 64-bittig. Dazu verhält sich Code beim Umgang mit den Datentypen auch völlig anders: Dividiert man in VB6 einen Wert vom Typ Double durch 0, löst das einen Fehler aus. In .NET gibt das ein gültiges Ergebnis ohne Ausnahme, nämlich, je nach positivem oder negativem Dividend, Double.PositiveInfinity oder Double.NegativeInfinity. Arrays können in Visual Basic 6 beliebige obere und untere Grenzen haben, in .NET sind sie immer 0-basierend. Der Zugriff auf Objekte erfolgt in VB6 über ein spezielles Schlüsselwort, Set, da die Sprache in der Version 6 ganz einfach mehr mit Objekten umging, als sie tatsächlich selbst zu definieren. Auch aus diesem Grund kannte VB6 die sogenannten Standardeigenschaften; in VB.NET haben diese eine völlig neue Bedeutung. In VB6 würde so die Anweisung TextBoxVar = obj dazu führen, dass die Standardeigenschaft Text der TextBox-Instanz neu definiert würde. Für das Setzen einer neuen TextBox-Instanz wäre hingegen die Anweisung Set TextBoxVar = obj vonnöten. In VB.NET macht aber TextBoxVar = obj genau dieses, das Set-Schlüsselwort zum Setzen einer neuen Referenz in einer Objektvariablen gibt es hier nicht mehr, und um eine Eigenschaft neu zu definieren, muss der Eigenschaftenname auch wirklich genannt werden: TextBoxVar.Text = obj.
Dazu kommt: Visual Basic 6 ist nicht typsicher.
Visual Basic .NET hat mit Visual Basic 6 einiges gemeinsam – aber verlangt völlig andere Herangehensweisen bei der Softwareentwicklung als VB6. Es gilt, für Teams gezielt die für das Team wichtigen „Best Practices“ zu lernen, um so schnell wie möglich wieder produktiv und zielgerichtet arbeiten zu können.
Der Compiler macht nicht nur unproblematische, erweiternde (Integer zu Long) sondern auch gefährliche, schmälende Typ-Castings (Long zu Integer) bzw. ganze Typumwandlungen (String zu Date oder Integer) mit, ohne entsprechende Warnungen oder Fehler auszugeben. Er produziert sogar den Code, damit eine Umwandlung von einer Zeichenkette in einen anderen primitiven Datentyp funktionieren kann. In C# ist das undenkbar, in Visual Basic .NET zum Glück abschaltbar. Genau dieses liberale Verhalten des VB6-Compilers sollte aber bei einer VB6-Migration zu .NET abgestellt werden, da es der Grund für viele, schwer zu findende Bugs ist – als Zeichenkette wird bei absteigender Sortierung der „21.02.2010“ nach dem „22.05.2005“ einsortiert, erst als wirklicher Datumswert genau umgekehrt und korrekt.
Schon diese paar Punkte, die bestenfalls einen Eiswürfel auf der Spitze des Eisbergs darstellen, machen deutlich, dass alle Algorithmen angepackt, umgeschrieben und gründlich neu getestet werden müssen und nur in den seltensten Fällen können Migrationstools dabei helfen – eine aufwändige Nacharbeit und intensives Testing bleibt in jedem Fall erforderlich.
Dabei stellen die unterschiedlichen Verhaltensweisen der VB-Anwendungen bei gleicher Syntax nur eine Hürde dar, die mit Fleißarbeit und gutem Tooling noch zu nehmen ist. Ungleich schwieriger sind die unterschiedlichen Paradigmen, mit denen in Visual Basic 6 und Visual Basic .NET idealerweise programmiert wird – bzw. leider programmiert wurde: In Visual Basic 6 nämlich prozedural und in Visual Basic .NET wirklich und vollständig objektorientiert.
Klassenfeind VB6: Kein noch so gutes Migrations-Tool macht aus einer prozeduralen VB6-Anwendung eine objektorientierte .NET-Anwendung – und die Altlasten werden auch nicht beseitigt!
Ein Beispiel: In Visual Basic 6 landen Zeichenketten direkt in Container-Steuerelementen wie beispielsweise ListBoxen, in .NET komplette Klasseninstanzen, die dann – im OOP-Sinne – für ihre Text-Repräsentation selbst sorgen.
Für C#-, C++, Java und Delphi-Programmierer ist das ein nicht erwähnenswerter Normalzustand, 95% aller VB6-Programmierer stehen hier erst einmal wie der Ochs vorm Berge. Ihre Sprache kennt nämlich keine klassische Vererbung, und damit auch kein polymorphes Aufrufen von Methoden über Variablen von gemeinsamen Basistypen einer Objekthierarchie, wie es die ListBox beispielsweise auf einfachste Weise mit ToString macht, um ein Objekt in seine Zeichenkettenrepräsentation umzuwandeln.
Genau das ist die große Gefahr, wenn komplexe Projekte mit Migrations-Tools abgewickelt werden sollen: In der Regel werden alle Altlasten mitmigriert, und das Team muss sich weiterhin mit ihnen herumschlagen. Und bei schlüsselfertigen Migrationen, wie sie einige Firmen anbieten, kommt dazu erschwerend hinzu: Das Team bleibt außen vor, es ist später nicht in der Lage, den migrierten Programmstand zu pflegen.