Einzelnen Beitrag anzeigen

mytbo

Registriert seit: 8. Jan 2007
461 Beiträge
 
#1

Die Arbeit mit Fake-Objekten erspart die Prüfung auf Nil

  Alt 23. Jun 2023, 23:56
Zugegeben, die Überschrift ist etwas zugespitzt formuliert, es soll zur Diskussion anregen. Starten wir mit Bekanntem. Gegeben ist die Situation: Arbeit mit einem Geschäftsobjekt (Business Object).

1) Die Definition sieht wie folgt aus:
Delphi-Quellcode:
type
  TPerson = class(TObject)
  private
    FID: TID;
    FVorname: String;
    FNachname: String;
    function GetCaption: String;
  public
    constructor Create(pmID: TID); reintroduce;
    property Caption: String // Format: Nachname, Vorname
      read GetCaption;
    property ID: TID
      read FID;
    property Vorname: String
      read FVorname write FVorname;
    property Nachname: String
      read FNachname write FNachname;
  end;

type
  TdmDaten = class(TDataModule)
  public
    function GetPerson(pmPersonID: TID): TPerson;
  end;

function TdmDaten.GetPerson(pmPersonID: TID): TPerson;
begin
  if IsValidID(pmPersonID) then
    Result := FPersonList.Find(pmPersonID)
  else
    Result := Nil;
end;
Angewendet wie folgt:
Delphi-Quellcode:
var person: TPerson := dmDaten.GetPerson(idPerson);
if person <> Nil
  name := person.Caption
else
  name := 'John Doe';
2) In der nächsten Überarbeitung erweitern wir das Datenmodul:
Delphi-Quellcode:
type
  TdmDaten = class(TDataModule)
  public
    ...
    function GetPersonCaption(pmPersonID: TID): String;
  end;

function TdmDaten.GetPersonCaption(pmPersonID: TID): String;
begin
  var person: TPerson := GetPerson(pmID);
  if person <> Nil then
    Result := person.Caption
  else
    Result := 'John Doe';
end;
Jetzt ist es deutlich komfortabler in der Anwendung: name := dmDaten.GetPersonCaption(idPerson); In der realen Welt kann ein Geschäftsobjekt viele Eigenschaften haben. Nicht alle kann/will man über einen Direktzugriff zugänglich machen. Damit wären wir wieder am Anfang und beim ersten Beispiel.

3) Was wäre, wenn es immer ein Objekt gibt. Wenn kein reales vorhanden ist, dann auf Wunsch ein Fake-Objekt. Es könnte wie folgt aussehen:
Delphi-Quellcode:
type
  TPerson = class(TObject)
  public
    function IsFake: Boolean;
    ...
  end;

  TdmDaten = class(TDataModule)
  public
    function GetPerson(pmPersonID: TID; pmFakeReturn: Boolean = False): TPerson;
    ...
  end;

function TPerson.IsFake: Boolean;
begin
  Result := (Self = __FakePerson);
end;

function TdmDaten.GetPerson(pmPersonID: TID; pmFakeReturn: Boolean): TPerson;
begin
  Result := Nil;
  if IsValidID(pmPersonID) then
    Result := FPersonList.Find(pmPersonID);

  if (Result = Nil) and pmFakeReturn then
    Result := __FakePerson;
end;

initialization
  __FakePerson := TPerson.Create(0);
  __FakePerson.Vorname := 'John';
  __FakePerson.Nachname := 'Doe';

finalization
  __FakePerson.Free;
Der Zugriff wie folgt: name := dmDaten.GetPerson(idPerson, True).Caption; Diese Schreibweise sieht elegant aus, beinhaltet aber auch Gefahren. Allerdings nichts, was bei disziplinierter Programmierung ein Problem sein sollte. Zur Zeit arbeite ich mit Fall 1), 2) und anderen Techniken. Gebe aber zu, der Ansatz mit dem Fake-Objekt hat einen gewissen Charme und schwirrt im Kopf herum. Im Anhang der Sourcecode zum Spielen.

Nachtrag: Die Bezeichnung Fake-Objekt scheint zu unpräzise. Dahinter kann sich auch ein Default-Objekt verbergen.
Delphi-Quellcode:
type
  TDefaultPerson = class(TPerson)
  protected
    function GetCaption: String; override;
  end;

function TDefaultPerson.GetCaption: String;
begin
  if DayOfWeek(Date) = 2 then // I don't like monday
    Result := Format('%s, %s', ['Lecter', 'Hannibal'])
  else
    Result := inherited GetCaption;
end;
Ich habe das Beispiel angepasst.

Bis bald...
Thomas
Angehängte Dateien
Dateityp: zip TestFakeObjektSource.zip (2,8 KB, 0x aufgerufen)

Geändert von mytbo (24. Jun 2023 um 16:30 Uhr) Grund: Beispiel Quelltext überarbeitet
  Mit Zitat antworten Zitat