|
![]() |
Der Blick über den Tellerrand In den letzten Tagen habe ich mich eingehend mit einem Produkt beschäftigt, welches meines Erachtens viel zu wenig Beachtung erhalten hat. Die Rede ist von ![]() Meine Highlights Ich möchte an dieser Stelle keine komplette Liste abarbeiten, das darf jeder auf der Seite des Herstellers selber tun. In diesem Artikel werde ich eine ganz subjektive Auswahl treffen. Da ich noch nicht allzu lange mit Chrome arbeite, werden das wahrscheinlich noch nicht einmal die wirklichen "Highlights" der Sprache sein. Als Erstes möchte ich auf Dinge eingehen, die der Compiler für den Programmierer erledigt. Und davon gibt es einige. Vor allem anderen gefällt mir dabei die so genannte "Type Inference", was soviel heißt, dass der Compiler nicht nur die Typen meiner Variablen erkennt, sondern erkennt, dass ich überhaupt eine neue Variable einführen will. Letzteres gilt für Variablen mit begrenzter Lebensdauer (also z.B. in with-Anweisungen). Wie sieht das genau aus? So z.B.:
Delphi-Quellcode:
Wir müssen foo nirgendwo deklarieren und wir müssen auch nicht den Typ von foo angeben.
with foo := new Tfoo() do
begin foo.DoSomething(); end; Ähnlich einfach kann man bei Bedarf neue Variablen einführen.
Delphi-Quellcode:
Diese Zeile steht, wie man sieht, irgendwo im Quelltext und nicht im Deklarationsteil.
begin
var bar := new TBar(); end; Ähnlich praktisch ist auch die Deklaration von Zählern: for i : Integer := 0 to 5 do In der for-schleife muss man diese Syntax wählen, welche auch eine Variablendeklaration enthält. Sie ist mit den oben demonstrierten Syntaxschemas kompatibel. Type Inference ist das dann natürlich nicht mehr. ![]() Ein guter Punkt, um zum nächsten Beispiel zu kommen, wo der Compiler Arbeit übernimmt. Oft kommt es vor, dass eine Property einfach nur ein privates Feld kapselt, also gar keine get- und set-Methoden vorhanden sind. Hier hilft Chrome, den ewig gleichen Standardcode zu vermeiden, indem es folgende Syntax erlaubt:
Delphi-Quellcode:
Mehr ist nicht nötig, um eine Property anzulegen, der Rest wird implizit deklariert. (Obiges Beispiel zeigt ein weiteres Chrome-Feature: Typensichtbarkeit wird vollständig unterstützt.)
type
TFoo = public class public property aProp : String; end; Kommen wir zu Kleinigkeiten, bei denen man erst einmal denkt, dass das nicht erwähnenswert ist. Aber zumindest mir geht es so, dass die Kleinigkeiten, denen man immer wieder begegnet, einen hohen Stellenwert erhalten. Da wäre zum einen die exit-Methode, der man einen Parameter übergeben kann. Anstatt also
Delphi-Quellcode:
schreiben zu müssen, reicht ein if aVal = anotherVal then exit(someVal);
. Wie gesagt, eine Kleinigkeit, aber man gewöhnt sich dran
if aVal = anotherVal then
begin result := someVal; exit; end; ![]() Nächste Kleinigkeit: "empty". Schonmal eine Methode gehabt, die im interface stehen musste, aber nur ein Dummy war? Kein Problem. Einfach folgendermaßen deklarieren:
Delphi-Quellcode:
Im implementation-Teil muss kein Dummy mehr angelegt werden. Kleinigkeiten, an die man sich gewöhnt ...
type
TFoo = public class public method aMethod; empty; end; Auffällige Sprachunterschiede zu Delphi Ich könnte meine Highlights noch fortsetzen und je länger ich mit Chrome arbeite, werde ich Neue entdecken. Aber das würde wohl mit der Zeit langweilig werden. Daher will ich noch ein paar auffällige Sprachunterschiede vorstellen, die ich nicht so liebgewonnen habe, die aber trotzdem von Bedeutung sind. Allen voran wäre da die Unterstützung von Generics. Sie sind eine der Voraussetzungen, die eine Sprache für .NET 2.0 erfüllen muss, und sie haben daher auch Einzug in Chrome gefunden. Die Syntax ist praktisch dieselbe wie in C#: var li : List<Integer> := new List<Integer>(); oder auch (Zitat aus der Chrome-Doku)
Delphi-Quellcode:
Also auch die Unterstützung für Constraints ist da.
type
MyArrayList<T> = public class(ArrayList, IPersistentCollection) where T is PersistentObject, T has constructor; Weil ich an dieser Stelle nicht weiter auf Generics eingehen möchte (das ginge zu weit), möchte ich Euer Augenmerk auf das erste Code-Beispiel zu Generics lenken und zwar auf die Konstruktor-Syntax. Da .NET keine Konstruktoren mit Namen kennt, wurde auch in Chrome darauf verzichtet. Anstatt einen Defaultnamen wie z.B. "Create" und die Funktionensyntax zu verwenden, wurde auf die von C# bekannte new-Syntax zurückgegriffen. Es ist Geschmackssache, was man besser findet, logisch erscheinen mir beide. Ich muss aber zugeben, dass es am Anfang komisch aussieht, in Pascal mit "new" zu arbeiten ![]() Ein weiterer Sprachunterschied zu Delphi sind die so genannten "Class Contracts". Class Contracts dienen der Überprüfung von Bedingungen, die vor / nach der Ausführung einer Methode wahr sein müssen (require / ensure) bzw. innerhalb einer Klasse immer erfüllt sein müssen (Invariants). An dieser Stelle sei erneut ein Beispiel aus der Chrome-Doku zitiert:
Delphi-Quellcode:
Es spricht eigentlich für sich, was hier passiert. Es wird sichergestellt, dass aValue nicht Null ist, weil durch Null zu teilen im Allgemeinen keine gute Idee ist. Invariants möchte ich an folgendem Beispiel demonstrieren:
method MyObject.DivideBy(aValue: Integer);
require aValue <> 0; begin MyValue := MyValue/aValue; end;
Delphi-Quellcode:
Hier wird festgelegt, dass die Eigenschaft "length" niemals kleiner Null sein darf. Wird sie es doch, wird eine Ausnahme geworfen. (Übrigens wäre diese Klasse so fertig, im implementation-Teil muss nichts mehr gemacht werden.)
type
TComplex = public class public property length : Double; public invariants length >= 0; end; Dass auf jeden Topf ein Deckel passt, ist bekannt. In Delphi muss man die Deckel allerdings selber aussortieren, was in Chrome für einen erledigt wird. Ein Beispiel (wieder aus der Doku) macht es deutlich:
Delphi-Quellcode:
Anstatt, dass die foreach-Schleife stupide alle Elemente durchläuft und man selber dafür verantwortlich ist zu schauen, ob es sich um den richtigen Typen handelt, werden hier nur bei den Elementen in den Schleifenrumpf gesprungen, welche der matching-Bedingung entsprechen.x := new ArrayList(); x.add('Test'); x.add(123); for each matching S: String in x do console.writeline(s); Den letzten hier genannten Sprachunterschied möchte einfach mal unkommentiert stehen lassen ![]()
Delphi-Quellcode:
case forum of
'df': DoDelphiForum; 'csf': DoCSharpForum; 'dl': DoDelphiLibrary; 'csl': DoCSharpLibrary; else DoEntwicklerEcke; end; Nobody is perfect Doch auch Chrome hat Schwächen. Die liegen ganz klar nicht in der Sprache, sondern im Editor. Da ich momentan mit einem RC arbeite, will ich auf Fehler hier nicht eingehen, die können in der Final schon behoben sein. Es geht mir viel mehr darum, dass viele Refactoring-Funktionen entweder vollständig fehlen oder ungenügend umgesetzt wurden. Smart Editing nennt sich das, was Chrome an Refactoring liefert. Doch was ist das? Zuerst einmal wären da die Navigation zwischen implementation- und interface-Abschnitt, wie man sie aus Delphi kennt. Ebenso die Klassenvervollständigung. Code Folding ist ebenfalls nichts Neues und das man Parameterlisten in einem Hint erhält, wenn man eine Funktion aufrufen will, ist inzwischen einfach Standard. Die Code-Vervollständigung hat in Chrome einige wünschenswerte und praktische Ergänzungen erfahren. So wird das Erstellen von Properties dadurch unterstützt, dass man automatisch die entsprechenden get- und set-Methoden oder private Felder anlegen kann. Auch bietet die Vervollständigung beim Anlegen von Klassenoperatoren eine Liste der verfügbaren Operatoren. Eine Kleinigkeit, an die man sich wieder schnell gewöhnt: Tippt man "begin" und die Eingabetaste, wird das "end;" ergänzt und der Cursor an die richtige Stelle gesetzt. Ein guter Ansatz, aber absolut nicht zu Ende gedacht, ist das Sync Rename. Damit sollte es eigentlich möglich sein, Mehtoden oder Klassen einfach umzubenennen. Leider heisst "Sync" hierbei nur, dass Änderung an diesen beiden Dingen (also Methode- und Klassennamen, anderes wird nicht unterstütz) synchron in interface- und implementation-Abschnitt gemacht wird. Aber im implementation-Abschnitt auch nur im Kopf der Methoden, nicht im Code. Und da muss ich einfach mal Fragen: Was soll das? Ich habe die Methode zigmal im Quelltext stehen und der ersetzt mir automatisch das Vorkommen, was ich am einfachsten selber finden kann? Na, vielen Dank auch. Dann wäre da noch die automatische Deklaration von Variablen. Setzt man den Cursor auf einen Bezeichner und drückt eine Tastenkombination, erstellt Chorme eine entsprechende Property (Bezeicher fängt mir großen Buchstaben an), ein privates Feld (Bezeichner fängt mit "f" an) und ansonsten eine lokale Variable. Eine andere Tastenkombination erstellt eine neue Methode Mehr an Refactoring gibt es nicht und das muss man einfach mal als mager bezeichnen. Da ist man deutlich mehr gewohnt und eine Firma, die ganz klar eine Konkurrenz zu Delphi präsentieren will, sollte auch auf diesem Bereich etwas mehr zu bieten haben. Und da muss man klar sagen: Delphi 2005 (2006 hab ich nicht) bietet deutlich mehr Komfort in diesem Bereich. Mein Fazit Ich habe den Kauf von Chrome nicht bereut und arbeite sehr gerne damit. Die Sprache bietet so viele Features, dass das Arbeiten trotz des dürftigen Editors Spaß macht. Ich entdecke immer wieder neue Features, die mir ein "Cool!" entlocken. Kurz um: Bei Chrome hat man einfach mal den Staub von der Sprache Pascal gewischt und das ist auch gut so. Das fehlende Refactoring ist ein deutlicher Mangel, aber es hat mich bisher nicht soweit gestört, dass es in mir Zweifel am Kauf von Chrome geweckt hätte. Dieser Artikel kann auch auf meiner Homepage abgerufen werden: ![]() Crossposting Entwickler-Ecke: ![]() //edit: Link zur Chrome-Homepage eingefügt |
Turbo Delphi für .NET |
#11
Ich finde es eigentlich auch recht gut, dass z.B. Variablen fest im Methodenkopf deklariert werden müssen. Ist einfach übersichtlicher. Gut, bei Variablen, die nur für eine For-Schleife benötigt werden, ist das vielleicht gar nicht so schlecht.
Aber nett, vielleicht kaufe ich mir das auch mal ![]() Ein wenig Bedenken habe ich jedoch dabei, dass die Firma ja noch recht jung ist und evtl. schnell wieder vom Markt verschwinden kann. Oder Nachfolgeversionen nicht mehr abwärtskompatibel sind. Wer übersetzt mir dann mein eigentlich fertiges Programm in eine neue Sprache ? Nachtrag: Was ich aber sehr fair finde ist das: ![]() Chrome 1.5 is a free update for all existing users of Chrome 1.0.
![]()
Alexander
|
![]() |
Delphi 7 Enterprise |
#12
![]() Wer übersetzt mir dann mein eigentlich fertiges Programm in eine neue Sprache ?
![]()
André
|
![]() |
Delphi 2010 Professional |
#13
Hallo Christian,
![]() ...
Ja, einige der Features von Chrome sind eine klare Abkehr von den Regeln, die Pascal dem Programmierer auferlegt, um sauberen Code zu erzwingen. Ich würde daher Delphi auch Chrome als Sprache für Anfänger vorziehen. Aber irgendwann ist man aus dem Stadium heraus, dass man einen Compiler braucht, der einem Vorschriften macht, um lesbaren Code zu erzeugen. Und an dem Punkt kommt mir Chrome sehr entgegen, weil es mir mehr Freiheiten gibt....
Albert
|
![]() |
Delphi 2010 Professional |
#14
![]() Ich finde es eigentlich auch recht gut, dass z.B. Variablen fest im Methodenkopf deklariert werden müssen. Ist einfach übersichtlicher.
Zum Bleistift wenn man die Variable auch in der "require" oder "ensure" Clause benutzen will.
Delphi-Quellcode:
Ansonsten benutzt man eher using oder with-Blöcke, da kann man sofort sehen wo der Wert herkommt und die Variable lebt nur in diesem Block.
var
mieps := iif(assigned(someParameter), someParameter.GetMieps(), nil); require assigned(someParameter); assigned(mieps); mieps.Count > 0; begin ... ensure mieps.Count = old mieps.Count - 1; end;
Delphi-Quellcode:
Variablen am Beginn einer Methode bringen IMO keineswegs mehr Übersichtlichkeit. Wenn ich hingegen den Methodenrumpf zusammenklappe und erst auf die Contracts schaue weiß ich viel mehr über das was in der Methode passiert und vor allem welche Zustände sie benötigt und welchen Endzustand sie garantiert.
using dialog := new MyDialogForm(SomeProperty := 'miep') do
begin if dialog.ShowDialog() = DialogResult.Ok then blabla end; ![]() Ein wenig Bedenken habe ich jedoch dabei, dass die Firma ja noch recht jung ist und evtl. schnell wieder vom Markt verschwinden kann.
btw: hinter Klaradingsens Link findest du auch warum es Chrome überhaupt gibt. RO hat nämlich seine .Net Versionen der Delphiprodukte in Chrome geschrieben. Solange es also das RO SDK un DA gibt, wird es zwangsläufig auch Chrome geben. ![]() ![]() Oder Nachfolgeversionen nicht mehr abwärtskompatibel sind.
Sie sind auch ein wenig zurückhaltend was Features angeht, die komplett "unpascalish" wären: Ich habe sie z.Bsp. bis heute nicht von +=, -=, ++, -- überzeugen können. (habe es aber schon vor langem aufgegeben. ![]() Wobei += und -= nur für Events vorhanden waren. [1] das beschränkt sich aber eigentlich nur auf
![]() Was ich aber sehr fair finde ist das:
![]() Chrome 1.5 is a free update for all existing users of Chrome 1.0.
![]() ![]() Eine deutsche Version fände ich auch nicht schlecht
![]() @MrSpock Viele von Delphis Einschränkungen sind IMO nur vermarktet als qualitätsfördernde Strenge. Gäbe es den Zwang, Variablen nur in der Var section deklarieren zu können, wirklich nur um saubereren Code zu erzwingen, hätte es niemals ein with in dieser kranken Form gegeben. ![]() Ich denke eher, dass die Investition in einen Compiler, der dazu in der Lage wäre, gescheut wurde. Aber Chrome ist IMO keine Sprache für Anfänger, schlicht und ergreifend weil ich keine richtige (also mit Ausnahme von KPL ![]()
Robert Giesecke
|
![]() |
Frickeldrecktuxer_TM
|
#15
![]() Hört sich an, wie irgendwann bin ich so gut, dass ich keinen sauberen Code mehr schreiben muss.
![]() ![]() Ich programmiere jetzt schon seit über 20 Jahre und habe mich durch Pascal / Delphi nie eingeschränkt gefühlt, glaube aber gut wartbaren Code zu schreiben.Sinnvolle Erweiterungen hat es ja im Laufe der Zeit auch in Delphi's Pascal gegeben.
Und ich persönlich finde es in komplexen Funktionen deutlich unübersichtlicher, alle Variablen im Funktionskopf zu haben. Man nehme zum Beispiel eine Nachrichtenbehandlungsroutine:
Code:
Mit passenden Optimierungen hältst du dir damit auch noch den Stack sauber. Angenommen ich bräuchte für jede Nachricht 5 Variablen unterschiedlichen Typs. Warum sollte ich mir meinen Funktionskopf mit 25 Variablen zukleistern? So kann ich wunderbar die Variablen dort deklarieren, wo ich sie benötige. Nur dort sind sie gültig und Objekte werden automatisch freigegeben, sobald der Scope verlassen wird (okay, sowas kennt Delphi nicht, aber das ist ja ein anderes Thema).
void myhandler(message_t somemmessage)
{ switch (somemmessage.type) { TYPE_1: { int i; // und weitere Variablen, die ich nur in dem Fall benötige, wenn ich Nachrichten vom Typ 1 erhalte break; } TYPE_2: { int i; // und weitere Variablen, die ich nur in dem Fall benötige, wenn ich Nachrichten vom Typ 2 erhalte break; } TYPE_3 { int i; // und weitere Variablen, die ich nur in dem Fall benötige, wenn ich Nachrichten vom Typ 3 erhalte break; } TYPE_4: { int i; // und weitere Variablen, die ich nur in dem Fall benötige, wenn ich Nachrichten vom Typ 4 erhalte break; } TYPE_5: { int i; // und weitere Variablen, die ich nur in dem Fall benötige, wenn ich Nachrichten vom Typ 5 erhalte break; } default: break; } } Vom Entwickler wird bezüglich der Wartbarkeit nur verlangt, daß er nicht einfach "irgendwo" die Variablen deklariert, dann das wäre wirklich unübersichtlich. Aber der Entwickler hat so ein feineres Werkzeug um zu bestimmen, wie lange die Variablen überhaupt existieren und bezüglich der Wartbarkeit den Variablen einen Block zuzuordnen, zu dem sie gehören. Dieses Märchen, daß die Pascal-Syntax automatisch für wartbaren Code sorgt und daß alle anderen Programmiersprachen dadurch automatisch böhse[tm] sind, habe ich oft genug gehört, als daß ich es noch ernstnehmen würde. Wartbarer Code liegt immer am Entwickler. Wer mit C oder C++ keinen wartbaren Code schreibt, benutzt sein Werkzeug falsch. |
![]() |
|
#16
Wie kann sich denn das:
![]() Aber irgendwann ist man aus dem Stadium heraus, dass man einen Compiler braucht, der einem Vorschriften macht, um lesbaren Code zu erzeugen.
![]() Hört sich an, wie irgendwann bin ich so gut, dass ich keinen sauberen Code mehr schreiben muss.
![]() Ich programmiere jetzt schon seit über 20 Jahre und habe mich durch Pascal / Delphi nie eingeschränkt gefühlt, glaube aber gut wartbaren Code zu schreiben.
Christian S.
|
![]() |
Delphi 8 Professional |
#17
![]() ..Hört sich an, wie irgendwann bin ich so gut, dass ich keinen sauberen Code mehr schreiben muss...
![]() ![]() ![]() Einige "Erweiterungen" durch Chrome sehe ich zumindest als klare Nachteile an. Und was nützt es mir, wenn ich sie dann gar nicht brauche oder vorsichtshalber nicht benutze ? Übrig bleiben mehr Nach- als Vorteile. Meine Meinung dazu ! Solche Threads führen sowieso zu keinem Ergebnis. |
![]() |
Delphi 10.4 Sydney |
#18
![]() Solche Threads führen sowieso zu keinem Ergebnis.
Christian hatte doch selbst schon geschrieben, dass es sich um einen Blick über den Teller-Rand handelt und das im Endeffekt jeder für sich entscheiden müsse. Es wäre schön, wenn Ihr wieder zu einer sachlichen (!) Bewertung zurückfinden könntet. Ganz nebenbei geht es hier nicht um "Highlander" - es kann also auch mehr als einen geben. ![]()
Daniel R. Wolf
|
![]() |
Frickeldrecktuxer_TM
|
#19
![]() einige fühlen sich offensichtich geradezu ermuntert, die Fehler von C-Programmierern nachmachen zu müssen.
![]() Ich kann nur sagen : es lebe die Freiheit, die nur die Inkompatibilität zur Folge hat.
![]() ![]() Kommt es auf die IDE an, oder auf die Programmiersprachen-Syntax ? Erst wird Delphi auf diese "Mist-IDE" reduziert und nun isr die ziemlich egal, denn die Syntax von Chrome ist ja so viel besser und bietet viel mehr ?
![]() Also, um deine Frage zu beantworten: Ja, die Syntax von Chrome ist für einige so viel besser und bietet (faktisch, nicht für einige) viel mehr, deswegen kann Delphi aber weiterhin eine "Mist-IDE" sein, weil das eine das andere nicht ausschließt. Chome hat schließlich nichts mit Delphi oder Borland gemein. ![]() Einige "Erweiterungen" durch Chrome sehe ich zumindest als klare Nachteile an.
![]() Und was nützt es mir, wenn ich sie dann gar nicht brauche oder vorsichtshalber nicht benutze ?
![]() Übrig bleiben mehr Nach- als Vorteile.
|
![]() |
Delphi 7 Enterprise |
#20
![]() Ein guter Punkt, um zum nächsten Beispiel zu kommen, wo der Compiler Arbeit übernimmt. Oft kommt es vor, dass eine Property einfach nur ein privates Feld kapselt, also gar keine get- und set-Methoden vorhanden sind.
Hier hilft Chrome, den ewig gleichen Standardcode zu vermeiden, indem es folgende Syntax erlaubt:
Delphi-Quellcode:
Mehr ist nicht nötig, um eine Property anzulegen, der Rest wird implizit deklariert. (Obiges Beispiel zeigt ein weiteres Chrome-Feature: Typensichtbarkeit wird vollständig unterstützt.)
type
TFoo = public class public property aProp : String; end;
Delphi-Quellcode:
Jetzt hab ich ein wenig mehr Code, wenn ich aber in der Klasse TFoo arbeite, weiss ich immer genau was passiert. Wenn ich dort naemlich "fremden" Code von Kollegen durchgehe, kann ich bei jeder Zuweisung erstmal nachschauen, ob nicht eine Setter-Methode noch mehr macht als nur die Variable zu setzen. Wenn sich aber jeder daran haelt innerhalb der Klasse nur auf die Feldvariablen zuzugreifen, kann ich auf einen Blick ausschliessen, dass noch irgendwas sonst passiert.
type
TFoo = public class private FProp: String; public property Prop : String read FProp write FProp; end; Wenn mich diese klare Trennung von Feldvariablen und Properties nicht sonderlich kuemmert, dann kann ich zur Not auch einfach die Variablen als public deklarieren ![]() Gruss, Lizzy |
![]() |
Ansicht |
![]() |
![]() |
![]() |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
![]() |
![]() |