Zusammenspiel von Klassen
Verfasst: Fr 26. Mär 2010, 11:10
Hallo!
In diesem Thread möchte ich einmal versuchen herauszufinden, wie man abhängige Klassen am besten miteinander verbindet.
Gegeben sei folgende Grundstruktur:
Beispiel:
Hauptklasse = Access.Application
Detailklasse = CurrentProject
Beispiel für Verwendung:
Das könnte ich in der Hauptklasse so gestalten
Nachteil dieser Variante: man macht die Hauptklasse von der Detailklasse abhängig. Wenn ich nun die Detailklasse ABC durch eine andere Klasse "ABCerweitert" ersetzten will, ist das nicht mehr ganz so einfach. Ich muss dann auf jeden Fall in ABCerweitert als Schnittstelle die Klasse DetailklasseABC einbauen. ... und da beginnt dann das Problem bei Access: je mehr Schnittstellen eingebaut werden, desto höher ist die Wahrscheinlichkeit, dass der VBA-Binär-Code defekt wird - ohne regelmäßiges Decompile kracht es dann laufend während der Programmierung (zumindest nach meiner bisherigen Erfahrung).
Ein anderer Ansatz:
Nicht die Hauptklasse von der Detailklasse (bzw. einer Schnittstelle dieser Detailklassendefinition) abhängig machen, sondern die Detailklassen von der Hauptklasse abhängig machen.
Diesen Weg wählte ich für die Erweiterungen zur Klasse "ApplicationHandler". (Bei Erweiterungen ist aber die Ausgangssituation eine andere.)
Prinzip:
Code in der Hauptklasse:
Code in der Detailklasse:
Vorteil: Damit kann ich die Detailklassen nach Belieben durch andere ersetzen, die auf das gleiche Ereignis reagieren.
Riesiger Nachteil: Kein Early Binding und somit keine Absicherung durch den Compiler und natürlich auch kein IntelliSense. => Fehleranfällig!
Ein anderer Weg wäre mit Hilfe des Import-Assistenten:
Ja nach Bedarf kopiert man sich das gewünschte Code-Modul aus der Code-Bibliothek, dass dann in der Anwendung die Detailklasse darstellt.
Vorteil: Code ist eindeutig und man kann im Prinzip auch von der Hauptklasse in die Detailklasse verweisen, da sich für die Hauptklasse nichts ändert, da ja beim Import der Code in der Detailklasse geändert wird, die Detailklasse aber immer den gleichen Namen behält, auch wenn der Code der erweiterten Detailklasse entspricht.
Nachteil: man kann nur eine einzige Erweiterung einsetzen und nicht während der Laufzeit entscheiden, welche Klasse an die Schnittstelle übergeben werden soll.
Wie seht ihr das?
mfg
Josef
PS: Ich hoffe obiges ist einigermaßen verständlich beschrieben.
Aus Programmiersicht ist meiner Meinung nach die Variante mit der Schnittstelle die sauberste Lösung. Nur was hilft mir eine "saubere Lösung", wenn mir Access dann dauernd abschmiert. Bei der Anwendungserstellung dreh ich bei meinen Anwendungen daher die Implements-Anweisung immer ab und stelle auf Late Binding um, sobald die Klasse fertig programmiert ist.
Und wenn ich später nur eine einzige Detailklasse benötige, neige ich mittlerweile dazu, das über den Import-Assistenten zu regeln.
In diesem Thread möchte ich einmal versuchen herauszufinden, wie man abhängige Klassen am besten miteinander verbindet.
Gegeben sei folgende Grundstruktur:
- Hauptklasse
- DetailklasseABC
- DetailklasseXYZ
Beispiel:
Hauptklasse = Access.Application
Detailklasse = CurrentProject
Beispiel für Verwendung:
- Code: Alles auswählen
dim HK as Hauptklasse
HK.ABC.Machwas
Das könnte ich in der Hauptklasse so gestalten
- Code: Alles auswählen
private m_ABC as DetailklasseABC
Public Property get ABC() As DetailklasseABC
...
set ABC = m_ABC
End Property
Nachteil dieser Variante: man macht die Hauptklasse von der Detailklasse abhängig. Wenn ich nun die Detailklasse ABC durch eine andere Klasse "ABCerweitert" ersetzten will, ist das nicht mehr ganz so einfach. Ich muss dann auf jeden Fall in ABCerweitert als Schnittstelle die Klasse DetailklasseABC einbauen. ... und da beginnt dann das Problem bei Access: je mehr Schnittstellen eingebaut werden, desto höher ist die Wahrscheinlichkeit, dass der VBA-Binär-Code defekt wird - ohne regelmäßiges Decompile kracht es dann laufend während der Programmierung (zumindest nach meiner bisherigen Erfahrung).
Ein anderer Ansatz:
Nicht die Hauptklasse von der Detailklasse (bzw. einer Schnittstelle dieser Detailklassendefinition) abhängig machen, sondern die Detailklassen von der Hauptklasse abhängig machen.
Diesen Weg wählte ich für die Erweiterungen zur Klasse "ApplicationHandler". (Bei Erweiterungen ist aber die Ausgangssituation eine andere.)
Prinzip:
Code in der Hauptklasse:
- Code: Alles auswählen
Public Event DetailklasseAbcWoBistDu(ByRef Detailklasse as object)
Public Property get ABC() As Object
dim DetailklassenRef as Object
RaiseEvent DetailklasseAbcWoBistDu(DetailklassenRef)
set ABC = DetailklassenRef
End Property
Code in der Detailklasse:
- Code: Alles auswählen
private WithEvents m_Hauptklasse as Hauptklasse
Private Sub m_Hauptklasse_DetailklassebcWoBistDu(ByRef Detailklasse as object)
set Detailklasse = Me
end Sub
Vorteil: Damit kann ich die Detailklassen nach Belieben durch andere ersetzen, die auf das gleiche Ereignis reagieren.
Riesiger Nachteil: Kein Early Binding und somit keine Absicherung durch den Compiler und natürlich auch kein IntelliSense. => Fehleranfällig!
Ein anderer Weg wäre mit Hilfe des Import-Assistenten:
Ja nach Bedarf kopiert man sich das gewünschte Code-Modul aus der Code-Bibliothek, dass dann in der Anwendung die Detailklasse darstellt.
Vorteil: Code ist eindeutig und man kann im Prinzip auch von der Hauptklasse in die Detailklasse verweisen, da sich für die Hauptklasse nichts ändert, da ja beim Import der Code in der Detailklasse geändert wird, die Detailklasse aber immer den gleichen Namen behält, auch wenn der Code der erweiterten Detailklasse entspricht.
Nachteil: man kann nur eine einzige Erweiterung einsetzen und nicht während der Laufzeit entscheiden, welche Klasse an die Schnittstelle übergeben werden soll.
Wie seht ihr das?
mfg
Josef
PS: Ich hoffe obiges ist einigermaßen verständlich beschrieben.
Aus Programmiersicht ist meiner Meinung nach die Variante mit der Schnittstelle die sauberste Lösung. Nur was hilft mir eine "saubere Lösung", wenn mir Access dann dauernd abschmiert. Bei der Anwendungserstellung dreh ich bei meinen Anwendungen daher die Implements-Anweisung immer ab und stelle auf Late Binding um, sobald die Klasse fertig programmiert ist.
Und wenn ich später nur eine einzige Detailklasse benötige, neige ich mittlerweile dazu, das über den Import-Assistenten zu regeln.