raist10 hat geschrieben:Lass mich kurz konkretisieren ... was definierst Du als Schnittstelle?
Eine festgeschriebene Definition wie zwei Elemente (z. B. Klassen) miteinander kommunizieren.
Würde ich eine Klasse für einen DAO-/ADO-Zugriff programmieren, würde jede Klasse einen eigenen Verbindungsaufbau für sich selbst spendiert bekommen, allerdings verbunden mit der Optionalen Möglichkeit bei Ansprache der Klasse eine bereits bestehende DbConnection mit zu geben.
Genau. Außerdem besitzen sie auch noch ein paar Ereignisse, mit denen sie notfalls fehlende Werte anfordern können bzw. anderen Steuerungsklassen die Möglichkeit geben einzugreifen.
Möglicherweise würde ich die DAO-/ADO-Zugriffe die die Klassen in sich selbst mitführen auf CurrentProject/CurrentDB beschränken und wer dann auf eine andere Verbindung zu greifen will, benötigt die Klasse DBConnection und gibt die dort erstellte Connection als zusätzlichen Parameter an den DAO-/ADO-Zugriff mit.
Die Verwendung von CurrentProject und CurrentDB sollte meiner Ansicht nach bei solchen Klassen tabu sein. Die passende ADODB.Connection bzw. DAO.Database sollten sie von außen erhalten, aber nicht selbstständig die Annahme treffen, dass mit den Standard-Verbindungen gearbeitet werden soll.
Würde zwar pro Klasse ein wenig mehr Aufwand bedeuten, würde aber die Klassen wesentlich flexibeler machen und vor allem kein Problem mehr wenn sich etwas an einer Klasse ändert … solange die Art der Übergabe stimmt juckt es keine der Klassen wenn sich eine andere Klasse geändert hat.
... zumindest ist es nicht deren Aufgabe auf Verbindungsänderungen zu horchen. Das ist eine Bringschuld der Verbindungssteuerung, diesen Klassen die passende Verbindung zu liefern.
Aber ich glaub, du musst dir die Klassen doch mal ansehen, bevor wir darüber (am besten im anderen Thread) weiter diskutieren.
Bezüglich Flexibilität fehlt denen vermutlich nicht besonders viel.
Da sind wir wieder beim Thema … eine Klasse sollte unabhängig vom Projekt funktionieren.
Wenn jede Klasse unabhängig vom Projekt funktionieren muss, dann kannst du somit alle .net-Projekte wegwerfen, da es dort nur Klassen zur Gestaltung des Projekt-Codes gibt.
Oder: Eine Datenkapselung einer Tabelle in einer Klasse funktioniert auch ohne Datenbank und Tabelle?
.. andererseits funktionieren Klassen natürlich auch unabhängig vom Projekt, wenn in einem anderen Projekt die gleichen Voraussetzungen gegeben sind.
Die Frage ist für mich eher:
muss eine Klasse unabhängig von anderen Klassen funktionieren? ... Meiner Ansicht nach muss sie das nicht, es ist aber durchaus gut, wenn sie eigenständig arbeiten kann.
Ich würde eine Zugriffsbeschränkung eher so formulieren:
Eine Detailklasse hat nichts in den Eigenschaften oder Methoden der übergeordneten Klasse zu suchen, sondern darf nur über Ereignisse von sich aus der übergeordneten Klasse etwas mitteilen. Im Standardfall hat die Detailklasse nur auf Anfragen (Methoden-/Eigenschaftsaufrufe) von der übergeordneten Klasse zu reagieren. Damit entsteht keine gegenseitige Abhängigkeit.
Möglicherweise reden wir aber auch aneinander vorbei. Ich glaube, wir beide verstehen unter eine Klasse unterschiedliche Dinge.
Sprichst du eventuell nur dann von Klassen, wenn sie eine kleine in sich geschlossene Aufgabenstellung kapseln. Ich erstelle eine Klasse durchaus auch für komplexere Aufgabenstellungen, für deren Lösung sich diese Klasse weiterer Klassen bedient. Eine Klasse ist für mich einfach eine Blackbox zur Lösung einer Aufgabestellung, egal wie komplex diese ist.
Beispiel:
Klasse Auto:
Methoden
- schneller fahren
- langsamer werden
- ...
Diese Klasse bedient sich
intern bei den Klassen: Motormanagement, Lenkung, ...
Für die Nutzung der Klasse Auto ist es mir aber vollkommen egal, wie die Klasse das macht. Ob sie das über Ereignisse, Callback-Aufrufe, Eigenschaftsübergaben usw. macht, hat mich als Nutzer der übergeordneten Klasse gar nicht zu interessieren, da für diese Dinge die Entwickler dieser Klasse dafür zuständig sind. Ich habe nur die Methoden und Eigenschaften, die über die Klasse "Auto" zur Verfügung gestellt werden, zu nutzen. Ich werden also nicht irgendwo ein Modul erstellen und Prozeduren programmieren, die die einzelnen Autoteile zuerst zu einem Auto zusammenbaut, um erst dann damit die Methoden nutzen zu können.
Ich würde höchsten die Klasse Auto in eine Klasse Ferrari ausbauen (Vererbung), um dort dann Feintuning zu betreiben und der Ferrari-Klasse einen anderen Motor geben, der dann über die ebenso ausgetauschte Motorsteuerung gesteuert wird. Die Schnittstelle "Fuß" müsste ich aber vermutlich auch beim Ferrari erfüllen.
Im Extrem habe ich sogar gelernt, dass eine Klasse die einen Verweis benötigt sich auch selber darum zu kümmern hat das der benötigte Verweise vorhanden ist und ihn wenn nicht vorhanden, dann auch beim Initiliaze selbst setzt.
So etwas halte ich zur Laufzeit für falsch. Außerdem: zeig mir bitte, wie du in einer mde einen Verweis hinzufügst.
Ich baute das dafür in den Import-Wizard ein, der Verweise in den Access-Anwendungsentwurf einfügen kann, wenn die Bibliothek im Codelib-Block angegeben wurde.
Daher auch die strikte Beachtung von Late Binding.
Late binding als allgemein gültige Vorschrift ist meiner Ansicht nach fahrlässig - vor allem bei Klassenmodulen, die in der Access-Anwendung gespeichert sind - da man damit jede Kontrolle durch den Compiler deaktiviert. Late binding sollte meiner Ansicht nach nur eine Notlösung sein.
... Oder deklarierst du auch alle Variablen generell als Variant und nicht als String oder Long usw.?
Eigentlich existiert diese Abhängigkeitsproblematik nur wegen der wiederverwendbaren Klassen. Würde ich Klassen nur für eine spezielle Anwendung erstellen, würde die Klasse genau auf diese zugeschnitten sein.
Wofür erstellt man eigentlich eine Klasse die man in keinem anderen Projekt mehr verwenden kann?
Damit man auch bei projektspezifischen Elementen die Vorteile von Klassen nutzen kann?
Und wer sagt dir eigentlich, dass du diese Klassen nicht später auch ein einem anderen Projekt verwendest, das auf dieses Projekt aufbaut?
Da will mir der Sinn solcher Klassen nicht einleuchten, eher unsinnig da man für die Verwendung der Klasse im Projekt ja immer referenzieren muss. Es gibt keinen Vorteil … ausser man benötigt die Feuerung von Klassen-Ereignissen.
Wie meinst du das? Meinst du damit das Instanzieren der Klasse? Ja klar ist das notwendig, aber das ist auch gleichzeitig der Vorteil zu einem allgemeinen Modul. Ich kann mehrere Instanzen parallel öffnen, ohne dass sie sich in die Quere komme. Würde ich nur Prozeduren aus allgemeinen Modulen verwenden, müsste ich in jeder Prozedur das mit einer nicht zu knappen Anzahl an Parametern abdecken.
Aber für genau so eine Code-Lib bietet es sich an die Grundregeln einer Klasse einzuhalten. Nämlich völlige Unabhängigkeit von anderen Klassen und damit absolute Portabilität in jedes x-beliebige Projekt ohne Vorraussetzung.
Das sehe ich nicht so. Ich will mir in meine Anwendung die Blackbox "Auto" holen. Wenn dann im Import andere Klassen mitgehen, ist mir das eigentlich egal. Hauptsache ich kann die Klasse Auto instanzieren und die Methode "Schneller fahren" aufrufen. Interessant wird es dann allerdings, wenn ich nun in meinem Projekt einzelne untergeordnete Klasse gegen Klassen mit projektspezifischer Erweiterung austauschen will. Sobald ich austausche, kann ich von den Weiterentwicklungen der Ursprungsklasse nicht mehr profitieren. (Anm.: Vererbung funktioniert ja leider unter VBA nicht.)
Die erzeugte Individualisierung kann allerdings doch so allgemein sein, dass sie auch in anderen Anwendung Verwendung findet. Also könnte ich sie wieder in die Code-Bibliothek stellen.
Problem: Doppelgleisigkeit bei der Entwicklung
Mögliche Lösung: die Ursprungsklasse mit ein paar weiteren Schnittstellen (z. B. in Form von Ereignissen) versehen, damit ich mich mit meiner Erweiterung dort einhängen kann.
Zur Sicherheit noch einmal: normalerweise wäre das ein Fall für Vererbung, der aber unter VBA nicht möglich ist. Daher kann man im Prinzip nur eine neue Klasse erstellen und die vorhandene Klasse darin als internes Objekt nutzen, um nicht jede Verbesserung auch noch in seiner eigenen Klasse einbauen zu müssen.
Nachteil: Die Anzahl der Klassenmodule in der Anwendung wird dadurch immer größer.
Was spricht dagegen Codes die von anderen Klassen abhängig sind, als Code-Module anstatt Code-Klassen einzustellen?
Grundsätzlich nichts ... aber was spricht dagegen, das auch als Klassenmodul einzustellen? ... meiner Ansicht nach genauso wenig.
Beim Einsatz in Klassen habe ich den Vorteil, dass ich auf die Ereignisse der verwendeten Klassen reagieren kann und falls ich mehrere Kombinationen gleichzeitig nutzen will, ist das meiner Ansicht nach auch übersichtlicher und weniger fehleranfällig gestaltbar.
Allgemeine Module sind für mich eher Code-Sammler für Prozeduren, die nur auf Basis der übergebenen Parameter agieren. Irgendwelches Zwischenspeichern von Modul-Variablen, die dann in anderen Prozeduren wieder zum Einsatz kommen, vermeide ich. So etwas nutze ich nur in Klassen, da in Klassen der Zugriffsbereich eindeutig abgesteckt ist.
Vor allem sollte man die Code-Module auch nicht jedes Mal nachbearbeiten müssen. ... aus diesem Grund nutzte ich schon länger die Variante mit dem "_config_Application"-Modul, in dem die Anpassung für die Anwendung stattfindet.
Was muss man bei einer Klasse die nach dem Prinzip der Unabhängigkeit programmiert wurde anpassen um Sie in einem Projekt einzusetzen?
... nichts, wenn sie so programmiert wurde und genügend Einstellmöglichkeiten von außen aufweist.
Wenn Du hier also Grundspielregeln für eingestellte Klassen festlegen willst, dann wäre wirklich die Frage ob es nicht sinniger wäre bei Einstellung einer Klasse als Code-Lib die Unabhängigkeit der Klasse von irgendwelchen weiteren Projektbausteinen als Basis festzulegen.
oha .. bitte nicht falsch verstehen. Ich will hier keinesfalls irgendwelche Code-Konstrukte verbieten.
Und je unabhängiger eine Klasse ist, umso besser ist es natürlich.
P.S.: Stell mal den Forums-Schnell-Editor um … das rumgehopse wenn man mal mehr schreiben will nervt. ^^
Welches Rumgehopse meinst du? Soll ich ihn ausschalten?
mfg
Josef
BTW: bevor jetzt viele befürchten, dass nur Klassen in die Code-Bibliothek kommen, deren Struktur keiner mehr versteht: die oben geschilderte Problemstellung wird bestimmt nur vereinzelt vorkommen, da ich aber schon länger über mögliche Konzepte für VBA und Einsatz von austauschbaren Klassen nachdenke, wollte ich das auch in Verbindung mit der Codelib betrachten.
Vielleicht noch ein Szenario, wie man das Auto vs. Ferrari-Problem mittels Import-Assistent lösen könnte.
Man baut in einer Access-Anwendung die Auto-Klasse direkt in eine Ferrari-Klasse um und behält den Klassenamen "Auto". Nur im Codelib-Block fügt man einen Dateinamen ein, der darauf hinweist, dass es sich um eine spezielle Auto-Klasse handelt (z. B. "Auto_Ferrari.cls").
Wenn man nun die so manipulierte Klasse "Auto" exportiert, entsteht die Datei Auto_Ferrari.cls. Beim Import dieser Datei in eine an der Anwendung heißt die Klasse aber wieder "Auto".
Damit gibt es auch bei den restlichen Code-Modulen kein Problem, da sich ja der Klassenname nicht geändert hat. Man kann somit die Klasse "Auto" von der Datei Auto.cls mit der Klasse "Auto" von der Datei Auto_Ferrari.cls ersetzen.
Nachteil: es funktioniert natürlich nur dann, wenn immer nur eine Auto-Klasse zum Einsatz kommen soll und man sieht am Klassennamen nicht, um welches Auto es sich handelt. ..
Größter Nachteil: Fehler im Code der Original-Klasse "Auto.cls" die in die Ferrari-Klasse ebenso noch existieren müssen in beiden Klassen korrigiert werden.
Vorteil: für Code, der einen anderen ersetzen soll, wäre damit eine Lösung geschaffen, die Early binding unterstützt, keine Schnittstellenklasse benötigt und keine weiteren Hilfsklassen benötigt.
Ein reales Beispiel, wo ich mir so einen Einsatz vorstellen könnte: Ein Klasse die SQL-Anweisungen abhängig vom verwendeten DBMS gestaltet. Da man in einer Access-Anwendung vermutlich eher nur auf ein DBMS ausrichtet, könnte man damit alle Code-Module die diese HIlfsklasse benötigen unabhänig vom DBMS gestalten.
(Natürlich wäre hier eine Schnittstellenklasse die bessere Lösung, aber wie schon öfter angedeutet ... Access/VBA ist eben nicht VB.net, C# oder C++
)