Delphi-PRAXiS
Seite 3 von 6     123 45     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Code strukturieren! Wie macht man es richtig .. (https://www.delphipraxis.net/122145-code-strukturieren-wie-macht-man-es-richtig.html)

Neutral General 10. Okt 2008 23:35

Re: Code strukturieren! Wie macht man es richtig ..
 
Hi,

Ich verstehe grad leider nicht was du da tun willst :wiejetzt:

Allgemein:

Delphi-Quellcode:
property _Name_: _Datentyp_ read FVar write FVar;
Beispiel:

Delphi-Quellcode:
private
  FName: String;
public
  property Name: String read FName write FName;
end;
Vor privaten Variablen steht ein F.

oder:

Delphi-Quellcode:
property _Name_[Index: Integer]: _Datentyp_ read GetVar write SetVar;
Delphi-Quellcode:
private
  FWerte: Array of Integer;
public
  property Werte[Index: Integer]: Integer read GetWert write SetWert;
end;

implementation

function TKlasse.GetWert(Index: Integer): Integer;
begin
  Result := FWerte[Index];
end;

procedure TKlasse.SetWert(Index: Integer; const Value: Integer);
begin
  FWerte[Index] := Value;
end;
:arrow: Vor Getter/Setter-Methoden steht das Get/Set Prefix. Ohne F!

Du kannst Setter und Getter auf für Nicht-Array-Properties benutzen:

Delphi-Quellcode:
private
  FName: String;
  function GetName: String;
  procedure SetName(const Value: String);
public
  property Name: String read GetName write SetName;
end;

implementation

function TKlasse.GetName: String;
begin
  Result := FName;
end;

procedure TKlasse.SetName(const Value: String);
begin
  FName := Value;
end;
In den Getter- und Setter Methoden kannst du zudem beeinflussen, was genau zurückgegeben, (gelesen) und geschrieben wird. z.B.
Delphi-Quellcode:
function TKlasse.GetWert(Index: Integer): Integer;
begin
  if not (Index in [0..High(FWerte)]) then
    Result := -1
  else
    Result := FWerte[Index];
end;

procedure TKlasse.SetWert(Index: Integer; const Value: Integer);
begin
  if Value < 0 then
    FWerte[Index] := 0
  else
    FWerte[Index] := Value;
end;
Das hier sind jetzt nur Beispiele. Ist jetzt evtl nicht das allersinnvollste. Aber ich denke es verdeutlicht den Sinn und Zweck von Properties. Und auch deren Funktionsweise ;)

EWeiss 10. Okt 2008 23:55

Re: Code strukturieren! Wie macht man es richtig ..
 
Ich habe in meiner Funktion 2 Werte nicht einen
Beide möchte ich über properties zurücklesen geht das nicht?

Ich möchte nicht
Delphi-Quellcode:
if SkinEngine.AeroEmulate(0, 1) = 0
abfragen
sondern so wie bisher

Delphi-Quellcode:
if SkinEngine.AeroEmulate = 0
Du verstehst ?
Und das über eine property

Ich lese aus meiner Datei den wert
Delphi-Quellcode:
nMode : Integer
ein
ist RW > 0 wird dieser wert in WasMode gespeichert.
andernfalls behält WasMode den alten wert.

Delphi-Quellcode:
AeroEmulate(StrToInt(ParseThis(sBF, ',', 1)), 1);
ich kann also AeroEmulate gegenprüfen ohne den vorherigen wert zu löschen wenn RW
den wert von 0 hat.

gruss Emil

EWeiss 11. Okt 2008 00:38

Re: Code strukturieren! Wie macht man es richtig ..
 
So habs jetzt so gemacht ..
Ist aber vom Code her sogar noch mehr als über die alte Funktion.

Delphi-Quellcode:
  // SkinConfig
  TSkinConfig = class
  private
    FAeroEmulate : Integer;
    function GetAeroEmulate(FMode, FReadMode: Integer): Integer;
    procedure SetAeroEmulate(FMode, FReadMode: Integer; const Value: Integer);
  public
    property AeroEmulate[FMode, FReadMode: Integer]: Integer read GetAeroEmulate write SetAeroEmulate;
  end;
 
  function TSkinConfig.GetAeroEmulate(FMode, FReadMode: Integer): Integer;
  begin
     if FReadMode > 0 then
      FAeroEmulate := FMode;

     Result := FAeroEmulate;
  end;
 
  // aus meiner TextDatei eingelesen
  case SkinType of
    stAeroEmulate:
    begin
      AeroEmulate[StrToInt(ParseThis(sBF, ',', 1)), 1];
    end;
  end;
Delphi-Quellcode:
  // SkinEngine
  TSkinEngine = class
  private
    //
  public  
    function SK_AEROEMULATE: Integer;
  end;
 
  function TSkinEngine.SK_AEROEMULATE: Integer;
  begin
     Result := SkinConfig.AeroEmulate[0, 0];

  end;
 
  // im Code abgefragt
  if SK_AEROEMULATE > 0 then
  begin
    //
  end;
Und genau das meine ich extrem viel Code nur um eine Funktion abzufragen.

gruss Emil

Roachford 11. Okt 2008 01:17

Re: Code strukturieren! Wie macht man es richtig ..
 
Fällt dir nicht selber auf, dass du beim zweiten Aufruf der Funktion zwei sinnlose Parameter mitgeben musst, wo du doch nur einen Wert haben willst?

Und wo wir gerade mal so beim grübeln sind: kommt dir es nicht ein wenig komisch vor, dass Parameter für eine Bedingung sowie einen bedingungspezifischen Wert an eine Property gibst? Wird da nicht selbst ein wenige mulmig, wenn eine Property (ich übersetze nochmal explizit: Eigenschaft) eine Bedingung enthält, wann sie was übernimmt und die Bedingungsparameter ihr auch noch mitgegeben werden? Meinst du nicht auch, dass dieses lieber ausserhalb der Property gemacht werden sollte?

Delphi-Quellcode:
// SkinConfig
  TSkinConfig = class
  private
    fAeroEmulate : Integer;
  public
    function ReadConfig: boolean;

    property AeroEmulate: integer read fAeroEmulate write fAeroEmulate;
  end;
Delphi-Quellcode:
procedure TSkinConfig.ReadConfig;
begin
  // aus meiner TextDatei eingelesen
  case SkinType of
    stAeroEmulate:
      begin
        fAeroEmulate := StrToInt(ParseThis(sBF, ',', 1));
      end;

 ....
  end;
end;
Die Abfrage an sich ist schon hinfällig, da du fest 1 übergibst bei dem Aufruf. Und somit entscheidet allein der Case Zweig, ob die Variable zugewiesen wird oder nicht. Und da wir schon im spezifischen Case Zweig sind, ist die Abfrage sinnlos. Und da die Config eigentlich von der Klasse selbst eingelesen werden sollte, schliesslich hält sie die Config, kann sie direkt den Member setzen.

Und dein SkinEngine kann doch einfach nur die Instanz der TSkinConfig öffentlich anbieten und somit auch nutzen:

Delphi-Quellcode:
// SkinEngine
  ESkinException = class(Exception);
  ESkinConfigError = class(ESkinException);

  TSkinEngine = class
  private
    fConfig: TSkinConfig;

  public  
    constructor Create;
    destructor Destroy; override;

    property Config: TSkinConfig read fConfig; // kein write!!!
  end;
Delphi-Quellcode:
constructor TSkinEngine.Create;
begin
  inherited;

  fConfig := TSkinConfig.Create;

  if not fConfig.ReadConfig then
    raise ESkinConfigError.Create('Skin Config invalid or not available!');
end;

destructor TSkinEngine.Destroy;
begin
  fConfig.Free;

  inherited;
end;
Delphi-Quellcode:
  // im Code abgefragt
  if fConfig.AeroEmulate > 0 then
  begin
    //
  end;

EWeiss 11. Okt 2008 02:03

Re: Code strukturieren! Wie macht man es richtig ..
 
was ist da sinnlos?
Die beiden parameter sind berechtigt da es sich hier um eine nonvcl anwendung handelt.
Ich also auch innerhalb unabhängig von der Config die eigenschaften ändern kann .. muss

Delphi-Quellcode:
Result := SkinConfig.AeroEmulate[0, 0];
Result := SkinConfig.AeroEmulate[0, 0];
erste wert gibt das neue ergebnis zurück wenn der zweite auf 1 steht.
erste wert gibt das aktuelle(alte) ergebnis zurück wenn der abgefragte zweite wert = 0 ist.
Der zweite wert ist nichts anderes als ein schalter EIN oder AUS

verstehe nicht was da sinnlos ist.

Bei den anderen Punkten muss ich sagen nicht schlecht ;)
Werd das wohl in der art übernehmen..
Danke

gruss Emil

alzaimar 11. Okt 2008 09:38

Re: Code strukturieren! Wie macht man es richtig ..
 
Zitat:

Zitat von EWeiss
verstehe nicht was da sinnlos ist.

Es ist keine Eigenschaft, sondern eine Prozedur. Der Getter setzt zudem die Eigenschaft, das ist "pfui, bäh" :zwinker: . Für einen Anwender der Klasse ist es nicht ersichtlich, das beim Lesezugriff bei bestimmten Kombination der Indexe (dazu sind die Parameter eigentlich gedacht) die darunterliegenden Daten verändert werden.

Auch schon in der prozeduralen Programmierung sind Funktionen, die nicht nur etwas liefern, sondern nebenbei auch verändernd wirken (=Seiteneffekte) ein absolutes 'No Go'. Eine Funktion (und nichts anderes ist ja eine Eigenschaft, auf die lesend zugegriffen wird) liefert Daten zurück, verändert aber keinesfalls die interne Semantik!
Natürlich kann man beim erstmaligen Lesezugriff ein Flag prüfen und ggf. setzen, um z.B. redundante langsame Abfragen zu vermeiden ("Fetch on Demand"), aber der Flag ist ja nicht Bestandteil der Semantik.
Delphi-Quellcode:
Function GetProperty : TSomeType;
Begin
  If Not FLoaded Then Begin
    FProperty := ExternalAndSlowReadProperty;
    FLoaded := True;
  End;
  Result := FProperty;
End;
Das ist ok, obwohl 'FLoaded' verändert wird.

In Deinem Fall würde ich eine zweite Eigenschaft 'AlternateAeroEmulate' definieren. Der Lesezugriff auf 'AeroEmulate' besitzt dann einen Parameter 'ReadMode', der steuert, ob FAlternateAeroEmulate' oder 'AeroEmulate' geliefert wird.

EWeiss 11. Okt 2008 15:47

Re: Code strukturieren! Wie macht man es richtig ..
 
Zitat:

In Deinem Fall würde ich eine zweite Eigenschaft 'AlternateAeroEmulate' definieren. Der Lesezugriff auf 'AeroEmulate' besitzt dann einen Parameter 'ReadMode', der steuert, ob FAlternateAeroEmulate' oder 'AeroEmulate' geliefert wird.
Da darf man sich nicht wundern warum heute 10GB für ein Spiel verschwendet werden
Wenn man für eine Aktion 5 Funktionen verwendet.
Die Gesellschaft ist schwer verschwenderisch geworden scheint überall der Fall zu sein
Selbst bei bit und byte

gruss Emil

jfheins 11. Okt 2008 15:59

Re: Code strukturieren! Wie macht man es richtig ..
 
Bei den heutigen Preisen von 10 cent je Gigabyte tendiert der Tradeoff zwischen Entwicklungskosten und Produktgröße eben immermehr dahin, dass die Entwicklung vereinfacht wird, und dafür das Ausgangsprodukt voluminöser wird ;)

.net Framework <> Assembler ;)

Es komt natürlich immer auf den Einsatzzweck an, auch heute gibt es noch Anwendungen, wo es auf die Größe ankommt. Nicht jeder will schließlich ein paar Gigabyte in einen Kühlschrank einbauen. Aber in Zeiten billiger Festplatten kann man eben dadurch enorm Entwicklungszeit (= -kosten) sparen ;)

alzaimar 11. Okt 2008 16:19

Re: Code strukturieren! Wie macht man es richtig ..
 
Zitat:

Zitat von EWeiss
Da darf man sich nicht wundern warum heute 10GB für ein Spiel verschwendet werden
Wenn man für eine Aktion 5 Funktionen verwendet.

Zwei Emil, nur zwei. :zwinker:
Zitat:

Zitat von EWeiss
Die Gesellschaft ist schwer verschwenderisch geworden scheint überall der Fall zu sein..Selbst bei bit und byte

Es geht doch nicht um möglichst kompakten Code, sondern um klare Strukturen, gute Verständlichkeit, Robustheit und Erweiterbarkeit. Du entwickelst doch heute Anwendungen in einer Komplexität, die man sich vor 10/20 Jahren gar nicht vorstellen konnte. Um die Komplexität einigermaßen in den Griff zu bekommen, wurde OOP irgendwann als Heilsbringer angesehen. Immerhin bringt die Objektmetapher Ordnung in das(den? die?) Codewirrwarr. Das man dabei im Endeffekt 5-10x so viel Maschinencode produziert, muss man einfach in Kauf nehmen. Und ich spreche hier nicht von dazugelinkten Libraries, sondern einfach vom Overhead, den gut programmiertes OOP nun mal verursacht.

Ich schreibe lieber eine Zeile mehr, wenn es dem Verständnis dient. Beim Codieren geht es doch nicht darum, mit möglichst wenig Zeilen zum Ziel zu kommen, sondern eher darum, eine Problemlösung mit formalen Mitteln (=Programmiersprache, OOP) allgemeinverständlich zu formulieren.

Ein schönes und sonniges Wochenende!

EWeiss 11. Okt 2008 19:39

Re: Code strukturieren! Wie macht man es richtig ..
 
Zitat:

Zwei Emil, nur zwei.
Also wenn du dir diesen link anschaust
http://www.delphipraxis.net/internal...=951802#951802

Dann habe ich jetzt schon bei weiten mehr an Code als über eine einfache Funktion
Gut muss aber sagen so bin ich auf der sicheren seite.

Addiere ich nun dein BEispiel hinzu sind es nicht nur zwei sondern
für jede abrage der Config * x
Das füllt ebend mal so die Seite locker mit mehr als 200 Zeilen.

Ich frage mich ob man dann noch eine übersicht behält.

Nur in der SkinConfig Unit habe ich jetzt schon 950 Zeilen.
In der uSkin schon 2440

gruss Emil


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:29 Uhr.
Seite 3 von 6     123 45     Letzte »    

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