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 18. Okt 2017, 09:20
Hi zusammen

Inzwischen habe ich, wie vor einiger Zeit von TigerLilly angesprochen, quasi "von Hand", bzw. durch Suchen und ersetzen, eine neue Klasse analog TQueryresultClass erstellt. Soweit wär eigentlicheine Vorausetzung für den Umbau gegeben.
Trotzdem hat mich die Sache nicht losgelassen, und so hab ich auch das gefunden. Weiter habe ich mir auch die verschiedenen Beiträge und Tutorials zu Interfaces hier und auf andern Webseiten, insbesondere Stahlisoft und Youtube, angesehen.
Die OOP-Vorgehensweise nach dem Decorator Pattern wäre demnach also gewesen:
  1. Ein Interface zu deklarieren(TInterfacedobjekt und (muss ich nochmal nachsehen)
  2. TQueryresultClass nicht nur von TPersistent, sondern zusätzlich von meinem Interface abzuleiten
Noch nicht ganz klar ist, ob ich die Methoden, die meine neu benannten Tabellen auslesen, im Interface nur deklariere oder auch implementiere ( Die Embarcadero Onlinehelp irritiert mich da etwas).
So aus dem Stegreif heraus: Ja zu letzterem und anschliessend in TQueryresultClass nur deklarieren, damit ich sie von da auch ausrufen kann. Diese Frage wird mir letztlich endgültig klar, wenn ich mir ein Testprogrämmchen geschrieben habe.

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 TigerLilly
TigerLilly

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

AW: OOP wirklich nicht möglich?

  Alt 18. Okt 2017, 09:41
Fein, dass mein Vorschlag des Decorator Patterns wieder auftaucht. *eiteldreinschau*

Aber der decorator macht ja eigentlich was anderes, als du hier beschrieben hast:Ein decorator legt eine andere Benutzerschicht über deine Klasse und reicht so Funktionalitäten durch. So kannst du die Methoden des Decorators aufrufen und der routet das weiter an die alte Klasse. das ist eine recht elegante Methode, wenn man wie du ja auch - Klassen umbaut und beide Varianten aktiv halten möchte.

Interfaces sind cool, haben mit dem Entwurfsmuster aber nichts zu tun. Interfaces sind operativ (=wie mache ich es), Entwurfsmuster sind taktisch(=was mache ich?). Und eine Strategie (=warum mache ich das?) braucht es natürlich auch.
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.666 Beiträge
 
Delphi 12 Athens
 
#3

AW: OOP wirklich nicht möglich?

  Alt 18. Okt 2017, 09:50
Man kann in einer Interface-Deklaration überhaupt nichts implementieren, das ist ja gerade deren Sinn. Wenn Du von außen auf ein Interface zugreifst, weißt Du zunächst einmal nur, dass die dahinterliegende Objektinstanz garantiert alle Eigenschaften besitzt und Methoden implementiert, die im Interface vereinbart sind.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  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 18. Okt 2017, 12:18
@Delbor

Ich denke, Du musst Deinen Grundsatzüberlegungen nochmal etwas ordnen und strukturieren.

Nimm Dir mal ein Blatt Papier und zeichne Dir mal einen Plan, wo welche Zuständigkeiten geregelt werden sollen. Je klarer Dir das gelingt, je strukturierter wird Dein Programm aufgebaut sein.

Für Außenstehende ist vermutlich schwer nachzuvollziehen, was Du aktuell genau vorliegen hast und was Du ändern willst.

Z.B. ist m.E. bisher nicht klar geworden, wie diese Komponenten
Delphi-Quellcode:
    FTblBildText : TTblBildText; // FBildDescribeTabelle : TBildDescribeTabelle;
     FTblAlbum : TTbl_Album; // FKategoryTabelle : TKategoryTabelle;
aufgebaut sind. Haben sie noch eine Verbindung zur Datenbank oder nicht?
Wenn nicht, warum sind es dann unterschiedliche Klassen und warum sind die Felder unterschiedlich benannt?
Wenn ja, warum nimmst Du nicht eine Klasse, die die Daten unabhängig von einer Datenbank verwaltet und bearbeitet?

Wie viele Daten verwaltest Du insgesamt in der Anwendung? Können alle Daten insgesamt im Speicher gehalten werden oder ist die Datenbank so groß, dass immer nur bestimmte Datensätze daraus abgeholt werden können?

Das sind viele grundsätzliche Fragen, die eigentlich erst mal geklärt werden müssten und zu entsprechend unterschiedlichen Lösungen führen werden.

Wie in #12 schon mal angesprochen, musst Du Dir eine übersichtliche Struktur überlegen, die klare Zuständigkeiten und Verbindungen verschiedener Projektmodule abbildet.

Dafür gibt es dann je nach den Gegebenheiten verschiedene Lösungsmöglichkeiten.


Was ich generell nicht verstehe ist, dass Du Deine Businessklassenstruktur änderst, wenn Du die Datenbank wechselst oder die Tabellen in der Datenbank andere Namen haben.

Nach meiner Überlegung müsstest Du in Deinem Projekt das "Datenbankmodul" anpassen, aber nicht die Businessklassen.


Interfaces zu verwenden kann sinnvoll sein, muss es aber nicht in jedem Fall. Wenn Du damit noch keine Erfahrungen hast, würde ich die Projektstruktur erst mal überarbeiten und auf Interfaces verzichten. Da hängt noch einiges an notwendigen Anpassungen dran, die jetzt vielleicht unnötig verwirren würden.

Statt dessen solltest Du eine Datenbankunit oder Datenbankklasse einführen, die alle Zugriffe auf die alte Datenbank kapselt - so dass Deine Anwendung nicht mehr die Datenbank selbst kennt, sondern nur noch Deine Datenbankunit oder Datenbankklasse.
Dann kannst Du eine neue Datenbankunit oder -Klasse aufbauen, die die selben Schnittstellen nach außen hat, aber intern auf eine andere Datenbank geht.

So hättest Du schon mal eine gute Trennung der Zuständigkeiten.
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
 
#5

AW: OOP wirklich nicht möglich?

  Alt 18. Okt 2017, 16:10
Hi zusammen

@ stahli
Zitat:
FTblBildText : TTblBildText; // FBildDescribeTabelle : TBildDescribeTabelle;
FTblAlbum : TTbl_Album; // FKategoryTabelle : TKategoryTabelle;
Grundsätzlich trennt mein Programm GUI und Datenhaltung. Letzteres fällt in die Zuständigkeit zweier Datenmodule; je eines für eine Verbindung zu MySQL und eines, relativ neu in Arbeit, zu SQLite.
Die Datenbank selbst beinhaltet 12 Tabellen, wovon zurzeit nur 4 für Bild- und Textinhalte zuständig sind. Von drei dieser Tabellen gibt es innerhalb von TQueryresultClass Entsprechungen gleichnamiger Klassen.
Das obige Zitat gibt 2 Klassenfelder meiner gleichaufgebauten Klassen TQueryCMresultClass(FTblBildText ,FTblAlbum) und TQueryresultClass(FBildDescribeTabelle,FKategoryTa belle) wider.
Ich hänge hier mal noch TQueryCMresultClass an, um die Unterschiede zu verdeutlichen; diese bestehen ausschlieslich aus den in TQueryCMresultClass verwendeten kürzeren Tabellen- und Feldbezeichnern.
Natürlich wurde die SQLite_Datenbank auch mit den verkürzten Tabellennamen erstellt.
Zitat:
Haben sie noch eine Verbindung zur Datenbank oder nicht?
Wie bereits gesagt, handelt es sich hierbei um Klassenfelder, bzw. Unterklassen, die selbst keine Verbindung zur Datenbank haben.
Bei Select-Abfragen der TQuery-Komponente werden deren Resultate jeweils pro Datensatz über 3 Tabellen (ohne Zwischentabelle) in einer TQueryCMresultClass - Instanz festgehalten und diese einer Objectlist hinzugefügt. Dabei gibt es eine Besonderheit: Bilddaten werden bei der ursprünglichen Abfrage über mehrere Datensätze mit Ausnahme des Thumbnails vorerst nicht abgefragt, sondern erst, wenn sie zur Darstellung des Bildes benötigt werden.

Ein Ziel meiner Umstellung auf SQLite: von mir so genannte "Satelliten-DBs" zu erstellen(*). Das hat folgende Grund: Zur Zeit speichere ich die Bilder noch in einem Ordner auf Festplatte. Wenn die Dinger schliesslich in die DB geschrieben werden, werden aus den Rohbildern nicht nur die Thumbnails, sondern auch gleichzeitig Bitmaps in Originalgrösse erstellt. Dabei sollten auch die Rohdaten ursprünglich mit in die DB - und blähen diese zu gigantischer Grösse auf.
Und hier kommen dann meine "Satelliten-DBs" zum Zug: In ihnen werden die Rohdaten und Originalbitmaps zusammen mit einem Textfeld für den Namen und einem FK-Integer für das Album gespeichert. Diese Dinger bringen es auf Grössen von in etwa 25GB oder weniger, sind also eigentlich sogar als eine Art Rohdatenbackup zu gebrauchen und können Extern an beliebigen Orten gespeichert werden.
Wo sich diese "Satelliten-DBs" befinden, bestimmt letzlich der User über ein Optionen-Fenster.

Zitat:
Wie viele Daten verwaltest Du insgesamt in der Anwendung? Können alle Daten insgesamt im Speicher gehalten werden oder ist die Datenbank so groß, dass immer nur bestimmte Datensätze daraus abgeholt werden können?
Als ich das letzte mal gezählt habe, waren es ca. 13 000 Fotos.
Zitat:
Was ich generell nicht verstehe ist, dass Du Deine Businessklassenstruktur änderst, wenn Du die Datenbank wechselst oder die Tabellen in der Datenbank andere Namen haben.
An den Strukturen der Klassen ändert sich ja nichts - nur die verwendeten Namen sind kürzer geworden. Am Beispiel eines SQL-Statements:
Delphi-Quellcode:
function TFDMySQLDml.DefineBildSQL3(Kath_Id: Integer) : String;
begin
Result := 'SELECT Bildtabelle.idBild as BildID, ' +
            'bilddescribetabelle.BilddesribeID as BildDescribeId, ' +
            'bilddescribetabelle.bildkatID as BildkatID, '+
            'bilddescribetabelle.bildname as Bildname, ' +
            'bilddescribetabelle.bildbeschreibung as Bildbeschreibung, '+
            'bilddescribetabelle.bildlegende as bildlegende, ' +
            'kategorien_tabelle.Kath_ID as KathID, ' +
            'kategorien_tabelle.Kategorie as Kategorie, '+
            'kategorien_tabelle_has_bilddescribetabelle.kategorien_tabelle_Kath_ID as TblKat_Id, '+
            'kategorien_tabelle_has_bilddescribetabelle.BildDescribeTabelle_BilddesribeID as BildDesc_Id '+
          'FROM ' +
            'bildtabelle, bilddescribetabelle, ' +
            'kategorien_tabelle_has_bilddescribetabelle, ' +
            'kategorien_tabelle '+
          'WHERE '+ {erste Tabelle}
            'Kategorien_tabelle.Kath_Id = :Kath_Id '+
          'AND '+ {zweite (Selektionstabelle) Tabelle wird mit erster verglichen}
            'kategorien_tabelle_has_bilddescribetabelle.kategorien_tabelle_Kath_ID = Kategorien_tabelle.Kath_Id ' +
          'AND '+ //--------------------
            'kategorien_tabelle_has_bilddescribetabelle.BildDescribeTabelle_BilddesribeID = bilddescribetabelle.BilddesribeID ' +
          'AND '+
            'Bildtabelle.idBild = bilddescribetabelle.bildtabelle_idbild';
// Showmessage(Result);
end;
Das dürfte viel schwerer zu lesen sein als:
Delphi-Quellcode:
function TFDMySQLDml.DefineBildSQL3(Kath_Id: Integer) : String;
begin
Result := 'SELECT Tbl_Bild.idBild as BildID, ' +
            'TblBildText.BilddesribeID as BildDescribeId, ' +
            'TblBildText.bildkatID as BildkatID, '+
            'TblBildText.bildname as Bildname, ' +
            'TblBildText.bildbeschreibung as Bildbeschreibung, '+
            'TblBildText.bildlegende as bildlegende, ' +
            'TblAlbum.Kath_ID as AlbumId, ' +
            'TblAlbum.Kategorie as Kategorie, '+
            'TblAlbum_has_TblBildText.TblAlbum_Album_Id as TblKat_Id, '+
            'TblAlbum_has_TblBildText.TblBildText_BilddesribeID as BildDesc_Id '+
          'FROM ' +
            'bildtabelle, TblBildText, ' +
            'TblAlbum_has_TblBildText, ' +
            'TblAlbum '+
          'WHERE '+ {erste Tabelle}
            'TblAlbum.Album_Id = :Album_Id '+
          'AND '+ {zweite (Selektionstabelle) Tabelle wird mit erster verglichen}
            'TblAlbum_has_TblBildText.TblAlbum_Album_Id = TblAlbum.Album_Id ' +
          'AND '+ //--------------------
            'TblAlbum_has_TblBildText.TblBildText_BilddesribeID = TblBildText.BilddesribeID ' +
          'AND '+
            'Bildtabelle.idBild = TblBildText.bildtabelle_idbild';
// Showmessage(Result);
end;
Wobei ich jetzt nur mal einiges ersetzen lassen habe - zu Demozwecken in einer neuangelegten, aber nicht gespeicherten Unit.
Zitat:
Nach meiner Überlegung müsstest Du in Deinem Projekt das "Datenbankmodul" anpassen, aber nicht die Businessklassen.
Hmmm - was verstehst du genau unter Businessklassen? In der Schichtenprogrammierung gibt es meines Wissens folgende Ebenen//Schichten:
  1. Die Gui
  2. Die Logik- oder BusinessSchicht und schliesslich die
  3. Datenschicht (Datenmodul(e), DB-Verbindungen)
wobei die oberen nach unten durchgreifen dürfen, aber nicht umgekehrt. Wobei die Daten von der Gui in einem Stringgrid dargestellt werden und das daher auf die Objectliste mit meinen Datenklassen zugreifen muss - das aber entspricht dem Modell(von oben nach unten).

Zitat:
Interfaces zu verwenden kann sinnvoll sein, muss es aber nicht in jedem Fall. Wenn Du damit noch keine Erfahrungen hast, würde ich die Projektstruktur erst mal überarbeiten und auf Interfaces verzichten. Da hängt noch einiges an notwendigen Anpassungen dran, die jetzt vielleicht unnötig verwirren würden.
Deshalb habe ich TQueryCMresultClass zuerst mal analog TQueryresultClass "händisch erstellt, indem ich TQueryresultClass als TQueryCMresultClass abgespeichert und verschiedene Namen durch <Suchen-Ersetzen> geändert habe.
Für Interfaces gibts erstmal ein (umfangreiches?) Testprogramm. Und erst Sachen, die da funktionieren und mir klar ist, warum sie das tun, können in meinem Programm eingebaut werden.

Zitat:
Statt dessen solltest Du eine Datenbankunit oder Datenbankklasse einführen, die alle Zugriffe auf die alte Datenbank kapselt - so dass Deine Anwendung nicht mehr die Datenbank selbst kennt, sondern nur noch Deine Datenbankunit oder Datenbankklasse.
Dann kannst Du eine neue Datenbankunit oder -Klasse aufbauen, die die selben Schnittstellen nach außen hat, aber intern auf eine andere Datenbank geht.
Das sind meine Datenmodule.

(*) abgesehen davon, dass es eigentlich unsinnig ist, als Anwendungsdatenbank einen Server wie MySQL zu verwenden (Ausnahme:EmbeddedServer)

Gruss
Delbor
Angehängte Dateien
Dateityp: pas QueryCMResultUnit.pas (15,9 KB, 3x aufgerufen)
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
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 21:56 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