Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Design-Frage "Klassen in anderen Klassen benutzen" (https://www.delphipraxis.net/146485-design-frage-klassen-anderen-klassen-benutzen.html)

burn 20. Jan 2010 22:22


Design-Frage "Klassen in anderen Klassen benutzen"
 
Guten Abend allerseits,

hab hier mal eine Design-Frage. Kann man folgenden Code der über 3 Units geht besser gestalten,
ausser alles in einer Unit zu speichern. Da verlier ich nämlich sonst den Überblick.
Das ganze funktioniert zwar aber ich bin mir nicht sicher ob das "professionel" ist.
Ich poste hier auch nur die relevanten Teile und eine verkürzte Fassung, sprich die
Public-Variablen werden noch ersetzt. :wink:

Delphi-Quellcode:
unit UTestObj;

interface

uses
  Unit2, Unit3;

type
  TTestObj = class(TObject)
    private
      KlasseAusUnit2 : TKlasseAusUnit2;
      KlasseAusUnit3 : TKlasseAusUnit3;
     
    public
      constructor Create;
    end;

implementation

constructor TTestObj.Create;
begin
  inherited Create;
  KlasseAusUnit2 := TKlasseAusUnit2.Create;
  // KlasseAusUnit3 erstellen und KlasseAusUnit2 übergeben
  KlasseAusUnit3 := TKlasseAusUnit3.Create(KlasseAusUnit2);
  // Von KlasseAusUnit3 aus in KlasseAusUnit2 lesen und schreiben
  KlasseAusUnit3.TuWas;
  // weiter mit KlasseAusUnit2 arbeiten
  ShowMessage(KlasseAusUnit2.Blup.Wert);
end;
Delphi-Quellcode:
unit Unit2;

interface

type
  TKlasseAusUnit2 = class(TObject)
    public
      Blub : TIrgendeineKlasse;
      constructor Create;
    end;

implementation

constructor TKlasseAusUnit2.Create;
begin
  inherited Create;
  Blub := TIrgendeineKlasse.Create;
end;
Delphi-Quellcode:
unit Unit3;

interface

uses
  Unit2;

type
  TKlasseAusUnit3 = class(TObject)
    private
      UebergabeAusTestObj: TKlasseAusUnit2;
     public
       constructor Create(Test: TKlasseAusUnit2);
       procedure TuWas;
    end

implementation

constructor TKlasseAusUnit3.Create(Test: TKlasseAusUnit2);
begin
  inherited Create;
  UebergabeAusTestObj := Test;
end;

procedure TKlasseAusUnit3.TuWas;
begin
  UebergabeAusTestObj.Blub.Wert := 'Test';
end;

mfG burn

s.h.a.r.k 20. Jan 2010 22:28

Re: Design-Frage "Klassen in anderen Klassen benutzen&a
 
Ich halte das in den meisten Fällen auch so! Es ergeben sich dann zwar viele Dateien, aber es ist, wie ich finde, sehr übersichtlich.

Der einzige Unterschied ist, dass ich die Units ordentlich benenne :zwinker:

sx2008 20. Jan 2010 23:29

Re: Design-Frage "Klassen in anderen Klassen benutzen&a
 
Übrigens...
Wenn man mehrere Klassen in einer Unit hat, dann sollte man die Kommentare die von der IDE automatisch generiert werden nicht löschen.
Delphi-Quellcode:
implementation

{ TTestObj }
//^^^^^^^^^^ Kommentar in obiger Zeile nicht löschen

constructor TTestObj.Create;
begin
  inherited Create;
Diese Kommentare mit dem Klassennamen dienen der IDE als Markierung um zu erkennen, wo eine Klasse anfängt und die andere aufhört.
Lässt man sich die Methodenrümpfe mit Shift-Strg-C erzeugen, wird der Code so an die richtige Stelle einsortiert.
Wenn man ein Klasse umbenennt, dann muss man leider die Kommentarzeile von Hand anpassen (zumindest in D5).

burn 21. Jan 2010 08:17

Re: Design-Frage "Klassen in anderen Klassen benutzen&a
 
@ s.h.a.r.k
Ich benenne meine Units später auch richtig. War doch nur ein Test ob das alles funktioniert.

@ sx2008
Ich habe keine Kommentare entfernt. Wie oder wann generiert denn die IDE das automatisch.
Hab ich noch nie gesehen...

mfg burn

Stevie 21. Jan 2010 08:23

Re: Design-Frage "Klassen in anderen Klassen benutzen&a
 
Oft mach ich es der Einfachheit halber auch so.
Dennoch ist es imo für die Testbarkeit des Codes (Stichwort Unittests) oft nicht so trivial, wenn verschiedene Klassen voneinander abhängen.
In diesen Fällen ist der Ansatz der Bei Google suchenDependency Injection ein gangbarer Weg.

sx2008 21. Jan 2010 08:38

Re: Design-Frage "Klassen in anderen Klassen benutzen&a
 
Zitat:

Zitat von burn
Wie oder wann generiert denn die IDE das automatisch. Hab ich noch nie gesehen...

:shock: du kennst die Klassenvervollständigung noch nicht? Das spart viel Schreibarbeit.
Wenn du in der Deklaration einer Klasse eine neue Methode oder ein Property einfügst, dann fehlt ja noch die Implementation.
Strg-Shift-C drücken und die IDE erzeugt automatisch leere Methodenrümpfe.
In dem Zuge werden Kommentare wie { TMeineKlasse } erzeugt.

Es macht durchaus Sinn, mehrere (eng gekoppelte) Klassen in einer Unit zu halten.
Klassen, die nichts miteinander zu tun haben, kommen in getrennte Units.
Es gibt also manchmal Units in denen 3 oder mehr Klassen sind.
Und genau dann sind die automatisch generierte Kommentare der IDE hilfreich.
Früher habe ich diese Kommentare gelöscht, weil ich nicht wusste wozu sie gut sind.

angos 21. Jan 2010 09:14

Re: Design-Frage "Klassen in anderen Klassen benutzen&a
 
... und ich Volldepp hab die Funktion nach 7 Jahren immer noch nicht selber entdeckt. :lol:

Nunja, dankeschön :)!

Edit: Das ding ist schon ziemlich genial. Das macht aus dem hier:

Delphi-Quellcode:
  TTestListe = class(TObjectList)
  private

  public
    procedure Machwas(s: String; i: Integer);
    function HastDuWasGemacht: Boolean;

    property Items[ndx: Integer]: TTest;
    property Irgendwas: String;
    property NurLesen: string read GetNurLesen;
    property LesenUndSchreiben: string read GetNurLesen write FNurLesen;
    constructor Create(s: String); override;
  end;
Das hier:

Delphi-Quellcode:
  TTestListe = class(TObjectList)
  private
    FNurLesen: string;
    FIrgendwas: String;
    function GetItems(ndx: Integer): TTest;
    function GetNurLesen: string;
    procedure SetIrgendwas(const Value: String);
    procedure SetItems(ndx: Integer; const Value: TTest);

  public
    procedure Machwas(s: String; i: Integer);
    function HastDuWasGemacht: Boolean;

    property Items[ndx: Integer]: TTest read GetItems write SetItems;
    property Irgendwas: String read FIrgendwas write SetIrgendwas;
    property NurLesen: string read GetNurLesen;
    property LesenUndSchreiben: string read GetNurLesen write FNurLesen;
    constructor Create(s: String); override;
  end;

implementation

{ TTestListe }

constructor TTestListe.Create(s: String);
begin
  inherited;

end;

function TTestListe.GetItems(ndx: Integer): TTest;
begin

end;

function TTestListe.GetNurLesen: string;
begin
  Result := FNurLesen;
end;

function TTestListe.HastDuWasGemacht: Boolean;
begin

end;

procedure TTestListe.Machwas(s: String; i: Integer);
begin

end;

procedure TTestListe.SetIrgendwas(const Value: String);
begin
  FIrgendwas := Value;
end;

procedure TTestListe.SetItems(ndx: Integer; const Value: TTest);
begin

end;

end.

Na, das nenn ich doch mal feine Arbeitserleichterung. Also nochmals danke :dp:

burn 21. Jan 2010 10:28

Re: Design-Frage "Klassen in anderen Klassen benutzen&a
 
Zitat:

... und ich Volldepp hab die Funktion nach 7 Jahren immer noch nicht selber entdeckt.
DITO ... Hab das auch noch nicht gekannt ...
Aber ist doch schön wenn man immer noch was dazu lernen kann.

Zurück zum dem Thema. Also kann ich mein Design so lassen?

mfG burn

angos 21. Jan 2010 10:55

Re: Design-Frage "Klassen in anderen Klassen benutzen&a
 
Hi,

gegen das Design spricht imho nichts, da schließe ich mich der Meinung von s.h.a.r.k. an

Gruß
angos

sx2008 23. Jan 2010 05:57

Re: Design-Frage "Klassen in anderen Klassen benutzen&a
 
Zitat:

Zitat von burn
Also kann ich mein Design so lassen?

Also ich würde Klassen, die in einem direkten Zusammenhang stehen in einer Unit speichern.
Beispiel 1:
Es gibt folgende Klassen:
TMorseEncoder - verwandelt Klartext in Morsezeichen ('... --- ...').
TMorseDecoder - parst Morsezeichen und liefert Klartext zurück.
Eine weitere Klasse TMorseSoundGen nimmt die Morsezeichen entgegen und steuert dann die Soundkarte an.
Also ich würde alle drei Klassen in einer Unit platzieren.
Je eine Unit pro Klasse würde hier keinen Sinn machen, zumal TMorseEncoder und TMorseDecoder das gleiche Morsealphabet benützen.

Beispiel 2:
Es gibt eine Klasse THashMap - die Klasse hält eine Liste von Wertepaaren (Schlüssel & Inhalt) Assoziatives Array
Davon abgeleitet gibt es eine weitere Klasse, die für einen bestimmten Zweck erweitert wurde.
In diesem Fall sollten es zwei Units sein, da man die abgeleitete Klasse ja nur für eine bestimmte Anwendung erstellt hat,
während die Basisklasse auch an anderen Stellen verwendet werden kann.

Wenn die Basisklasse also allgemein verwendbar ist, während die abgeleitete Klasse projektspezifisch ist, dann sollte man
in verschiedene Units aufteilen.
Es kommt halt immer auf die Umstände an, wie man die Klassen auf die Units verteilt.

Suchwörter: Modularisierung, Kohäsion, Kopplung


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:55 Uhr.

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