Gebrauch von With

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut

Gebrauch von With

Beitragvon Warf » 24. Mai 2018, 20:21 Gebrauch von With

Marc hat geschrieben:Hallo Theo

Vielen Dank für die schnelle Hilfe!

Ich hab es jetzt so gemacht :
Code: Alles auswählen
 Form2 := TForm2.CREATE(Application);
 Form2.ShowModal;
 FreeAndNil(Form2);

Das scheint zu funktionieren.


Man braucht nicht mal ne Variable:
Code: Alles auswählen
With TForm2.Create(nil) do // Owner nicht benötigt wenn man selbst freed
try
  ShowModal();
finally
  Free;
end;
Warf
 
Beiträge: 838
Registriert: 23. Sep 2014, 16:46
Wohnort: Aachen
OS, Lazarus, FPC: Mac OSX 10.11 | Win 10 | FPC 3.0.0 | L trunk | 
CPU-Target: x86_64, i368, ARM
Nach oben

Beitragvon theo » 25. Mai 2018, 08:11 Re: Form schliessen und wieder öffnen

Warf hat geschrieben:Man braucht nicht mal ne Variable:

Den Gebrauch von "with" sollte man nun wirklich nicht noch fördern... :roll:
theo
 
Beiträge: 8046
Registriert: 11. Sep 2006, 18:01

Beitragvon Warf » 25. Mai 2018, 12:21 Re: Form schliessen und wieder öffnen

theo hat geschrieben:
Warf hat geschrieben:Man braucht nicht mal ne Variable:

Den Gebrauch von "with" sollte man nun wirklich nicht noch fördern... :roll:


Naja, kommt drauf an. Wenn man z.B. ein sehr langes prefix hat dann lohnt es sich auf jeden fall:
Code: Alles auswählen
Form2.Image1.Bitmap.Canvas.MoveTo(0,0);
Form2.Image1.Bitmap.Canvas.LineTo(Form2.Image1.Bitmap.Width,Form2.Image1.Bitmap.Height);
// vs
With Form2.Image1.Bitmap do
begin
  Canvas.MoveTo(0,0);
  Canvas.LineTo(Width, Height);
end;


Ich persönlich verwende es auch immer wenn ich ein Objekt für wenige Operationen brauche, z.B. eine Textdatei in einen stream laden:
Code: Alles auswählen
With TStringList.Create do
try
  LoadFromFile(FName);
  SaveToStream(Stream);
finally
  Free;
end;


Weder LoadFromFile noch SaveToStream sind in irgendeiner form mehrdeutig im Kontext einer Formsklasse, daher spricht absolut nichts dagegen.

Man muss sich nur an ein paar Spielregeln halten:
1. Keine geschachtelten With
2. Auf Methoden und Felder des Objektes innerhalb von with immer mit Self zugreifen
3. Mehrdeutige bezeichnet mit unitname.Bezeichner aufrufen (z.B. wenn man eine property Pos hat dann würde man System.Pos für die Funktion verwenden).

Und wenn man nicht in einem Objekt ist spricht sogar absolut nichts gegen with.

Wovon ich nichts halte sind größere With blöcke, mehr als 5-10 Zeilen würde ich auch nicht in einen With block hauen
Warf
 
Beiträge: 838
Registriert: 23. Sep 2014, 16:46
Wohnort: Aachen
OS, Lazarus, FPC: Mac OSX 10.11 | Win 10 | FPC 3.0.0 | L trunk | 
CPU-Target: x86_64, i368, ARM
Nach oben

Beitragvon theo » 25. Mai 2018, 12:39 Re: Form schliessen und wieder öffnen

Es kann jeder programmieren wie er will, aber empfehlen würde ich es einem Einsteiger nie.
Das erste was ich beim Debuggen von fremdem Code mache, ist alle "with" rausschmeißen. :wink:
theo
 
Beiträge: 8046
Registriert: 11. Sep 2006, 18:01

Beitragvon Warf » 25. Mai 2018, 12:43 Re: Form schliessen und wieder öffnen

theo hat geschrieben:Es kann jeder programmieren wie er will, aber empfehlen würde ich es einem Einsteiger nie.
Das erste was ich beim Debuggen von fremdem Code mache, ist alle "with" rausschmeißen. :wink:


Ist halt ein typischer Fall von "Code der einfacher zu schreiben als zu lesen ist"
Warf
 
Beiträge: 838
Registriert: 23. Sep 2014, 16:46
Wohnort: Aachen
OS, Lazarus, FPC: Mac OSX 10.11 | Win 10 | FPC 3.0.0 | L trunk | 
CPU-Target: x86_64, i368, ARM
Nach oben

Beitragvon pluto » 25. Mai 2018, 13:29 Re: Form schliessen und wieder öffnen

Ist halt ein typischer Fall von "Code der einfacher zu schreiben als zu lesen ist"

Ich finde eine Variable zu nutzen, als einfacher und übersichtlicher...
Häuft verwende ich Variablen um Zugriffe(Damit meine ich unter anderem Umwandlungen) zu "Sparen"....
MFG
Michael Springwald
Aktuelles Projekt: PlutoArduino
pluto
 
Beiträge: 6534
Registriert: 19. Nov 2006, 12:06
Wohnort: Oldenburg/Oldenburg
OS, Lazarus, FPC: Linux Mint 18.1 | 
CPU-Target: AMD
Nach oben

Beitragvon wp_xyz » 25. Mai 2018, 13:34 Re: Form schliessen und wieder öffnen

Warf hat geschrieben:
Code: Alles auswählen
Form2.Image1.Bitmap.Canvas.MoveTo(0,0);
Form2.Image1.Bitmap.Canvas.LineTo(Form2.Image1.Bitmap.Width,Form2.Image1.Bitmap.Height);
// vs
With Form2.Image1.Bitmap do
begin
  Canvas.MoveTo(0,0);
  Canvas.LineTo(Width, Height);
end;


Abweichend vom Thema - aber ich kann das einfach nicht mehr sehen: Ich nehme mal an, dass es hier um eine Methode von TForm2 geht. Dann hast du hier die Todsünde begangen, in der Implementierung der Methode die Instanz-Variable zu verwenden. Als Folge wird dein Code nur funktionieren, wenn die Instanz von TForm2 Form2 heißt und nicht anders. Das ist derselbe Unsinn, wie wenn man gezwungen wäre jeden Integer "i" zu nennen.

Je öfter solcher Unsinn in Foren auftaucht, um so öfter wird er angewendet.
wp_xyz
 
Beiträge: 2531
Registriert: 8. Apr 2011, 08:01

Beitragvon Warf » 25. Mai 2018, 14:52 Re: Form schliessen und wieder öffnen

wp_xyz hat geschrieben:
Warf hat geschrieben:
Code: Alles auswählen
Form2.Image1.Bitmap.Canvas.MoveTo(0,0);
Form2.Image1.Bitmap.Canvas.LineTo(Form2.Image1.Bitmap.Width,Form2.Image1.Bitmap.Height);
// vs
With Form2.Image1.Bitmap do
begin
  Canvas.MoveTo(0,0);
  Canvas.LineTo(Width, Height);
end;


Ich nehme mal an, dass es hier um eine Methode von TForm2 geht. Dann hast du hier die Todsünde begangen, in der Implementierung der Methode die Instanz-Variable zu verwenden. Als Folge wird dein Code nur funktionieren, wenn die Instanz von TForm2 Form2 heißt und nicht anders. Das ist derselbe Unsinn, wie wenn man gezwungen wäre jeden Integer "i" zu nennen.

Als nächstes zurück zum Thema: theo hat recht, denn das ist auch ein schönes Beispiel für die Probleme mit with. So wie es da steht, sind Width und Height die entsprechenden Eigenschaften des Bitmap. Aber was ist wenn du eigentlich die Eigenschaften des Formular gemeint hast und vergessen hast, "self" (oder - wieder Todsünde - "Form2") voranzustellen? Du bekommst keine Fehlermeldung, und du wirst, wenn dir dein Kunde nach 6 Monaten Darstellugsprobleme gemeldet hat und du alle Details vergessen hast, mit stundenlanger Fehlersuche bestraft.

Das Beispiel hab ich mir einfach ausgedacht und es stammt nicht aus echtem code. Aber lange Präfixe gibt es auch in vielen anderen situation.

Sehr gut eignet sich With z.B. für Listview ähnliche Datenstrukturen:
Code: Alles auswählen
With ListView1.Items.Add do
begin
  Caption := 'CAP';
  SubItems.Add('S2');
  SubItems.Add('S3');
  Tag = Sender;
end;


Wegen der Mehrdeutigkeit, dafür hab ich mir angewöhnt immer self zu verwenden im with. Ansonsten könnte man genauso argumentieren, warum verwendet man Klassen statt Objects / Advanced Records, bei Klassen können Access violations auftreten wenn die Klasse gefreed wurde oder von Anfang an ein Nullpointer war. Einen Fehler zu finden aufgrund eines vorzeitigen Free's kann deutlich schlimmer werden als ein Falscher bezeichner, denn im Worst case wurde der Speicher noch nicht überschrieben und die Klasse verhält sich wie gewohnt, aber irgendwann nach dem Alloziieren einer neuen Klasse ist plötzlich der gesamte Speicher überschrieben, und das Wohlgemerkt ohne einen einzigen Fehler. Z.B.:
Code: Alles auswählen
program Test;
{$Mode ObjFPC}{$H+}
 
type
  TTestClass = class
  private
    FName: String;
  public
    property Name: String read FName write FName;
  end;
 
var foo, bar: TTestClass;
begin
  foo:= TTestClass.Create;
  foo.free;
  foo.Name := 'abc';
  WriteLn(foo.name);
  bar := TTestClass.Create;
  WriteLn(foo.name);
  bar.Free;
end.

Dieser code sollte bei einem x86-64 system mit FPC memory manager zu erst abc danach den leeren string outputen ohne irgendeine Fehlermeldung. Das ist allerdings dennoch kein Grund aufzuhören Klassen zu verwenden, denn Klassen sind super komfortabel (im Gegensatz zu Objects) und da nehme ich das gerne In kauf. Und genauso sehe ich es mit With. Es können echt widerliche Fehler passieren, ist aber relativ leicht unter Kontrolle zu bekommen (und die Fehler durch with sind generell nicht so schwerwiegend, da ein falscher wert im Debugger recht schnell gefunden werden kann)
Warf
 
Beiträge: 838
Registriert: 23. Sep 2014, 16:46
Wohnort: Aachen
OS, Lazarus, FPC: Mac OSX 10.11 | Win 10 | FPC 3.0.0 | L trunk | 
CPU-Target: x86_64, i368, ARM
Nach oben

Beitragvon Mathias » 25. Mai 2018, 18:16 Re: Form schliessen und wieder öffnen

Ich verwende auch sehr gerne with, man kann damit auch sehr schön Blöcke abtrennen.
Code: Alles auswählen
  // Shader des Quadrates
  with Quad_Shader do begin
    Shader := TShader.Create([FileToStr('quad.vert'), FileToStr('quad.frag')]);
    with Shader do begin
      UseProgram;
 
      WorldMatrix_id := UniformLocation('Matrix');
    end;
  end;
 
  // Shader des Würfels.
  with Cube_Shader do begin
    Shader := TShader.Create([FileToStr('cube.vert'), FileToStr('cube.frag')]);
    with Shader do begin
      UseProgram;
      glUniform1i(UniformLocation('Sampler0'), 0);
 
      WorldMatrix_id := UniformLocation('Matrix');
    end;
  end;

Aber schlussendlich ist es Geschmackssache.
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 3987
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon theo » 26. Mai 2018, 09:02 Re: Form schliessen und wieder öffnen

Mathias hat geschrieben:Ich verwende auch sehr gerne with, man kann damit auch sehr schön Blöcke abtrennen.
Code: Alles auswählen
  // Shader des Quadrates
  with Quad_Shader do begin
    Shader := TShader.Create([FileToStr('quad.vert'), FileToStr('quad.frag')]);
    with Shader do begin
      UseProgram;
 
      WorldMatrix_id := UniformLocation('Matrix');
    end;
  end;
 
  // Shader des Würfels.
  with Cube_Shader do begin
    Shader := TShader.Create([FileToStr('cube.vert'), FileToStr('cube.frag')]);
    with Shader do begin
      UseProgram;
      glUniform1i(UniformLocation('Sampler0'), 0);
 
      WorldMatrix_id := UniformLocation('Matrix');
    end;
  end;



Grauenhaft. :shock:
Ich habe schon viele Bugs gefunden, welche nur durch diese "praktische" Schreibweise entstanden sind.
Bei Verwendung von Code Completion hat das doch auch kaum einen Vorteil.
theo
 
Beiträge: 8046
Registriert: 11. Sep 2006, 18:01

Beitragvon m.fuchs » 26. Mai 2018, 09:10 Re: Gebrauch von With

Moderationshinweis: Ich habe mir mal erlaubt, die Diskussionen zu with aus dem ursprünglichen Thema in ein neues zu verschieben.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de
m.fuchs
 
Beiträge: 1946
Registriert: 22. Sep 2006, 18:32
Wohnort: Berlin
OS, Lazarus, FPC: Winux (L 1.8.4, FPC 3.0.4) | 
CPU-Target: x86, x64, arm
Nach oben

Beitragvon m.fuchs » 26. Mai 2018, 09:21 Re: Form schliessen und wieder öffnen

Warf hat geschrieben:Ist halt ein typischer Fall von "Code der einfacher zu schreiben als zu lesen ist"

Code der einfacher zu schreiben als zu lesen ist, ist grundsätzlich kein guter Code.

Mathias hat geschrieben:Ich verwende auch sehr gerne with, man kann damit auch sehr schön Blöcke abtrennen.

Wenn du Blöcke abtrennen möchtest, dann verwende doch einfach mal Methoden.

Code: Alles auswählen
 
procedure InitQuadShader(QuadShader: TWasWeissIch);
begin
  QuadShader.Shader := TShader.Create([FileToStr('quad.vert'), FileToStr('quad.frag')]);
  QuadShader.Shader.UseProgram;
  QuadShader.Shader.WorldMatrix_id := UniformLocation('Matrix');
end;
 
procedure InitCubeShader(CubeShader: TWasWeissIch);
begin
  CubeShader.Shader := TShader.Create([FileToStr('cube.vert'), FileToStr('cube.frag')]);
  CubeShader.Shader.UseProgram;
  CubeShader.Shader.glUniform1i(UniformLocation('Sampler0'), 0);
  CubeShader.Shader.WorldMatrix_id := UniformLocation('Matrix');
end
 
 
(* ... *)
 
InitQuadShader(Quad_Shader);
InitCubeShader(Cube_Shader);


Aber ich finde es gut, dass die Diskussion aufgekommen ist. So konnte ich gleich mal meine Code-Quality-Checks um ein Verbot von with...do erweitern. :mrgreen:
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de
m.fuchs
 
Beiträge: 1946
Registriert: 22. Sep 2006, 18:32
Wohnort: Berlin
OS, Lazarus, FPC: Winux (L 1.8.4, FPC 3.0.4) | 
CPU-Target: x86, x64, arm
Nach oben

Beitragvon mse » 26. Mai 2018, 09:24 Re: Gebrauch von With

Warum Free Pascal immer noch keine sichere "with" Version anbietet ist mir schleierhaft.
Sonst wird ja kritiklos jeder Mist von allen möglichen anderen Programmiersprachen übernommen um aus Free Pascal ein aufgeblähtes Monster zu machen.
Nur ein sicheres "with", wo eine Ergänzung wirklich sinnvoll wäre, wird seit über zehn Jahren ergebnislos diskutiert.
mse
 
Beiträge: 1933
Registriert: 16. Okt 2008, 09:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0) | 
CPU-Target: x86,x64,ARM
Nach oben

Beitragvon m.fuchs » 26. Mai 2018, 09:37 Re: Gebrauch von With

Ja, da ist das in Visual Basic.NET wirklich sauberer gelöst.

Code: Alles auswählen
With result
  .AutoRenew = True
  .CancelPeriod = tld.CancellationPeriodInDays
  .Contact0 = Model.Core.DaoHelper.GetContactByHandle(context, bulktask.GetPropertyValue("owner"))
  .Contact1 = Model.Core.DaoHelper.GetContactByHandle(context, bulktask.GetPropertyValue("admin"))
  .DateModified = DateTime.Now
  .NameACE = nameACE
  .NameIDN = nameIDN
  .UpdateRequired = True
End With


Andererseits ist der Gebrauch von with häufig ein Zeichen dafür, dass eine Methode zu viel kann.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de
m.fuchs
 
Beiträge: 1946
Registriert: 22. Sep 2006, 18:32
Wohnort: Berlin
OS, Lazarus, FPC: Winux (L 1.8.4, FPC 3.0.4) | 
CPU-Target: x86, x64, arm
Nach oben

Beitragvon siro » 26. Mai 2018, 14:03 Re: Gebrauch von With

Ich liebe das "with"..... und vermisse es sehr in "C"
egal ob der "." oder "->" das macht die Software oftmals unnötig unleserlich.
Aber man muss natürlich aufpassen, dass man tatsächlich mit den richtigen Objekten/Records hantiert.
Im Prinzp ist das ja nur ein "versteckter" Pointer auf ein Object oder einen Record.
Hab sogar schon "with" mit 2 Paramtern benutzt. Bei 2 gleichen Objekten geht das aber eventuell in die Hose...
Grad mal probiert:
Code: Alles auswählen
 
with Button1,Button2 do begin
  caption:='Hallo';    // Button2 wird adressiert
end;
 
with Button2,Button1 do begin
  caption:='Hallo';    // Button1 wird adressiert
end;
 
with Button3,Button1,Button2 do begin
  caption:='Hallo';   // Button2 wird adressiert
end;                                   


hier wird anscheinend immer der zuletzt aufgeführte Parameter benutzt.

Siro
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...
siro
 
Beiträge: 292
Registriert: 23. Aug 2016, 13:25
Wohnort: Berlin
OS, Lazarus, FPC: Windows 7 Windows 8.1 Windows 10 | 
CPU-Target: 64Bit
Nach oben

» Weitere Beiträge siehe nächste Seite »
Nächste

Zurück zu Freepascal



Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 2 Gäste

porpoises-institution
accuracy-worried