AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

OOP wirklich nicht möglich?

Ein Thema von Delbor · begonnen am 12. Okt 2017 · letzter Beitrag vom 20. Okt 2017
Antwort Antwort
Delbor

Registriert seit: 8. Okt 2006
Ort: St.Gallen/Schweiz
1.196 Beiträge
 
Delphi 11 Alexandria
 
#1

AW: OOP wirklich nicht möglich?

  Alt 19. Okt 2017, 15:14
Hi zusammen

TQueryResultClass arbeitet schon länger zur vollkomenen Zufriedenheit - das Problem, das ich mit dem Threadtitel angesprochen habe, war: Gäbe es eine OOP-Lösung, um TQueryResultClass zu ändern? Änderungsziel: Gleiches Funktionieren, wie ursprünglich implementiert, aber mit andern Bezeichnern. Aber erstmal, was TQueryResultClass tut (und mehr hat diese Klasse auch nicht zu tun):
Delphi-Quellcode:
procedure TFDMySQLDml.SelectBildDaten(FCategoryKey : Integer);
  var SQLString: String; Kath_Id : integer;
begin
  Kath_Id := FCategoryKey;
  SQLString := DefineBildSQL3(Kath_Id); // Liefert den SQL-String zurück
  FDQueryMain.Connection := Self.FDConnectionMySql;
  FDQueryMain.Close;
  FDQueryMain.SQL.Text := SQLString;
  FDQueryMain.Params.CreateParam(ftInteger, 'Kath_Id', ptOutput);
  FDQueryMain.Params[0].AsInteger := Kath_Id;
  FDQueryMain.Open;
  FDQueryMain.First;
  While (Not FDQueryMain.Eof) do
  begin
    FQueryResult := TQueryResultClass.Create(Self);
    FQueryResult.IdBild := (FDQueryMain.FieldByName('BildId').AsInteger);
    [QUOTE]FQueryResult.BildDescribeTabelle.BilddesribeID := FDQueryMain.FieldByName('BildDescribeId').AsInteger;[/QUOTE]
    FQueryResult.BildDescribeTabelle.bildkatID := FDQueryMain.FieldByName('bildkatID').AsInteger;
    FQueryResult.BildDescribeTabelle.BildName := FDQueryMain.FieldByName('BildName').AsString;
    FQueryResult.BildDescribeTabelle.BildBeschreibung := FDQueryMain.FieldByName('Bildbeschreibung').AsString;
    FQueryResult.BildDescribeTabelle.BildLegende := FDQueryMain.FieldByName('Bildlegende').AsString;
    FQueryResult.KategoryTabelle.Kategory := FDQueryMain.FieldByName('Kategorie').AsString;
    FDQueryMain.Next;
    FCategoryBildlist.Add(FQueryResult); // Die Records in TQueryResultClass müssen überprüft werden.
  end;
  FDQueryMain.Close;
end;
Wie ersichtlich ist: Weder das Query noch TQueryResultClass verfügen in dieser Abfrage über einen Stream für Blobdaten. Interesieren tun hier nur gerade mal die Begleitdaten zum Bild.
Das besondere, weswegen es TQueryResultClass überhaupt gibt, sind seine Bilder-Propertis:
Delphi-Quellcode:
    property Thumbnail: TMemoryStream read GetThumbnail write SetThumbnail;
    property Bitmap: TMemoryStream read GetBitmap write SetBitmap;
Die beiden Getter, aam Beispiel von GetThumbnail:
Delphi-Quellcode:
function TQueryResultClass.GetThumbnail: TMemoryStream;
  var AUser, APass : String;
begin
  if not Assigned(FThumbnail) then
  begin
    FThumbnail := TMemorystream.Create;
    Result := FillThumbnail(FThumbnail);
  end else
    Result := FThumbnail;
end;
Die Funktion Fillthumbnail:
Delphi-Quellcode:
function TQueryResultClass.FillThumbnail(var Thumbnail: TMemoryStream):TMemoryStream;
var
  BildID: Integer;
  BlobStream: TStream;
  LNull: string;
  SQLString: string;
begin
    BildID := Self.FidBild;
    SQLString := 'SELECT Bildtabelle.Thumbnail as Thumbnail FROM Bildtabelle WHERE Bildtabelle.idBild = :BildID';
    FDMySQLDml.FDQueryMain.SQL.Text := SQLString;
    FDMySQLDml.FDQueryMain.Params.CreateParam(ftInteger, 'BildID', ptInput);
    FDMySQLDml.FDQueryMain.Params[0].AsInteger := BildID;
    FDMySQLDml.FDQueryMain.Open;
    FDMySQLDml.FDQueryMain.First;
    while not FDMySQLDml.FDQueryMain.Eof do
    begin
      if not FDMySQLDml.FDQueryMain.FieldByName('Thumbnail').IsNull then
      begin
        BlobStream := FDMySQLDml.FDQueryMain.CreateBlobStream(FDMySQLDml.FDQueryMain.FieldByName('Thumbnail'), bmread);
        BlobStream.Position := 0;
        FThumbnail.CopyFrom(BlobStream, Blobstream.Size);
        BlobStream.Free;
        FDMySQLDml.FDQueryMain.Next;
        Result:= FThumbnail;
      end
      else
      begin
        LNull := 'Kein Thumbnail vorhanden';
        FThumbnail.WriteBuffer(LNull, SizeOf(LNull));
      end;
    end;
    FDMySQLDml.FDQueryMain.Close;
end;
Das ist das, was geschieht, wenn zur Darstellung der Datensätze auch auf die Bildpropertys von TQueryResultClass zugegriffen wird.

Und nochmal zur Übereinstimmung von Klassen-/Feld und Tabellen/Feldnamen: Der Klasse tuts nicht weh, wenn ihre Felder gleich heissen, wie diejenigen der Tabelle, und zu Fehlfunktionen kann es auch nicht kommen. Aber was liest sich besser:
Delphi-Quellcode:
FQueryResult.BildDescribeTabelle.bildkatID := FDQueryMain.FieldByName('bildkatID').AsInteger;
// oder
FQueryResult.Id := FDQueryMain.FieldByName('bildkatID').AsInteger;
Von den drei beteiligten Tabellen hat jede eine Id als Primärschlüssel und eine als Fremdschlüssel,und alle sind sie wichtig. Bei übereinstimmenden Namen kannst du in der Zuweisung nicht irren, bei grundsätzlich verschiedenen Namen hingegen schon.

Zitat von DeddyH:
Zitat:
Je mehr ich lese, desto mehr frage ich mich: wozu das Ganze? Soll das ein ORM werden/sein? Dann haben IMO die Tabellen- bzw. Feldnamen in den Objekten nichts zu suchen, die Objekte sollte es nicht interessieren, woher die Daten kommen oder wohin sie gehen, dafür ist eine Schicht zuständig. So wie ich es sehe bringt der ganze Aufwand momentan 0% Nutzen (sofern ich das richtig überblicke, ich kann mich auch irren), sondern sorgt eher für Verwirrung.
Gewissermassen ja. Das ganze, insbesondere der Teil mit dem Nachladen der Bilddaten, ist unter anderem mit deiner tatkräftigen Mithilfe (auf Delphi Treff) entstanden. Dein Kommentar damals: "Ein Mini-Orm".
Ein ORM bildet ja eine komplette Datenbank mit Hilfe von zB. Delphi-Objekten ab. Aber eben eine komplette Datenbank. Meine Klasse gestattet das Nachladen der Bilddaten bei Bedarf und das Iterieren durch die Ergebnismenge bei geschlossenem Query oder sogar geschlossener Verbindung, mehr nicht.


Gruss
Delbor
Roger
Man muss und kann nicht alles wissen - man muss nur wissen, wo es steht.
Frei nach Albert Einstein
http://roase.ch
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.358 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: OOP wirklich nicht möglich?

  Alt 19. Okt 2017, 16:53
Gäbe es eine OOP-Lösung, um TQueryResultClass zu ändern? Änderungsziel: Gleiches Funktionieren, wie ursprünglich implementiert, aber mit andern Bezeichnern.
Ok, also ist Deine Kernfrage, wie Du die Properties der Klasse und die Klasse selbst am einfachsten umbenennen kannst?
Da wäre zu sagen: Rechtsklick / Refactoring / Umbenennen.
Das kannst Du für die Properties sowie Getter und Setter machen.

Was Du in diesem Zusammenhang mit OOP meinst, kann ich nicht nachvollziehen.

Insgesamt würde ich aber weiterhin zu einem anderen Ansatz raten.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Delbor

Registriert seit: 8. Okt 2006
Ort: St.Gallen/Schweiz
1.196 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: OOP wirklich nicht möglich?

  Alt 19. Okt 2017, 19:02
Hi stahli

Zitat:
Da wäre zu sagen: Rechtsklick / Refactoring / Umbenennen.
In etwa so ist QueryCMResultClass entstanden, wobei ich in den meisten Fällen den Sync-Arbeitsmodus verwendet habe.
Die Frage zielte eigentlich hauptsächlich darauf ab, wie ich das nächste mal vorgehen muss, um die Sache möglichst einfach durchzuziehen.
Vor kurzem habe ich ein Interface-Testprogrämmchen begonnen.
Wenn ich die Sache richtig verstanden habe, müsste ich TQueryResultClass statt von TPersistent von TInterfacedobject, IMeinInterface abbleiten, letzteres inklusive der Member deklarieren und die Member in TQueryResultClass implementieren. Somit hätte ich, wenn ich das richtig verstehe, durchaus eine OOP-Lösung.

Gruss
Delbor
Angehängte Grafiken
Dateityp: jpg 19_49_52-Klassen_QueryCMResultUnit.pas.jpg (78,5 KB, 12x aufgerufen)
Roger
Man muss und kann nicht alles wissen - man muss nur wissen, wo es steht.
Frei nach Albert Einstein
http://roase.ch

Geändert von Delbor (19. Okt 2017 um 19:07 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.358 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: OOP wirklich nicht möglich?

  Alt 19. Okt 2017, 19:55
Irgendwie verstehen wir uns nicht so richtig...

Also mit OOP arbeitest Du ja schon, da Du mit Klassen und Objekten arbeitest.

Mit Interfaces zu arbeiten ist schon auch sinnvoll, bedingt aber einige Einarbeitungszeit und erhöht den Schreibaufwand, da man die Klassenmember immer zwei mal schreiben muss und Delphi dabei wenig unterstützt.
Mit der automatischen Referenzzählung hat man ggf. einen Vorteil, weil man sich nicht um die Lebenszeit der Objekte kümmern muss. Das braucht aber auch einige Zeit, bis man damit richtig umgehen kann und das verinnerlicht.

Was auf jeden Fall eine Hilfe ist, ist die Abstraktion, die man durch Interfaces erhält.

Aber genau gegen diese Abstraktion wehrst Du Dich schon bei Deinen Klassen, weil Du die völlig abhängig von Deinen Datenbanktabellen gestalten willst. Das ist wirklich nicht sinnvoll. Wenn Du jetzt mit Deinen Datenbankabhängigen Klassen noch Interfaces unterstützen willst, dann hast Du noch mehr Aufwand und noch weniger Nutzen.

Was ich oben schon versucht habe zu vermitteln ist, dass die Businessklassen ihren Kram so erledigen sollen, dass sie optimal und logisch arbeiten, ohne irgendeinen Bezug zur Datenbank zu haben.
Dann baust Du eine Datenbank, die Ihre Aufgabe, Daten zu verwalten, gut erledigt. Da eine relationale Datenbank keine Delphi-Klasse ist, wird es in der Datenschicht irgendwie anders aussehen, als in der Business-Schicht. Wurscht!!!!!!
Jetzt brauchst Du einen Vermittler, der Daten aus den Objekten in die Datenbank schreibt oder in der anderen Richtung in die Objekte lädt.

Wenn Du das versuchen würdest, hättest Du eine gute Projektstruktur mit einer (relativ) guten Entkopplung der einzelnen Schichten.


Wenn das getan ist - und wirklich erst dann! - könnte man die Entkopplung noch weiter treiben und Interfaces einführen.
Das wäre aber der I-Punkt auf eine saubere Trennung der einzelnen Schichten.


Also mein Tipp fürs nächste Mal:

1) Businessklassen für die Buisnesslogik (ohne Abhängigkeit und zwanghafte Namensgleichheit zur Datenbank).
2) Datenbank in sich sinnvoll aufbauen (ohne Abhängigkeit auf die Klassen)
3) Datenbankmanager zum Speichern und Laden von Daten.
4) GUI nur mit Bezug auf die Business-Schicht
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Benutzerbild von TigerLilly
TigerLilly

Registriert seit: 24. Mai 2017
Ort: Wien, Österreich
1.251 Beiträge
 
Delphi 12 Athens
 
#5

AW: OOP wirklich nicht möglich?

  Alt 19. Okt 2017, 21:14
Nochmal. Decorator.

Mach eine Klasse, deren Properties so heißen, wie du möchtest, deren Getter+Setter aber auf deine Originale Klasse zugreifen.
Alle Methode dieser Klasse benennst du, wie du möchtest, die rufen aber nur Methoden deiner alten Klasse auf.

Wenn das nicht das ist, was du möchtest, weiß ich leider nicht weiter.

Vergiss das mit den Interfaces vorerst, das ist ein Implementierungsdetail + ich glaube, du weißt noch nicht, was du implementieren möchtest.
  Mit Zitat antworten Zitat
Delbor

Registriert seit: 8. Okt 2006
Ort: St.Gallen/Schweiz
1.196 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: OOP wirklich nicht möglich?

  Alt 19. Okt 2017, 21:43
Hi TigerLilly
Zitat:
Nochmal. Decorator.

Mach eine Klasse, deren Properties so heißen, wie du möchtest, deren Getter+Setter aber auf deine Originale Klasse zugreifen.
Alle Methode dieser Klasse benennst du, wie du möchtest, die rufen aber nur Methoden deiner alten Klasse auf.
Ups! Offenbar hab ich da was überlesen, bzw. einen fatalen Denkfehler gemacht, indem ich dachte, die Basisklasse würde da (auf der von mir verlinkten Seite zum Decorator Pattern) gewissermassen mit einem Interface 'dekoriert'.

Ich werde mir da doch noch einiges a Tutorials und Theorie einverleiben müssen.

Gruss
Delbor
Roger
Man muss und kann nicht alles wissen - man muss nur wissen, wo es steht.
Frei nach Albert Einstein
http://roase.ch
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.358 Beiträge
 
Delphi 11 Alexandria
 
#7

AW: OOP wirklich nicht möglich?

  Alt 19. Okt 2017, 22:03
Ich denke nicht, dass das Decorator-Pattern hier wirklich hilfreich ist.

Das Ziel ist ja, dass die Klassenmember so heißen, wie die Datenbankfelder.
Man müsste also die DB-Zugriffe in den Originalklassen auf die neue Datenbank anpassen und um die alten Klassen neue Klassen hüllen, die nach außen neue Namen für die alten Member anbieten.

Das wäre ja noch mehr Durcheinander als so schon.

Wenn Du von den namensgleichen Klassenmembern und Tabellenfeldern nicht abrücken willst und die Tabellenfelder neue Namen erhalten, dann ist der einfachste Weg, tatsächlich das Refactoring-Umbenennen.


Dass diese Namensgleichheit aber unnötig und nachteilig ist, habe ich ja schon öfter erwähnt.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.052 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#8

AW: OOP wirklich nicht möglich?

  Alt 20. Okt 2017, 10:47
Nochmal. Decorator.

Mach eine Klasse, deren Properties so heißen, wie du möchtest, deren Getter+Setter aber auf deine Originale Klasse zugreifen.
Alle Methode dieser Klasse benennst du, wie du möchtest, die rufen aber nur Methoden deiner alten Klasse auf.
Das nennt sich Adapter und nicht Decorator.
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight
  Mit Zitat antworten Zitat
Benutzerbild von TigerLilly
TigerLilly

Registriert seit: 24. Mai 2017
Ort: Wien, Österreich
1.251 Beiträge
 
Delphi 12 Athens
 
#9

AW: OOP wirklich nicht möglich?

  Alt 20. Okt 2017, 10:52
Da hast du recht.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:25 Uhr.
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