none
Interface Benutzung RRS feed

  • 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

    Dienstag, 15. Oktober 2013 07:46

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

    Dienstag, 15. Oktober 2013 08:20
  • 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

    Dienstag, 15. Oktober 2013 08:40
  • 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

    Dienstag, 15. Oktober 2013 12:33
  • 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
    Dienstag, 15. Oktober 2013 12:39
  • 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.


    Dienstag, 15. Oktober 2013 13:02
    Moderator

  • 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.

    Dienstag, 15. Oktober 2013 13:59
  • 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.

    Dienstag, 15. Oktober 2013 14:10
    Moderator
  • 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.


    Dienstag, 15. Oktober 2013 14:18
  • 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.

    Dienstag, 15. Oktober 2013 14:52
    Moderator
  • 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"

    Mittwoch, 16. Oktober 2013 07:14
  • 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

    Mittwoch, 16. Oktober 2013 11:49
  • 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 Class

    Public 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 Interface

    Im 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 .


    Mittwoch, 16. Oktober 2013 12:42
  • 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 Interface

    Public 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


    Mittwoch, 16. Oktober 2013 13:23
  • 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

    Mittwoch, 16. Oktober 2013 18:03
  • 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 Class
    ---------------------------------------------------------
    Class 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 Class
    ---------------------------------------------------------------------------------------------------------------------

    Jeder 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 .


    Mittwoch, 16. Oktober 2013 19:47
  • 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 

    Mittwoch, 16. Oktober 2013 21:50
  • 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.

    Donnerstag, 17. Oktober 2013 07:32
  • 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

    Donnerstag, 17. Oktober 2013 17:54
  • 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 .

    Donnerstag, 17. Oktober 2013 19:35
  • 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

     

    Donnerstag, 17. Oktober 2013 20:55