Fragensteller
Interface Benutzung

Allgemeine Diskussion
-
Hallo,
Ich hab jetzt zwar schon gesucht , aber auf meine Frage keine passende Antwort gefunden.Ich bin grad im Bereich Interface Design und ich versteh auch das Prinzip und die Art und Weise wie Interfaces fuktionieren.
Hab auch in gewissen Praxisfällen schon mit gearbeitet.
(Plug In Prinzip über Dlls. ) .
--------------------------------------------------------------------------------------
Jetzt meine Frage :
In allen meinen Beispelen musste ich die Klassen explizit Instanzieren und einen Cast auf das Interface benutzen um auf diese zu zu greifen.
Standard Schnittstellen von Microsoft (zb. die IErrordatainfo) die implementiert man in seine Klasse und schon bindet die sich mit einem Objekt X , welches dann auf magische Weise darauf antwortet.
Jetzt mal Spaß beiseite , irgendwo muss meine Klasse , die dieses Interface besitzt doch gekoppelt werden , sonst würde niemand seine Events / Funktionsergebnisse etc. empfangen. Wo macht des das Studio und wie krieg ch das auch hin ?
Ich will nen Log schreiben undderzet wäre meine einzige Lösung eine Log Klasse zu schreiben , die global zu deklarieren und dann über eine Add Funktion jedes mal wenn ich nen objekt Instanziere dort einzulesen und zu verbinden.
Ich hab das Gefühl , dass es da eine elegantere Variante gibt. Die Theorie mit den Pattern hat mir auch net weitergeholfen , da für mich immernoch ein "magisches" Objekt existiert , welches sich auch Automatisch mit Instanzen ,die dessen Interface besitzen , verbindet .
Ich hoffe ich konnte mein Problem gut schildern.
mfg
Florian Veit
- Typ geändert Ionut DumaModerator Dienstag, 29. Oktober 2013 16:28 Diskussion
Alle Antworten
-
Hi,
ein Interface ist ein Vertrag, der sichert, dass der Nutzer das im Interface definierte bekommt bzw. nutzen kann. Der Bereitsteller muss alles implementieren, was im Vertrag / Interface deklariert ist.Der Nutzer bekommt ein Objekt - d.h. einen Verweis auf ein Objekt (in einer Verweisvariablen). Von welchem Typ (Klassenname) das Objekt instanziiert wurde, ist bei der Nutzung von Interfaces ohne Bedeutung. Die Laufzeitumgebung prüft zur Ausführungszeit, ob im Typ (=Klasse) des Objektes auch das Interface implementiert wurde. Wenn das der Fall ist, kommt kein Fehler und es kann alles genutzt werden, was im Interface deklariert wurde, auch wenn mit dem Objekt noch viel mehr gemacht werden könnte.
Es gibt keine "magischen" Objekte. Jedes Objekt muss im Laufe seines Lebens erstellt (instanziiert) werden, entweder man macht es selbst mittels "new" oder man bekommt das Objekt über eine Funktion (Methode mit Rückgabewert) geliefert. Oft wird ein Objekt (als Objektverweis) von Methoden statischer Objekte (Klassen) geliefert (in VB sind das Moduln) oder auch aus der Programmumgebung, die beim Start des Programmes implizit bereitgestellt wird.
Wenn es Dir um eine Kopplung geht, dann nutze im Programm eine statische Klasse (in VB ist das ein Module) mit Eigenschaften, die Verweise auf Objekte bereitstellen. Alle anderen Objekte im Programm können sich dann von der statischen Klasse die Verweise holen und damit gemeinsam auf die gleichen Objekte zugreifen.
Ich hoffe, ich habe Deine Frage richtig verstanden.
--
Peter -
Hallo Peter,
Nicht Ganz . Die ganze Vertragsgeschichte bei Interfaces ist mir (hoff ich doch ) komplett klar .
Es stellt nen Rumpf dar mit Events nd Funktionen . Man kann anhand der Interface deklaration Klassen auf diese Beschränken und sie somit allgemeingültig übergeben . Ich nehm mal die Assoziation mit dem Vertrag um mein Problem besser zu beschreiben :
Wenn ich zb. meine Klasse mit IDataError implementiere erstelle ich einen Klienten , der den Vertrag für IDataError unterschreibt.
Ich weiss zu dem Zeitpunkt aber doch gar nicht , wer sich an meiner Gegenstelle befindet.
Ich mein dem Klient kann es egal sein , Interface prinzip halt. Aber irgendwo in den Weiten des Quellcodes muss entweder ich oder das Studio dem Objekt , was die Funktionen und Events auswerten soll , eine Instanz des Interfaces meiner klasse geben (also , die , die das Interface implementiert hat)
Und da ist gerade mein Verständnis Problem. Ich persöhnlich weise da nichts zu , dass muss das Studio irgendwie wissen .
Ich komm mit dieser unbekannten Objektbindung nicht klar .
Es kann sein , das ichmich in der Vorstellung etwas verrannt habe , aber es muss doch eigtl. bei der Kommunikation mit 2 Objekten immer einen Sender und einen Empfänger geben. Woher weiss der ohne , dass ich es ihm je gesagt hab seinen Empfänger ? Muss ja irgendwie automatisch verknüpft werden .
mfg
Florian
-
Hi Florian,
Interface hat nichts mit Sender und Empfänger zu tun, auch nichts mit Master und Slave, auch nichts mit Server und Client. Demnach gibt es keine Gegenstelle im Sinne Sender / Empfänger.In einer Befehlsfolge gibt es Sprungbefehle, die, wenn sie nicht direkt verzweigen, eine Methode aufrufen. Im weitesten Sinne kann der Methodenaufruf eine Funktion (Methode mit Rückgabewert), eine Get- oder Set-Methode (Eigenschaft) oder einen Delegate-Aufruf (Ereignis) sein.
Die aufgerufene Methode kann in einem "fremden" Objekt liegen. Die Laufzeitumgebung (CLR) prüft dann, ob Absprung zum Sprungziel passt. Das ist aber nur möglich, wenn die CLR das prüfen kann, indem sie entweder den Typ (Klasse) kennt, in dem das Ziel deklariert ist, oder auch unabhängig vom Typ die Beschreibung kennt, in der das Ziel beschrieben ist. Und diese Beschreibung ist das Interface.
Eine Instanz eines Interfaces gibt es nicht. Es gibt nur eine Instanz eines Typs (=Klasse), der ein oder mehrere Interfaces implementieren kann.
Das Studio ist lediglich eine vorgelagerte CLR. Das bedeutet, dass bereits zur Entwurfs- und Übersetzungszeit geprüft wird, ob Aufrufer und Aufgerufener zusammenpassen.
Was Du unter Objektbindung verstehst, ist unklar. Auch gibt es keine automatische Bindung. Erzeugt werden müssen zuerst Objekt. Zu jedem Objekt gehört Programmcode, der das "Leben" des Objektes bestimmt. Und in diesem Code wird zu einem Unterprogramm gesprungen. Wenn sich dieses Unterprogramm in einem anderen Objekt befindet, muss es zur Laufzeit auch einen Objektverweis geben.
Wenn Du Deine Begriffswelt etwas präziser wählst, wirst Du auch weniger Verständnisprobleme haben.
--
Peter -
Also, wenn ihr von den selben Interfaces redet, die ich mir bei dem ganzen Vertragsbrei jetzt vorstelle, dann würde ich vorschlagen, dass wir uns von der Analogie mit dem Vertrag mal verabschieden, da (wie richtig festgestellt) das einen Vertragspartner vermuten lässt.
Nehmen wir eher an, ein Interface ist eine Schnittstelle. Solange ein Objekt diese Schnittstelle fehlerfrei implementiert, kann man sichergehen, dass alle Methoden/Eigenschaften, die das Interface zusichert, auch erfüllt sind. Wenn ich also beispielsweise in einer Methode A(B as String) im Kopf stehen habe, übergebe ich einen String ... mit all den stringtypischen Eigenschaften, z.B. dem Index, um auf einzelne Zeichen zuzugreifen. Wenn ich A(B as IMeinInterface) verwende, dann muss das übergebene Objekt - und hier ist es nun völlig Wurst, wie es sonst aussieht, ob es ein Bild, ein Control, oder was ganz abgefahrenes ist - diese Schnittstelle implementieren, also MINDESTENS all das können, was im Interface vorgeschrieben ist.
Aber da weiß weder das Interface von dem konkreten Objekt, noch andersherum. Das Interface ist ja abstrakt, quasi wie eine Wolke um alle Objekte jeder Art und Ausprägung herum, die irgendwie dieses Interface implementieren. Eine Art "Gemeinsamkeit" aller Objekte in der Wolke. Was sie außerdem noch können, welches andere Interface sie vielleicht noch implementieren, ist in dem Moment völlig ohne Belang. Alles ist möglich.
LG, Dennis.
EDI Consultant/Developer
Ich nutze meistens VB6 und VS2005 bis VS2012
Bitte die Antworten sowie weitere hilfreiche Beiträge von Mitgliedern markieren. Vielen Dank.
- Bearbeitet Dennis Becker Dienstag, 15. Oktober 2013 12:42 Wortfehler
-
Hallo,
ich habe Florians Frage vollkommen anders verstanden.Hier erstmal mein Code, auf den ich mich beziehe:
Module Module1 Sub Main() Dim c1 As New Class1() Console.WriteLine(c1.GetName())'Geht Problemlos Dim c2 As New Class2() Console.WriteLine(c2.GetName())'Geht nicht Problemlos, es wird ein Cast erwartet um auf den Schnittstellen-Member zugreifen zu können. Dim c2_i As ISchnittstelle = CType(c2, ISchnittstelle) Console.WriteLine(c2_i.GetName()) 'Geht wiederum End Sub End Module Interface ISchnittstelle Function GetName() As String End Interface Class Class1 Implements ISchnittstelle 'implizit implementiert Public Function GetName() As String Implements ISchnittstelle.GetName Return "Class1" End Function End Class Class Class2 Implements ISchnittstelle 'Explizit implementiert Private Function ISchnittstelle_GetName() As String Implements ISchnittstelle.GetName Return "Class2" End Function End Class
Die Klasse 1 verhält sich wie die meisten anderen, Schnittstellen-Implementierenden, Klassen auch. Man kann einfach auf die Schnittstellen-Member zugreifen.
In Class2 dagegen kann man nicht darauf zugreifen, weil die Schnittstelle explizit implementiert ist.
Sollte ich deine Frage falsch verstanden haben, dann hier noch ein Beispiel, wofür man Schnittstellen gebrauchen kann.
Sub DoSome(value As ISchnittstelle) Console.WriteLine(value.GetName()) End Sub
Beim Aufruf von DoSome() wird der zurück gegebene Wert ausgegeben. Unabhängig ob das Übergebene Objekt vom Typ Class1 oder Class2 ist.
Sobald du Class1 (bzw. Class2) instanzierst, sind auch alle Member von ISchnittstelle abrufbar. Darum funktioniert das Casten und Aufrufen auch so Problemlos.
PS: Kannst du vielleicht einen kleinen Beispielcode posten, anhand dem du uns dein Problem nochmal näher erklärst?
Koopakiller [kuːpakɪllɐ] (Tom Lambert)
Webseite |
Code Beispiele |
Facebook |
Twitter |
Snippets
C# ↔ VB.NET Konverter
Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.- Bearbeitet Tom Lambert (Koopakiller)Moderator Dienstag, 15. Oktober 2013 13:04 PS
-
Hallo,
Präzise Begriffswelt ist immer ein toll gesagt. Seit ich mit WPF angefangen hab bezweifle ich manchmal ob Microsoft selbst noch weiss welcher Begriff welche Bedeutung haben soll.... . Aber anderes Thema.
Das mit der Instanzierung kam hierdurch :
Public sub Add(byval Interface as ITest)
' Innerhalb dieser Routine ist das Objekt für nicht das Objekt der Ursprungsklasse
' Es ist aber auch kein statisches Objekt' Für mich war das immer die Instanz der Objektes ITest , welches bei der Instanzierung der Klasse , zu der es gehört , erzeugt wurde
End Sub
Wir reden immernoch aneinander vorbei , denk ich .
Mein Problem bezieht sich nichtauf die Deklaration des Interfaces , sondern auf den Zugriff während der Laufzeit.
Nehemn wir als Beispiel die IDataErrorInfo
Objekt A = Das Objekt , um welches mir hier geht . Dies empfängt die Error Nachricht
Objekt B = Mein Objekt , welches ich mit IDataErrorInfo implementiert habe
Ohne das ich Objekt A aber jemals gesagt habe (weil ichs net kenne ) das es Funktion von meinen Objekt B aufrufen soll , empfängt es fröhlich die Fehler .
Wenn ich diesen Ganzen tutorials und MSDN How To's glauben schenken darf.
mir Fehlt der Teil wo A kenntnis von B erhält .
Ich bin nicht mehr bei , was ein interface macht , sondern bei "warum zum Teufel brauch ich das nur implementieren und dann läuft das " . Wenn ich Ihn zb. wie oben mit nen Add Befehl irgendwo eintragen lasse , wär alles kein Problem .Ich les aber immer nur , "Da implementierste des und des Interface und dann geht das " .
Ich mein Objekt A dürfte doch neimals auf ein Event (Eins was im Interface steht) steht reagieren , wenn ihm nicht mal irgendwer mit zb. nen Addhandler das Event von Objekt B zuweist.
Ich les immer nur " Implementiere das " und dann geht das aufeinmal . Wann , wo und wie , kriegt dieses A mit das es B gibt ?
Vllt. Steh ich auch voll auf dem Schlauch und hab mich gute 200 mal verlesen.
-
Grundsätzlich hast du eigentlich recht. A kennt B nicht. A kennt nur die Schnittstelle und damit das was B garantiert hat.
Die IDataErrorInfo-Schnittstelle hat 2 Eigenschaften. (Siehe MSDN)
B implementiert diese beiden Eigenschaften.
Nun bekommt A ein Objekt, welches die Schnittstelle implementiert. A hat keine Ahnung was B noch alles enthält (A weiß nicht einmal ob es B erhält oder vielleicht D oder etwas ganz anderes), aber die Schnittstellen-Eigenschaften sind da. Das steht fest.Also kann A seine Arbeit tun, weil nur Error und Item benötigt werden. Und genau das stellt B bereit. (Durch die Schnittstelle sicher gestellt.)
Koopakiller [kuːpakɪllɐ] (Tom Lambert)
Webseite |
Code Beispiele |
Facebook |
Twitter |
Snippets
C# ↔ VB.NET Konverter
Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke. -
Genau wir sind schon nah dran , das A nur kenntnisse vom Interface hat ist mir klar.
"Nun bekommt A ein Objekt, welches die Schnittstelle implementiert. " jetzt bin ich beim Wo.
Das ist genau der Punkt . Wo bekommt A das übergeben.
Ich übergebe A nirgendwo das "Interface Objekt" von B und trotzdem kann A auf die beiden Eigenschaften reagieren.
-
An irgendeiner Stelle erhält A "das Objekt" (hier B).
Nun ist die Frage, was A ist. Je nach dem lernt A dann B kennen. IDataErrorInfo ist da für meinen Geschmack ein zuvielseitig anwendbares Beispiel.
Mal als ein einfaches Beispiel mit einem ValueConverter und der IValueConverter-Schnittstelle. Der Konverter implementiert die Schnittstelle. Somit steht fest, das es die Methoden Convert und ConvertBack gibt.
Nun wird der Konverter instanziert und in der Bindung zwischen Ziel und Eigenschaft gehängt. Somit bekommt das Binding-Objekt den Konverter und weiß auch nur, das IValueConverter implementiert ist. Mehr ist der Bindung auch nicht bekannt.In diesem Beispiel wird dem Objekt der Konverter direkt übergeben. In ähnlicher Weiße geschiet es auch bei anderen Schnittstellen.
Koopakiller [kuːpakɪllɐ] (Tom Lambert)
Webseite |
Code Beispiele |
Facebook |
Twitter |
Snippets
C# ↔ VB.NET Konverter
Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke. -
Guten Morgen Koopakiller,
Ja nu beim Beispiel IDatErrorInfo weiss ich ja selber nicht , was A istbzw. wusste nichtmal dessen Existenz .
Aber genau diesen Ansatz will ich dahinter verstehen. Ich will ne Log Klasse schreiben und derzeit müsst ich ja alle Elemente die mein Ilog implementiert haben in die Log Klasse eintragen , damit diese dann Events des Ilog interfaces handlen kann.
Dies setzt aber entweder vorraus das die Log Klasse Global ist und jedes Element zu jeder Zeit darauf zugreifen kann ( da der Zeitpunkt der Instanzierung für die Klassen , die ILog benutzen unbekannt sein kann)
Mir fehlt irgendwie ne gute Kapselung , dass man das Ilog Interface auch nutzen kann , ohne das eine globable Log Klasse vorhanden sein muss.
Ich dachte , dass ich die Art und Weise wie IDataErrorInfo das macht selbst nutzen kann.
"Ich muss das Interfce nur in der Klasse implemnetieren und der rest geht automatisch" -
Hi Florian,
allein durch das Einfügen (Implementation) eines Interfaces passiert überhaupt noch nichts.Notwendig ist, dass Nutzer der Objekte auch die Methoden aufrufen, die im Interface deklariert sind. Häufig fragen die Nutzer (aufrufende Objekte), ob ein bestimmtes Interface implementiert ist. Wenn das Interface nicht implementiert ist, wird einfach nichts gemacht.
Wenn Du also Dein ILog deklarierst und auch in einigen Klassen implementierst, dann musst Du auch in den Klassen, die mit Objekten vom betreffenden Typ (Klasse mit ILog) arbeiten, die entsprechenden Prüfungen und Aufrufe einbauen.
--
Peter -
Naja ich hab jetzt ne teilweise One Way Lösung gebastelt , ich schau grad wie ich den Rückweg bekomme :
Public Class Log
Public Function Register(ByVal Obj As Object) As Boolean
Try
Dim IObj As ILog = CType(Obj, ILog)
AddHandler IObj.Write, AddressOf WriteLog
AddHandler IObj.Register, AddressOf Register
Catch ex As Exception : End Try
Return True
End Function
Private Sub WriteLog(ByVal LogText As String, ByVal Priorität As IAppCenter.Info)
Console.WriteLine("Träger : " & LogText)
End Sub
End ClassPublic Interface ILog
Event Write(ByVal LogText As String, ByVal Priority As Info)
Event Register(ByVal Obj As Object)
Event Unregister(ByVal Obj As Object)
End InterfaceIm Hauptprogramm erstell ich eine Instnz der Klasse Log und registrier (alle Objekte die diese Schnittstelle haben) alle Objekte auf dieser Ebene .
Ich muss in den tieferen Ebenen nur noch die Schnittstelle implementieren und bei der Instanzierung von Objekten innerhalb der Klasse , diese registrieren .
Was mir jetzt noch fehlt ist ne Möglichkeit das ich auch Werte zurückkriegen kann (Hm Evtl. ein Parent Property , welches aufgerufen werden kann) .
Wenn ich es schaffen würde dieses "RaiseEvent Register()" automatisch aufrufen zu lassen bei jeder Instanzirung eines Objektes , dann wäre das System vollautomatisch .
- Bearbeitet Florian Veit Mittwoch, 16. Oktober 2013 12:43
-
Hier noch die etwas unausgereifte Version mit überagabe Werten
Public Interface ISetting
Event Register(ByVal Obj As Object) 'Registriert
Event Unregister(ByVal Obj As Object)
Property Setting As ISetting ' Gibt das Interface der späteren Setting Klasse zurück
Function GetValue(ByVal ObjName As String) ' Im späteren Interface der Setting klasse sind dann SetValue
Sub SetValue(ByVal ObjName As String, ByVal Value As Object) ' Und getValue in der Lage zu verarbeiten
End InterfacePublic Class SettingsNeu
Implements ISetting
Public Function Register(ByVal Obj As Object) As Boolean
Try
Dim IObj As ISetting = CType(Obj, ISetting)
AddHandler IObj.Register, AddressOf Register
IObj.Setting = CType(Me, ISetting)
Catch ex As Exception : End Try
Return True
End Function
Public Function GetValue(ObjName As String) As Object Implements ISetting.GetValue
Return "Hallo"
End Function
Public Event Register1(Obj As Object) Implements ISetting.Register
Public Property Setting As ISetting Implements ISetting.Setting
Get
Return Nothing
End Get
Set(value As ISetting)
End Set
End Property
Public Sub SetValue(ObjName As String, Value As Object) Implements ISetting.SetValue
End Sub
Public Event Unregister(Obj As Object) Implements ISetting.Unregister
End Class
Hat bis jetzt immer noch den Nachgeschmack , das ich Routinen implementiere , die ich nur an einer Stelle brauche(SetValue , GetValue) . Dafür ist das Interface aber unabhängig gegenüber andere Interfaces
-
Hi Florian,
ich habe immer noch nicht verstanden, was Du erreichen willst. Deine Codeabschnitte sind da auch nicht hilfreich.Schreib mal, was Du erreichen willst. Wenn Du mit Interfaces arbeiten willst, dann schreibe mal, was die aufrufende Klasse mit den Objekten machen soll, die das Interface implementieren.
--
Peter -
Ich mach mal Anhand des Ilog ein Beispiel:
Class Main
---------------------------------------------------------
Private Log as new Log private obj as new Class2 public sub new() log.register(obj) end sub End ClassClass Class2 Implements Ilog private obj as new Class3 public sub new() RaiseEvent Register(obj) End Sub private Sub DoSomething() RaiseEvent Write("Test") End Sub Event Write(ByVal LogText As String, ByVal Priority As Info) Event Register(ByVal Obj As Object) Event Unregister(ByVal Obj As Object) End Class
------------------------------------------------------------------------------------------------------------------Class Class3 Implements Ilog
---------------------------------------------------------------------------------------------------------------------
public sub new() End Sub
private Sub DoSomething() RaiseEvent Write("Test") End Sub
Event Write(ByVal LogText As String, ByVal Priority As Info)
Event Register(ByVal Obj As Object)
Event Unregister(ByVal Obj As Object) End ClassJeder dieser 3 Klassen kann auf Funktionen der Klasse Log zugreifen, aber nur die Main weiss überhaupt das es Log gibt. Alle anderen Klassen können Dank dem Interface neue Elemente registrieren , ohne überhupt zu wissen wo oder bei wem. Jetzt klar was diese konstellation macht ? Ich kann jetzt innerhalb der Klassen Class2 und Class3 jedes beliebige Element dort registrieren und muss nichtml wissen ob des Ilog implementiert hat.
Im zweiten Beispiel benutz ich das System um auch Daten zurück geben zu könnnen.
Ich weiss nur net ob mein System Klug oder einfach nur su kompliziert ist , weils da schon was gibt .
- Bearbeitet Tom Lambert (Koopakiller)Moderator Mittwoch, 16. Oktober 2013 19:50 Code formatiert
-
Hi Florin,
wenn du folgende Regist Methode verwendest kannst du nicht alle Klassen nutzen.
Public Function Register(ByVal Obj As Object) As Boolean Try Dim IObj As ILog = CType(Obj, ILog) AddHandler IObj.Write, AddressOf WriteLog AddHandler IObj.Register, AddressOf Register Catch ex As Exception : End Try Return True End Function
Alle Klassen die du verwenden willst müssen das ILog Interface implementieren, sonst wirft CType eine Exeption. Nur weil du einfach alle Exeptions abfängst (sollte man nicht machen) und true zurück gibst heist das noch nicht das die Funktion auch das macht was sie soll.
Und z.B. ein Auto sollte kein Interface ILogger Implementieren, da es einfach nichts mit Loggen zu tun hat.
Wenn du einen Logger schreiben willst kann man sich im Internet viele Beispiele ansehen wie man so was machen kann wie z.b. bei log4net, dort kannst du auch den Quellcode finden.
Hier mal ein einfaches Beispiel wie/wozu man Interfaces Benutzt. Grob gesagt Klassen die ein Interface implementieren, mit denen wird etwas gemacht, eine andere Klasse ruft die Methode auf. Wobei der anderen Klasse die Entgültige implementierung egal ist. Bei deinen Logger wäre es wohl SchreibeDaten, ob der Logger jetzt die Daten auf die Festplatte schreibt oder in eine Datenbank, das ist den aufrufer egal.
Wenn deine Klasse Daten an eine andere Klasse senden soll (oder besser Methoden ausführen soll), die sie zur zeit der Implementierung nicht kennen kann benutzt man ein Event (z.B. Button Click, der die Klasse Button geschrieben hatt kann einfach nicht wissen was du machen möchtest wenn der Button gecklickt wird.
MFG
Björn
-
gut dann nehm ich statt try Catch , Is Type Of . Ging mir grad nur um die Veranschaulichung.
Nunja , das Beispiel Log4Net setzt dann aber vorraus , das man das immer mit einbindet (habs nur kurz überflogen , schande über mein Haupt wenn ich mich verlesen habe).
Vorteil meiner Konstruktion ist , dass sie ohne wissen über die Log Klasse arbeiten kann. Ich könnte das Ilog auch in ner Auslagerungs DLL implementieren und das würde nochfunktionieren. Nachteil ist , dass dieses Konstrukt ne Baumstruktur hat. Wenn ich nicht alle Knoten durchgehend mit Ilog implementiere , dann können weitere Kettenmitglieder nicht mit angebunden werden.
Für einfache Anwendungen sind diese Beispiele doch schön und gut ,aber für ne professionelle Lösung muss von der Architektur noch ein wenig mehr her. Ich will zb. ein paar Klassen , die Ilog implementieren , so wie sie sind , in anderen Projekten anwenden können. Da hilfts mir nicht wenn in dieser Klasse auf Klassen wie zb. God (siehe einfaches Beispiel) verwiesen werden muss . Die Lösung einer globalen Log Klasse , auf die alle zugreifen hilft hier also nicht. Ich könnte die Klasse in einem Projekt , wo diese Log Klasse fehlt oder anders existiert gar nicht mehr verwendet.
-
Bei deiner Lösung must du in allen Klassen und dlls Einmal das Interface einbinden und jede Klasse muss das Interface implementieren. Du hast also bei weiten mehr Abhänigkeiten.
Log4Net habe ich überigens schon in professionellen Lösungen eingesetzt. Es werden oft Bibiliotheken von 3 Anbietern verwendet damit nicht alles selbst Programmiert werden muss und die Kosten sinken.
Hier bitet sich dann aber auch an die 3. Anbieterkomponenten hinter ein Adapter wegzukappseln.
Bei eine Logger könnte man ein Interface bereitstellen (welches nur die nötigsten Funktionen hat) und den Logger über eine Factory Klasse erzeugen lassen. Die Klassen in denen du loggen möchtest, kennen dann nur dein Interface und die Factory Klasse, damit kannst du jederzeit den Logger austauschen.
Es sollte überigens auch nicht in jeder Klasse und Methode geloggt werden, da das Loggen meist mit einem Zugriff auf das Dateisystem verbunden ist und somit zu den Langsamst Operationen gehört.
Zu eine guten Software Architektur gehört es auch grundlegende Prinzipien wie KISS und YAGNI einzuhalten. Haltes einfach so das es jeder Verwstehen kann, erfinde dsa Rad nicht neu und Implementier nichts was du nicht wirklich brauchst. Auch wenn du denkst das es sicher noch gebraucht wird, es später zu implementieren dauert genau solange.
MFG
Björn
-
Wohl Wahr ,
Ich muss aber auch sagen , das ich wenig Lektüre zum Thema gute Software Archiketur finde. Theorie ja , aber bei der praktischen Umsetzung haperts dann. HAb das System von mir heut noch bissle abgeändert ^^ statt nen Property von dem Interface hab ich zb. Delegate Properties benutzt .Was ich in das System nicht gekoppelt bekomme sind Events . Also von aussen in eine Klasse rein.
Was ich da fabriziert hab gefällt mir irgendwie , ich weiss es ist noch nicht ganz sauber , aber der Ansatz gefällt mir . Ich konnte heute an vier Baustellen die Klassen fertig schreiben , ohne das auch nur das Schreiben der Setting Klasse fertig war. Das hab ich dann später eingebaut und es ging alles so wie es sollte .
Gibts vom MSDN eigtl. irgendwo tipps zum Thema "professionelle Programmierung" ? Ich frag das , weils mir wahrscheinlich viele Forenfragen ersparen könnte . Ich mein bei WPF ist mit den Bindings , der Trennung zu XAML und Interfaces so viel möglich und uch soviele möglichkeiten es ineffektiv zu machen . Ich würd Wpf gern profesionell starten . Winforms war bei mir , den umständen entsprochen , eher bissle holprig .
-
Hi
Bücher gibt es schon einige auch von Microsoft (Press), z.B. Code Complied zum Thema professionelle Programmierung. In dem Buch werden alle wichtigen Themen behandelt, mir fällt auf jeden fall nichts ein was nicht behandelt wird. Was die tiefe angeht gibt es sicher Bücher die mehr ins Detail gehen, dafür aber nicht die breite Abdecken.
Ein klassiker in dem rahmen ist dann noch Clean Code, daraus hat sich im Prinzip eine ganze bewegung entwickelt.
Für Software Architektur gibt es den Klassiker Entwurfsmuster von der Gang of Four (GoF), lohnt sich auf jeden Fall. Gute kenntnise in der OOP solte man aber haben.
Ein paar andere Bücher würde mir Spontan noch einfallen, aber ich denke die genanten sind ein guter einstieg. Damit hast du aber schon mal was zu lesen.
Da ich gerade im Hotel bin und die Internet anbindung ist unterirdisch ist, hab ich jetzt mal keine Links zu den Büchern rausgesucht. (Amazon bekommt einen Timeout). Ich denke aber, dass du das selbst hinbekommst.
Die SOLID Prinzipien kannst du die auch mal anschauen. Auf diese wird in vielen Büchern und Artikel verwiesen.
Was deinen Logger angeht, da ihn jede Klasse Implementieren muss damit es Funktioniert haben alle Klassen die Anhänigkeit. Wenn du jetzt feststellst das es doch anders implementiert werden muss weil ein anders Problem so nicht gelöst werden kann. Kannst du im Prinzip deinen ganzen Quellcode wegschmeißen.
Man sollte immer die Anhänigkeiten so gering wie möglich halten.
Aber um die Möglickeiten der OOP auszuprobiern und zu testen was geht, ist es schon ok.
MFG
Björn