Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Die Delphi-IDE (https://www.delphipraxis.net/62-die-delphi-ide/)
-   -   Interface-Unterstützung (https://www.delphipraxis.net/193733-interface-unterstuetzung.html)

stahli 8. Nov 2017 11:35

AW: Interface-Unterstützung
 
@Uwe

Was ist denn an meinen Anforderungen speziell?

Ich hätte gedacht, dass jeder, der intensiver Interfaces benutzt, über das gleiche Problem stolpert.

Wenn eine Klasse mehrere Interfaces unterstützt, kann man das nicht mehr einfach über Vererbung abfrühstücken und müsste somit mindestens einige (oder sogar alle) Member neu implementieren.

Das ist besonders bei Gettern und Settern nervig, weil dort ja i.d.R. eh nur in ein privates Feld geschrieben oder daraus gelesen wird. Und dann sollte das als Standardweg halt automatisch voreingestellt werden. Bei Bedarf kann man es dann ja immer noch ändern.


Als Fazit würde ich mal ziehen, dass keiner zu doof ist ;-) und das Tool mal weiter basteln.

TiGü 8. Nov 2017 12:00

AW: Interface-Unterstützung
 
Zitat:

Zitat von Stevie (Beitrag 1385618)
Zitat:

Zitat von TiGü (Beitrag 1385572)
Meiner Meinung nach wäre es viel sinnvoller, wenn es ein Tool geben würde, dass automatisch vergessende Semikolons hinter die Zeilen tackert.
Das regt mich immer maßlos auf! Schnell was hingeschrieben, Strg + F9 und Bumm:
"Nak nak nak, Sie haben ein Semikolon vergessen...ich als Compiler finde das voll doof...ich könnte zwar selber eins hinbasteln, aber ich will Sie als Programmierer noch ein bissel gängeln!".

Es soll Programmiersprachen geben, wo man gar keine Semikolons machen muss, weil der Compiler schlau genug ist, zu erkennen, wo Anweisungen enden.

Ketzerei! :evil:

Wosi 8. Nov 2017 12:15

AW: Interface-Unterstützung
 
Zitat:

Zitat von stahli (Beitrag 1385627)
Ich hätte gedacht, dass jeder, der intensiver Interfaces benutzt, über das gleiche Problem stolpert.

Bisher bin ich nicht über das Problem gestolpert, obwohl 99% meiner Klassen Interfaces implementieren. Allerdings unterscheidet sich mein Code-Design in mindestens zwei Punkten von deinem:

- Nur ein kleiner Bruchteil der Klassen implementiert mehr als ein Interface
- Es gib kaum Setter. Kurzer Überblick über eines meiner Projekte: In 171 Interfaces gibt es 239 Properties. Davon haben 18 einen Setter. Die beschreibbaren Properties verteilen sich auf 8 Interfaces, von denen es jeweils nur eine Implementierung gibt.

Eventuell liegt das Problem auch in einem unglücklich gewähltem Klassen-Design, das dich zu immer wiederkehrenden Anpassungen zwingt. Hast du ein praktisches Beispiel für die mehrfache Implementierung von Interfaces mit Settern?

stahli 8. Nov 2017 12:50

AW: Interface-Unterstützung
 
Meinen aktuellen Quelltext will ich hier nicht veröffentlichen.

Aber ich erstelle ein früheres Projekt noch einmal neu und überarbeite dabei gleich komplett das Klassendesign (schreibe Interfaces wie am Fließband ;-) ).

Ausgehen tue ich dabei immer von Interfaces (Funktionalitäten).

Die tatsächlichen Klassen sind hinter einer Factory versteckt, so dass die Businesslogik nur noch die Interfaces kennt und benutzt.

Da es viele Überschneidungen der Funktionalitäten gibt, müssen mehrere Klassen auch mehrere Interfaces unterstützen.


Ok, mag sein, dass mein Klassendesign schon etwas ausgefallen ist und mir diese IDE-Schwäche deshalb besonders auffällt. Aber stören würde mich das tatsächlich auch bei weniger Mehrfach-Interfaces.

MichaelT 8. Nov 2017 14:29

AW: Interface-Unterstützung
 
Danke für den Tip mit dem Interface. Ich habe bisher den MMX nur zur Anzeige der Methoden genommen.

Etwas off-topic aber ich bekomme das Bookmark 7 beim MMX nicht weg. Egal was ich in den Optionen einstelle. Angeblich stammt das aus 'Drop Bookmark on Start Search Position' ... Aber immer wenn ich rumpfrimmle kommt das Bookmark 7 obwohl es auf none steht in den Optionen.

Kommt das bei dir auch?

Zitat:

Zitat von Uwe Raabe (Beitrag 1380211)
Zitat:

Zitat von stahli (Beitrag 1380206)
MMX bietet aber nicht die Möglichkeit, die Klasse durch fehlende Interface-Members zu ergänzen - oder?

Das Interface per Drag-Drop oder Copy-Paste auf die implementierende Klasse ziehen.


Uwe Raabe 8. Nov 2017 15:53

AW: Interface-Unterstützung
 
Zitat:

Zitat von MichaelT (Beitrag 1385678)
Etwas off-topic aber ich bekomme das Bookmark 7 beim MMX nicht weg. Egal was ich in den Optionen einstelle. Angeblich stammt das aus 'Drop Bookmark on Start Search Position' ... Aber immer wenn ich rumpfrimmle kommt das Bookmark 7 obwohl es auf none steht in den Optionen.

Schick mir mal 'ne PM mit den einzelnen Schritten, die das Problem zeigen.

MichaelT 8. Nov 2017 17:22

AW: Interface-Unterstützung
 
Danke. Uwe.

Plag dich nicht. Beizeiten. Es erscheint einfach ein Bookmark 7 und wenn ich MMX deinstalliere kommt es nicht mehr. Seit XE ist das so, egal mit welchem MMX.

Es erscheint auch zufällig. Es erscheint dann auf jeden Fall wenn der MMX im Code rumpfrimmelt an der Stelle wo das passiert. Die Idee ist an sich ja nicht falsch. Ich muss noch rausfinden wenn es passiert.

Es ist bspw. passiert wie in der Strukuranzeige des MMX oben das Interface über die Klasse gezogen hat. Dann hat der MMX ganz korrekt die Deklarationen durchgezogen und eine Bookmark platziert nämlich Bookmark 7 (default Einstellung für Search - an der ersten Fundstelle Positionieren). Ich schaue noch zuvor ob sich das Bookmark 7 ändert wenn dieses spezifische Bookmark auf bspw. 8 umstelle. Dann melde ich mich gerne mal. Bitte keinen Aufwand treiben.

Danke nochmal für den Tip.:thumb: (* Ich bin schon sehr froh, dass überhaupt die Methoden usw... der Unit sauber strukturiert sehe*).

Allein verwende ich eher sehr übersichtliche Anzahl von Codezeilen in Units, aber nicht so exzessiv sodass ich während des Debuggens zuviel in Einzeilern herumhüpfe und ich halt die aktuellen Prozeduren eher oben und nicht unten ala FIFO Queue, denn ich arbeite eher Bottom Up.

Lieben Gruß

Zitat:

Zitat von Uwe Raabe (Beitrag 1385693)
Zitat:

Zitat von MichaelT (Beitrag 1385678)
Etwas off-topic aber ich bekomme das Bookmark 7 beim MMX nicht weg. Egal was ich in den Optionen einstelle. Angeblich stammt das aus 'Drop Bookmark on Start Search Position' ... Aber immer wenn ich rumpfrimmle kommt das Bookmark 7 obwohl es auf none steht in den Optionen.

Schick mir mal 'ne PM mit den einzelnen Schritten, die das Problem zeigen.


Uwe Raabe 9. Nov 2017 11:43

AW: Interface-Unterstützung
 
Vielleicht noch ergänzend zum MMX: Interface wizard

MichaelT 9. Nov 2017 12:10

AW: Interface-Unterstützung
 
Danke

Zitat:

Zitat von Uwe Raabe (Beitrag 1385787)
Vielleicht noch ergänzend zum MMX: Interface wizard


jaenicke 9. Nov 2017 12:20

AW: Interface-Unterstützung
 
Ja, genau diese Funktionen sind an MMX sehr interessant. :thumb:
Mehr habe ich bei Interfaces auch noch nie gebraucht.

Stevie 9. Nov 2017 13:25

AW: Interface-Unterstützung
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1385787)
Vielleicht noch ergänzend zum MMX: Interface wizard

Naja, interessant wirds, wenn du zig Klassen in verschiedenen Units und Modulen hast, die das Interface implementieren.
Muss ich dann in jede Klasse und das dort pasten, damit er ne simple Signatur updatet oder neue Methoden hinufügt?

Uwe Raabe 9. Nov 2017 13:51

AW: Interface-Unterstützung
 
Zitat:

Zitat von Stevie (Beitrag 1385796)
Naja, interessant wirds, wenn du zig Klassen in verschiedenen Units und Modulen hast, die das Interface implementieren.
Muss ich dann in jede Klasse und das dort pasten, damit er ne simple Signatur updatet oder neue Methoden hinufügt?

Ja, der Auslöser ist in diesem Fall das Paste bzw. das Drop. Man kann aber den Interface-Wizard so einstellen, daß der Dialog gar nicht mehr aufpoppt (ist eh nur informativ). Damit genügt dann wirklich das Paste für die Synchronisierung. Ich muss natürlich trotzdem jede Klasse einmal im Source selektieren und Ctrl-Alt-V drücken.

Ich könnte mir aber vorstellen, daß MMX die implementierenden Klassen zumindest im aktuellen Projekt/Projektgruppe automatisch ausfindig macht und eine Synchronisierung anbietet oder optional automatisch durchführt. Wäre zumindest einen Feature-Request wert.

stahli 11. Dez 2017 22:48

AW: Interface-Unterstützung
 
Hier nochmal ein neuer Zwischenstand.

Im ersten Text ist verkürzt eine Klasse deklariert und nach Tastendruck wird daraus das nachfolgende Ergebnis generiert.
Es geht noch nicht alles, aber die Idee dahinter sollte schon mal gut erkennbar sein.

Es werden die Methoden, Properties und privaten Felder erzeugt und auch die Methoden soweit möglich vorausgefüllt. Das natürlich nur, wenn sie neu generiert werden. Spätere händische Änderungen bleiben natürlich bei künftigen Optimierungen erhalten.

Der Implementationsteil wird analog dem Interfaceteil sortiert. Das gilt auch, wenn die Reihenfolge der Klassen oder Klassenmember im Interfaceteil nachträglich verändert wird. Bei der nächsten Optimierung werden dann die Klassen und Methoden im Implementationsteil an die neue Reihenfolge im Interfaceteil angepasst.

Derzeit habe ich die Getter und Setter mit _get_... und _set_ benannt und die privaten Felder mit "f".
Außerdem habe ich in generierten Methoden ein ? eingesetzt, damit man die Methoden mindestens einmal bearbeitet.
In Settern prüfe ich erst auf eine Werteänderung.
Das alles lässt sich natürlich ggf. auch über Optionen steuern, falls daran Bedarf wäre.


Original:

Delphi-Quellcode:
unit Unit2;

interface

uses
  System.Classes, Vcl.Graphics, System.Types, System.UITypes;

const

  aConst = 100;

type

  TClass1 = class
  private
    procedure PrivProc; virtual;
  public
    constructor Create; virtual;
    destructor Destroy; override;
  public
    procedure Execute(NewVal: String); virtual;
    function TestFunc(var Val1: Integer): Boolean;
    prop PropString: string;
    prop PropInteger: Integer rf;
    prop PropBoolean: Boolean v ws vi;
    prop PropByte: Byte s;
    prop PropWord: Word c w rf;
    prop PropString2: string c vi;
  end;

implementation

end.

Ergebnis:

Delphi-Quellcode:
unit Unit2;

interface

uses
  System.Classes, Vcl.Graphics, System.Types, System.UITypes;

const

  aConst = 100;

type

  TClass1 = class
  private
    fPropString: string;
    fPropInteger: Integer;
    fPropBoolean: Boolean;
    fPropByte: Byte;
    fPropWord: Word;
    fPropString2: string;
    procedure PrivProc; virtual;
    function _get_PropString: string;
    procedure _set_PropString(aValue: string);
    procedure _set_PropBoolean(var aValue: Boolean); virtual;
    function _get_PropByte: Byte; stdcall;
    procedure _set_PropByte(aValue: Byte); stdcall;
    function _get_PropString2: string; virtual;
    procedure _set_PropString2(const aValue: string); virtual;
  public
    constructor Create; virtual;
    destructor Destroy; override;
    procedure Execute(NewVal: String); virtual;
    function TestFunc(var Val1: Integer) Boolean
    property PropString: string read _get_PropString write _set_PropString;
    property PropInteger: Integer read fPropInteger;
    property PropBoolean: Boolean write _set_PropBoolean;
    property PropByte: Byte read _get_PropByte write _set_PropByte;
    property PropWord: Word read fPropWord;
    property PropString2: string read _get_PropString2 write _set_PropString2;
  end;

implementation

{ TClass1 }

constructor TClass1.Create;
begin

end;

destructor TClass1.Destroy;
begin

end

procedure TClass1.PrivProc;
begin
  ?;
end

function TClass1._get_PropString: string;
begin
  Result := fPropString;
end

procedure TClass1._set_PropString(aValue: string);
begin
  if (fPropString <> aValue) then
  begin
    fPropString := aValue;
  end;
end

procedure TClass1._set_PropBoolean(var aValue: Boolean);
begin
  if (fPropBoolean <> aValue) then
  begin
    fPropBoolean := aValue;
  end;
end

function TClass1._get_PropByte: Byte;
begin
  Result := fPropByte;
end

procedure TClass1._set_PropByte(aValue: Byte);
begin
  if (fPropByte <> aValue) then
  begin
    fPropByte := aValue;
  end;
end

function TClass1._get_PropString2: string;
begin
  Result := fPropString2;
end

procedure TClass1._set_PropString2(const aValue: string);
begin
  if (fPropString2 <> aValue) then
  begin
    fPropString2 := aValue;
  end;
end

procedure TClass1.Execute(NewVal: String);
begin
  ?;
end

function TClass1.TestFunc(var Val1: Integer): Boolean;
begin
  Result := ?;
end

end.

Als nächstes will ich jetzt die Optimierung von Interfaces und von Klassen, die Interfaces verwenden, umsetzen.
Dann würden entsprechende Deklarationen wie oben im Interface automatisch auf die das Interface verwendenden Klassen durchschlagen.
In der Klasse gäbe es dann Sektionen wie

Delphi-Quellcode:
private // Intf1
  fProp: Integer
protected // Intf1
  function _get_Prop: Integer;
public // Intf1
  property Prop: Integer read _get_Prop;
Spätere Änderungen im Interface würden automatisch auf die Klassen durchschlagen. Das wird (mit einer entsprechenden Anweisung) sogar für Umbenennungen von Properties und Methoden möglich sein, so dass eine InterfaceMember-Namensänderung nacheinander in mehreren Projekten nacheinander automatisiert durchgeführt werden kann (allerdings dann wohl nur bei den Klassenmembern, nicht als wirkliches Refactoring).


Wird das jetzt interessanter?

freimatz 12. Dez 2017 16:35

AW: Interface-Unterstützung
 
Für mich Nein, sorry. Ich nehm meist den MMX für so was.
Übrigens habe ich mir auch ein Tool für DTO-Datenklassen gemacht. Man schreibt ein interface (mit oder ohne Getter) und das Tool ergänzt die interfaces, erstellt die Klassen die das implementieren und dazu noch Fabrikmethoden und auf Wunsch records dazu.

jaenicke 13. Dez 2017 06:12

AW: Interface-Unterstützung
 
Zitat:

Zitat von stahli (Beitrag 1388520)
Derzeit habe ich die Getter und Setter mit _get_... und _set_ benannt und die privaten Felder mit "f".

Schöner wäre, sich an den Styleguide (und die interne Implementierung der Klassenvervollständigung von Delphi) zu halten...
Dass da immer wieder jemand sein eigenes Süppchen kocht, ist echt suboptimal.

Da das ein Tool vor allem für dich selbst ist, bist du da natürlich frei, aber so wird es dann wohl auch eher eine Lösung bleiben, die sonst nicht viele nutzen möchten. Gerade die Verwendung von Standards ist in vielen Bereichen wirklich hilfreich (und trägt zur Verbreitung einer Lösung bei)...

Was ich tatsächlich nützlich finden würde, wäre, wenn man die Property normal hinschreiben könnte ohne read und write und dann analog zur Klassenvervollständigung Getter und Setter ergänzt würden.
Wie ich das aktuell mache, hatte ich ja schon geschrieben:
http://www.delphipraxis.net/1380202-post13.html
Das geht zwar sehr schnell, auch bei mehreren Properties, aber wenn das in einem Schritt ginge, wäre das schon schön.

Mit deiner Kurzschreibweise kann ich mich leider gar nicht anfreunden. Die paar Millisekunden Zeitersparnis beim Tippen (prop vs. property) sind für mich nicht relevant, da schreibe ich es lieber richtig...
Wenn statt
Delphi-Quellcode:
prop PropString: string;
das ganze auch mit
Delphi-Quellcode:
property PropString: string;
gehen würde, wäre das schon gut. Dann könnte es eine Alternative zur Klassenvervollständigung werden.

Trotzdem geht mit MMX aktuell noch deutlich mehr.

stahli 13. Dez 2017 08:39

AW: Interface-Unterstützung
 
@freimatz

Ich hatte auch mal einen Codegenerator, der mir anhand von Datenstrukturen komplette Klassen erstellt hat. Das ist aber nicht vergleichbar mit der Änderung einer bestehenden Unit.

Kann Dein Tool so etwas auch? Ich würde es dann gerne übernehmen, wobei ich mit meinem jetzt auch schon recht weit und zufrieden bin.


@jaenicke

_get_ und _set_ verwende ich gern, weil Getter und Setter ja eher Hilfskonstrukte sind, die normalerweise nicht extern aufgerufen werden. So sind "echte Funktionen" wie GetBestFriends(1000) durch die Namensgebung besser von Gettern und Settern zu unterscheiden.
Aber wie gesagt, das ließe sich ja völlig unproblematisch über Optionen steuern.

Auch "property" auf Wunsch auszuschreiben wäre kein Problem. Die Codevervollständigung würde dann analog "prop" zuschlagen, wenn darauf kein read und kein write folgt (sonst wäre das Property ja schon mit einem read und/oder write vollständig deklariert und dürfte nicht mehr automatisch verändert werden).

Klar ist der MMX komplexer, mir aber zu umständlich. Mein Tool sehe ich einfach als Codevervollständigung 2.0 + UnitSortierer.
Meiner Arbeitsweise kommt das (wenn es fertig wird, wie erhofft) sehr viel mehr entgegen.

Wenn man in Interfaces oder im Interfaceteil von Klassen bestimmte Vorgaben trifft, ergibt sich daraus bereits exakt, was an anderen Stellen nochmal exakt so geschrieben werden muss. Und genau das nervt mich inzwischen extrem.

freimatz 14. Dez 2017 10:12

AW: Interface-Unterstützung
 
Mein Tool ist nicht unviversell brauchbar. Erstmal ist er nur für Transferobjekte da. Weiter wird formatierter Code verlangt so wie es unser Formatter macht. Dann ist das Tool ein Gebastel und mit <duck>VS/C#</duck> erstellt. Neuerdings sollte das Tool auch mit bestehenden units klar kommen.
Zum Verständnis noch ein Beispiel:
Gegeben
Delphi-Quellcode:
  IBlafaselCalculatorSourceData = interface(IBlaCalculatorSourceData)
    ['{FDFBCC49-C16F-4BC1-B6BF-7926EA37113F}']
    property ToleranceZoneGeometry: IToleranceZoneGeometryBase;
    property PreparedPoints: TPreparedPoints;
  end;
Dann wird da draus:
Delphi-Quellcode:
  IBlafaselCalculatorSourceData = interface(IBlaCalculatorSourceData)
    ['{FDFBCC49-C16F-4BC1-B6BF-7926EA37113F}']
    function GetToleranceZoneGeometry(): IToleranceZoneGeometryBase;
    function GetPreparedPoints(): TPreparedPoints;

    property ToleranceZoneGeometry: IToleranceZoneGeometryBase read GetToleranceZoneGeometry;
    property PreparedPoints: TPreparedPoints read GetPreparedPoints;
  end;
...
function CreateBlafaselCalculatorSourceData(
  ... Zeug von Vorfahre
  const p_ToleranceZoneGeometry: IToleranceZoneGeometryBase;
  const p_PreparedPoints      : TPreparedPoints): IBlafaselCalculatorSourceData;
...
  TBlafaselCalculatorSourceData = class(TBlaCalculatorSourceData,
    IBlafaselCalculatorSourceData)
  strict private
    FToleranceZoneGeometry: IToleranceZoneGeometryBase;
    FPreparedPoints      : TPreparedPoints;
    function GetToleranceZoneGeometry(): IToleranceZoneGeometryBase;
    function GetPreparedPoints(): TPreparedPoints;

  public
    constructor Create(
      ... Zeug von Vorfahre
      const p_ToleranceZoneGeometry: IToleranceZoneGeometryBase;
      const p_PreparedPoints      : TPreparedPoints);
    property ToleranceZoneGeometry: IToleranceZoneGeometryBase read GetToleranceZoneGeometry;
    property PreparedPoints: TPreparedPoints read GetPreparedPoints;
  end;
...
constructor TBlafaselCalculatorSourceData.Create(
  ... Zeug von Vorfahre
  const p_ToleranceZoneGeometry: IToleranceZoneGeometryBase;
  const p_PreparedPoints      : TPreparedPoints);
begin
  inherited Create(... Zeug von Vorfahre);
  FToleranceZoneGeometry := p_ToleranceZoneGeometry;
  FPreparedPoints := p_PreparedPoints;
end;
...
constructor TBlafaselCalculatorSourceData.Create(
  ... Zeug von Vorfahre
  const p_ToleranceZoneGeometry: IToleranceZoneGeometryBase;
  const p_PreparedPoints      : TPreparedPoints);
begin
  inherited Create(... Zeug von Vorfahre);
  FToleranceZoneGeometry := p_ToleranceZoneGeometry;
  FPreparedPoints := p_PreparedPoints;
end;
...
constructor TBlafaselCalculatorSourceData.Create(
  ... Zeug von Vorfahre
  const p_ToleranceZoneGeometry: IToleranceZoneGeometryBase;
  const p_PreparedPoints      : TPreparedPoints);
begin
  inherited Create(... Zeug von Vorfahre);
  FToleranceZoneGeometry := p_ToleranceZoneGeometry;
  FPreparedPoints := p_PreparedPoints;
end;

function TBlafaselCalculatorSourceData.GetToleranceZoneGeometry(): IToleranceZoneGeometryBase;
begin
  Result := FToleranceZoneGeometry;
end;

function TBlafaselCalculatorSourceData.GetPreparedPoints(): TPreparedPoints;
begin
  Result := FPreparedPoints;
end;
...
function CreateBlafaselCalculatorSourceData(
  ... Zeug von Vorfahre
  const p_ToleranceZoneGeometry: IToleranceZoneGeometryBase;
  const p_PreparedPoints      : TPreparedPoints): IBlafaselCalculatorSourceData;
begin
  Result := TBlafaselCalculatorSourceData.Create(... Zeug von Vorfahre, p_ToleranceZoneGeometry, p_PreparedPoints);
end;
Der Record ist hier noch nicht dabei. Auch etliche REGIONS habe ich weggelassen.

stahli 26. Jan 2018 11:08

AW: Interface-Unterstützung
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich habe jetzt noch einen neuen Ansatz realisiert.
Das Tool analysiert die zusammenhängenden Blöcke und kennzeichnet sie farblich. (Umgebaut wird die Unit noch nicht.)

Es ist doch überraschend, wie unstrukturiert die Pascal-Unit wirklich ist. Es ist gar nicht immer so eindeutig zu erkennen, wo eine Anweisung zu Ende ist.

Das Tool ist ja kein Compiler und soll gar nicht wissen, was jedes Wort bedeutet. Es muss sich daher allein an der Struktur des Textes orientieren.

"virtual;" hinter einer Prozedur-Deklaration gehört noch zu ihr.
"end;" aber nicht.
"Quatsch ;" würde mit zur Prozedur gehören (auch wenn es natürlich kein Pascal-Schlüsselwort ist, könnte aber vielleicht ja in 2 Jahren eins werden ;-) )
"Quatsch!" würde wohl irgendwie zur Klassendeklaration gehören.

Zusätzlich können überall Leerzeichen, Kommentare und Zeichenumbrüche dazwischen stehen. Manche Anweisungen müssen mit ";" abgeschlossen werden, andere nicht, weitere werden trotz ";" fortgesetzt (wie bei "virtual")


Ich bin auf einem guten Weg, denke ich, aber es war kein leichter. :-)



PS: Kennt jemand sich mit den Tool-Api´s aus im Sinne Refactoring und Code-Formatierung?

freimatz 29. Jan 2018 07:21

AW: Interface-Unterstützung
 
Zitat:

Zitat von stahli (Beitrag 1392086)
Das Tool ist ja kein Compiler und soll gar nicht wissen, was jedes Wort bedeutet. Es muss sich daher allein an der Struktur des Textes orientieren.
...
Ich bin auf einem guten Weg, denke ich, aber es war kein leichter. :-)

Auch wenn Du das nicht hören willst: Nein, du bist auf keinem guten Weg.
Ja, du machst keinen Compiler. Aber die Analyse sollte auf dem gleichen Weg passieren, also mit einem Parser. Sonst wird der Weg nie zu Ende sein. Ständig kommt dann irgendwelcher "Quatsch" daher an den du nicht gedacht hast. Pascal ist schließlich auch eine formatfreie Sprache.
Es gibt Parser. Hier in meiner Firma wird ein solcher auch verwendet um aus interfaces Mock-Objekte zu erzeugen. Auskennen tue ich mich da aber nicht, habe nur einmal was daran geändert.

jaenicke 29. Jan 2018 07:28

AW: Interface-Unterstützung
 
Zitat:

Zitat von stahli (Beitrag 1392086)
Es ist doch überraschend, wie unstrukturiert die Pascal-Unit wirklich ist. Es ist gar nicht immer so eindeutig zu erkennen, wo eine Anweisung zu Ende ist.

Wenn man (wie ich bei meinen Experimenten ein Refactoring Tool zu bauen) einen Parser wie den von Castalia nimmt, ist das kein Problem. ;-)
Denn strukturiert ist das ganze schon eindeutig, nur wenn du mal z.B. in den genannten Parser hineinschaust, siehst du auch wie viele Fälle da eigentlich behandelt werden müssen...

stahli 20. Mär 2018 09:36

AW: Interface-Unterstützung
 
Hi,

auch wenn mein Ansatz nicht so auf allgemeine Begeisterung stößt will ich mal etwas grundsätzliches fragen:

Welche Ordnung würdet Ihr innerhalb einer Interface- und Klassendeklaration bevorzugen?
Mein Tool soll ja einiges automatisieren. Jetzt stellt sich die Frage, wie es da heran gehen sollte.
Unabhängig davon, dass man natürlich (falls es doch mal Interesse gibt) auch Optionen anbieten sollte, möchte ich mal Eure Meinungen dazu anfragen.

Im Interface werden bei Properties die Getter und Setter ergänzt.
Ich würde diese jeweils unmittelbar vor den Properties einfügen in der Reihenfolge
Getter (wenn nötig), Setter (wenn nötig), Property.
Macht Ihr das anders?
Sollte vor dem Block noch eine Leerzeile zur besseren Übersichtlichkeit eingefügt werden?

Bei den Klassen habe ich verschiedene Ideen.

Class1:
Man könnte alles (klasseneigene und Interface-Member) zusammen in die normalen Sektionen (private, protected und public) schreiben.

Class2:
Oder man erzeugt eigene Sektionen (private, protected und public) pro Interface und beschriftet diese (mit einem Kommentar).

Class3:
Wie Class2 aber die Interface-Sektionen kommen alle zum Schluss.

Class4:
Alle Interface-Member kommen einfach in eine beschriftete public-Sektion.

Im letzten Beispiel habe ich ich auch mal eine eigene Sektion vorgesehen, in die alle Getter und Setter kommen könnten (entweder nur die von der Klasse selbst oder auch alle Getter und Setter, die zu den Interfaces gehören).


Zu entscheiden wäre auch, ob private Felder sowie Getter und Setter jetzt eher in protected oder private sections gehören.
Das Tool soll bestehende Ordnungen NICHT durcheinander bringen aber ich müsste entscheiden, wie es mit automatischen Ergänzungen umgehen soll.
Was sind da Eure Ideen und Meinungen?


Delphi-Quellcode:
interface

IIntf1 = interface
  procedure Proc(Param: String);
  function Func(var Param: Integer): Boolean;

  function Getter1: string;
  procedure Setter1(aValue: string);
  property Prop1: string read Getter1 write Setter1;

  function Getter2: string;
  procedure Setter2(aValue: string);
  property Prop2: string read Getter2 write Setter2;
end;

TClass1 = class(TInterfacedObject, IIntf1)
private
  fNew: String;
  fProp1: string;
  fProp2: string;
protected
  function GetterNew: string;
  procedure SetterNew(aValue: string);
  function Getter1: string;
  procedure Setter1(aValue: string);
  function Getter2: string;
  procedure Setter2(aValue: string);
public
  constructor Create; virtual;
  destructor Destroy; override;
  procedure New;
  procedure Proc(Param: String);
  function Func(var Param: Integer): Boolean;
  property New: string read GetterNew write SetterNew;
  property Prop1: string read Getter1 write Setter1;
  property Prop2: string read Getter2 write Setter2;
end;

TClass2 = class(TInterfacedObject, IIntf1)
private
  fNew: String;
private // IIntf1
  fProp1: string;
  fProp2: string;
protected
  function GetterNew: string;
  procedure SetterNew(aValue: string);
protected // IIntf1
  function Getter1: string;
  procedure Setter1(aValue: string);
  function Getter2: string;
  procedure Setter2(aValue: string);
public
  constructor Create; virtual;
  destructor Destroy; override;
  procedure New;
  property New: string read GetterNew write SetterNew;
public // IIntf1
  procedure Proc(Param: String);
  function Func(var Param: Integer): Boolean;
  property Prop1: string read Getter1 write Setter1;
  property Prop2: string read Getter2 write Setter2;
end;

TClass3 = class(TInterfacedObject, IIntf1)
private
  fNew: String;
protected
  function GetterNew: string;
  procedure SetterNew(aValue: string);
public
  constructor Create; virtual;
  destructor Destroy; override;
  procedure New;
  property New: string read GetterNew write SetterNew;
private // IIntf1
  fProp1: string;
  fProp2: string;
protected // IIntf1
  function Getter1: string;
  procedure Setter1(aValue: string);
  function Getter2: string;
  procedure Setter2(aValue: string);
public // IIntf1
  procedure Proc(Param: String);
  function Func(var Param: Integer): Boolean;
  property Prop1: string read Getter1 write Setter1;
  property Prop2: string read Getter2 write Setter2;
end;

TClass4 = class(TInterfacedObject, IIntf1)
private
  fNew: String;
protected // Getter&Setter
  function GetterNew: string;
  procedure SetterNew(aValue: string);
public
  constructor Create; virtual;
  destructor Destroy; override;
  procedure New;
  property New: string read GetterNew write SetterNew;
public // IIntf1
  fProp1: string;
  fProp2: string;
  function Getter1: string;
  procedure Setter1(aValue: string);
  function Getter2: string;
  procedure Setter2(aValue: string);
  procedure Proc(Param: String);
  function Func(var Param: Integer): Boolean;
  property Prop1: string read Getter1 write Setter1;
  property Prop2: string read Getter2 write Setter2;
end;

implementation

...

end.

Fritzew 20. Mär 2018 10:39

AW: Interface-Unterstützung
 
Also ich würde sagen alle Interface Methoden privat oder protected für Ableitungen (wenn notwendig).
Keine davon public in den implementierenden Klassen.
Die properties selber nicht in die Klassen, nur Setter und Getter.
Dadurch verhindert man das mixen von Class und Interface. Zugriff nur über das Interface.
Aber das ist natürlich nur meine Meinung, bewährt sich hier aber.

Mavarik 20. Mär 2018 10:48

AW: Interface-Unterstützung
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von stahli (Beitrag 1396748)
auch wenn mein Ansatz nicht so auf allgemeine Begeisterung stößt will ich mal etwas grundsätzliches fragen:

also....

Für das erzeugen des Interfaces habe ich ein Livetemplate...

ipropgs ipropg

Die Erzeugen mir ein Interface mit den propertys mit oder ohne setter.

Schön wäre es wenn eine automatische Sortierung passieren würde.

die propertys werden in der classe logischerweise nicht gebraucht.

Zu meinen Besonderheiten:
Source in der Anlage als Bild (Beispiel) da hier der Delphi-Formatter der DP - wahrscheinlich aus gutem Grund - MEINE Formatierung zerstört.

1.) In Propertys stehen die read und writes untereinander!
2.) Funktionen haben immer ein doppeltest Space, damit die Namen untereinander stehen.
3.) Setter haben immer den Parameter "AValue"
4.) In der Classe gibt es pro Interface ein "strict private" um zu signalisieren, dass diese Methoden aus dem Interface kommen. Wenn es mehr als ein Interface gibt steht hinter "strict private // IFoo" der Interfacename
5.) Die Variabel kommen jeweils unter eine eigen private Unterteilung - Natürlich mit großem "F" und Doppelpunkte untereinander.
6.) Immer ein AfterConstruction / BeforeDestruction da ich i.d.R. die Instance über eine Factory erzeuge und daher keine Create procedure verwende um parameter zu übergeben.

Ich habe noch viele Kleinigkeiten die mir das Sourcecode lesen erleichtern, aber das soll erstmal reichen.

Mavarik

stahli 20. Mär 2018 17:06

AW: Interface-Unterstützung
 
@Fritzew

Auf die Properties in den Klassen zu verzichten ist eine Überlegung wert.
Andererseits hat man mit den Properties auch einen kompletten Überblick über die Klassenmember innerhalb der Klassenmethoden.

Die Klassenunits verstecke ich mittlerweile regelmäßig hinter einer Factory, so dass ich auf der Projektlogik heraus ohnehin nur noch die Interfaces sehe.

Also ich werde die Properties weiter in den Klassen aufnehmen, könnte das aber optional auch ausschalten lassen.

Ist wohl eher Geschmacksache.


@Mavarik

Das Schieben von Gettern und Settern in Interfaces nach ganz oben finde ich gut. Werde ich so umsetzen.
(Im Grunde sollten die gar nicht geschrieben werden müssen und im Interface stehen. Ist ja ohnehin klar, wie die aussehen müssen.)

Die Properties selbst würde ich (wie oben beschrieben) eher mit in die Klassen übernehmen - optional abschaltbar.

Deine Einrückungen finde ich gewöhnungsbedürftig und bin noch unschlüssig, ob ich das gut finde oder nicht so gut.
Mich würde es stören, auf den Codeformatierer (von Delphi oder Third Party) verzichten zu müssen und das alles von Hand zurecht zu schieben. Wenn Du ein Property kürzer oder länger umbenennst wird das ja eine Schiebe-Orgie.

Aber ich kann mal schauen, ob ich eine solche Funktion mit unterbringen kann. Das Tool müsste halt hinter "function"-Deklarationen zwei Leerzeichen einfügen und bei gleichenartigen Zeilen untereinander bestimmte "virtuelle Tabs" benutzen.

Auch hatte ich schon mal überlegt, Code mit diesen Verkettungen (ich weiß gerade nicht wie man das nennt)
Code:
X := Y(123).
{}   Z(234);
automatisch auszurichten, was Du immer mit den geschweiften Klammern machst.

Das würde mich ja rammdösig machen... ;-)

Mavarik 20. Mär 2018 17:26

AW: Interface-Unterstützung
 
Zitat:

Zitat von stahli (Beitrag 1396808)
Mich würde es stören, auf den Codeformatierer (von Delphi oder Third Party) verzichten zu müssen und das alles von Hand zurecht zu schieben.

100% richtig... Ich habe auch noch auf meiner ToDo Liste stehen einen eigenen Formatter zu programmieren...

Hab für die Unicode umstellen schon die ein oder anderen Sourcecode Analyse geschrieben... Aber bisher fehlte mir einfach die Zeit.

stahli 20. Mai 2018 22:18

AW: Interface-Unterstützung
 
Hier mal ein aktueller Zwischenstand als Video: https://youtu.be/cfKa3wuoEd0

Der Optimizer funktioniert schon mal als erster Test innerhalb der IDE.
Eine direkte Codeformatierung (Einrückung) habe ich noch nicht drin, will das aber auch noch ergänzen.
Die anderen Features gehen für mich aber vor.

Findet das JETZT vielleicht jemand interessant?

Ich würde das später sehr gern kommerziell anbieten, wenn es Nachfrage gibt.
Für öffentliche Tests ist es noch etwas früh. Dazu muss ich noch einiges ausbauen und ausbessern.
Sofern jemand Erfahrungen mit den OTA hat und daran mitarbeiten möchte, dann gebt Bescheid...

stahli 25. Mai 2018 09:16

AW: Interface-Unterstützung
 
Weiter hier: https://www.delphipraxis.net/196493-...ml#post1402947


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:53 Uhr.
Seite 2 von 2     12   

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz