Announcement

Collapse
No announcement yet.

C# Mehrere Projekte | Eine Kontainerklasse (Architektur)

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • C# Mehrere Projekte | Eine Kontainerklasse (Architektur)

    Hi!

    Heute eine Architektur anliegen.

    Folgendes (virtuelles) Szenario:
    Man nehme an ich habe eine Solution mit sagen wir 3 Projekten.

    Projekt 1: Hat die Aufgabe von irgendwoher (sagen wir einer Datenbank) Daten auszulesen, und über Events (wenn diese denn Abonniert sind) anderen Teilprogrammen die Ausgelesenen Informationen zur Verfügung zu stellen.
    Projekt 2: Abonniert die in Projekt 1 zur Verfügung gestellten Events und präsentiert die auf irgendeine Weise dem User. (Sagen wir durch ein Formular)
    Projekt 3: Der User hat nun durch das Formular die Möglichkeit die präsentierten Daten zu ergänzen etc. Und diese über Projekt 3 irgendwo anders hinzuspeichern. (Sagen wir am Filesystem)

    Vorweg die Sinnhaftigkeit des oben beschriebenen Programmes sei dahingestellt. (Nur ein Beispiel)

    Ich benötige nun irgendeine Art von Kontainerklasse mit der ich die nötigen Daten kapsle.
    Zum Beispiel sowas:

    public struct Person {
    public string Nachname;
    public string Vorname;
    }

    Somit habe ich die Möglichkeit Objekte(oder Strukturen) vom Typ Person zwischen Projekt 1, Projekt 2 und Projekt 3 hin und her zu schieben.


    Nun aber meine Frage (und ich hoffe man kann mein Beispiel verstehen) wie macht man das richtig, also wie sollte man das machen um auch Konzepten wie der Losen Koppelung zu entsprechen?
    Bei dem oben gezeigten Beispiel müsste ich ja das Projekt in dem sich die Definition der gezeigten Kontainerklasse befindet, an alle anderen als Referenz übergeben, diese Projekte sind sozusagen voneinander abhängig.



    Gerne versuche ich das noch etwas genauer zu Beschreiben sollte man nicht verstehen was ich haben will


    mit freundlichen Grüßen

    BaDo

  • #2
    Das übliche wären weitere reine Interface Projekte hinzuzunehmen. Will sagen in deinem Projekt 1 werden ja vermutlich irgendwelche Klassen veröffentlicht über die man Daten anfordern kann. Also wirst du zu Projekt1 noch ein Interface Project erzeugen das die Beschreibungen der Oberflächen der veröffentlichten Klassen in Projekt 1 enthält (also Interfaces) und die Datenklassen die man über diese Interfaces erhalten kann. Und ich meine Klassen (POCO Klassen die möglichst nur Daten enthalten und keine weitere Abhängigkeiten). Structs zu nehmen ist innerhalb von .Net in 99% aller Fälle falsch. Die sind hier nicht schneller, platzsparender oder was auch immer. Die haben nur eine andere Zuweisungssemantik. Die Klassen in Project 2 sollten also dann auch so geschrieben sein das sie nur gegen die Klassen und Interfaces aus dem Project 1 Interface Project arbeiten. Das Unterfüttern der Interface mit konkreten Klassen aus Project 1 würde dann eine System basierend auf einem der üblichen Factory Patterns übernehmen. Wo du das unterbringst, hängt dann ein wenig von der Wahl des konkreten Patterns ab. Das Ziel wäre also das jedes Project das Daten aus Project 1 braucht nur das dazugehörende Interface Project referenziert (das so simples gestrickt ist das jeder es referenzieren darf) aber nicht Project 1 selbst und dazu das Project das die Factory enthält. So hast du deine lose Kopplung erreicht und kannst die Implementierung von Project 1 autauschen ohne das andere betroffen sind (ok die Factory müßte vielleicht umkonfiguriert/angepaßt werden).

    Comment


    • #3
      Hi,

      und erstmal danke für die schnelle Antwort.
      Ja das mit den Interfaces habe ich auch schon gelesen und mir überlegt. Ich fände die Idee auch super, allerdings glaube ich doch zu wissen das man in .Net Interfaces keine Fields einfügen kann oder?

      Also etwas wie das folgende ist meines Wissens nicht möglich:

      public Interface IPerson {
      public string Nachname;
      public string Vorname;
      }


      Und so bringt mir das ja dann nix, also wenn ich nur Methoden im Interface kapseln kann, weil ich habe ja keine Methoden
      Könnte dann natürlich in Projekt 1 das Interface auch konkret Implementieren, bringt mir aber nichts weil ich dann ja ohne Cast auf etwas das ich dann erst wieder erfragen muss auf die Daten zugreifen kann.

      So in etwa:

      PROJEKT1#

      public Interface IPerson {
      }

      public class cPerson : IPerson {
      public string Name;
      }

      public class Controller{
      public static IPerson GetPerson() {
      return new cPerson();
      }
      }


      PROJEKT2#

      void main {

      Console.WriteLine(PROJEKT1.Controller.GetPerson(). Name); //Fehler Hier da Name Teil der Klasse nicht des Interfaces ist. Mit Cast wohl machbar aber dann komisch

      }



      Sehe ich da was falsch?


      lg

      Comment


      • #4
        Das ist jetzt wirklich keine leichte Frage, denn das hängt stark von der Architektur der restlichen Applikation ab. Sofern die einzelnen Projekte tatsächlich eigenständig Applikation sind, würde ich diese über (Web-)Services entkoppeln. Hier kann man sich noch die Frage stellen ob es Sinn macht ein Client Projekt zu erstellen. Generell sollte ein Client für einen Webservice allerdings trivial sein und kann meines Erachtens nach auch kopiert werden. Von Interfaces teilen halte ich an dieser Stelle nicht sehr viel, denn der Webservice gibt ja die Schnittstelle vor. Der Code Teil dazu hilft dann eigentlich nur beim de-/serialisieren. Gefährlich sind dann vor allem Updates und potenzielle Versionsunterschiede.

        Bewegt sich das alles immer innerhalb eines Projekts was immer in einem Stück gebaut und ausgeliefert wird, dann könnte man allerdings auch eine geteilte Dll verwenden. Alle Projekte verwenden dann immer dieselbe Version der Dll und müssen dementsprechend auch alle upgedatet werden.

        Zum generellen Thema DRY Prinzip: Man sollte nicht auf biegen und brechen versuchen kein Stückchen Code doppelt zu schreiben. Oft wird der Code gerade deswegen so super generisch, dass er viel schwerer zu verstehen ist als wie wenn ich einfach ein kleines Stückchen Code kopiert hätte. Ausserdem sollte man auch versuchen die Anwendung erst gar nicht so groß werden zu lassen dass man sich viele Gedanken über Code machen muss der geteilt werden soll. In der Arbeit sind wir auch gerade dabei die Anwendung in abgetrennte Teile zu zerschneiden die im Endeffekt nur über URLs miteinander kommunizieren. Dort gibt es mit Sicherheit auch eine Stückchen Data Access Code der doppelt. Typischerweise ist dieser Code allerdings trivial und wenig fehleranfällig.

        Comment


        • #5
          Und so bringt mir das ja dann nix, also wenn ich nur Methoden im Interface kapseln kann, weil ich habe ja keine Methoden
          Man benutzt ja auch keine Felder direkt sondern Properties und die kann man natürlich in das Interface aufnehmen.
          Für deine Datenklasse wäre ein Interface höchstwahrscheinlich eh überflüssiger Overhead. Mit loser Kopplung kann man es auch übertreiben.

          Dein Controller sollte eine Interface sein. In deiner gezeigten Main Methode greifst du ja so auch wieder auf Projekt1 zu was du direkt ja nicht solltest.

          Das

          Code:
          Console.WriteLine(PROJEKT1.Controller.GetPerson().  Name);     //Fehler  Hier da Name Teil der Klasse nicht des Interfaces ist. Mit Cast wohl  machbar aber dann komisch :)
          sollte also eher

          Code:
          IController controller = PROJEKT1Interface.Factory.GetConcreteController();
          Console.WriteLine(controller.GetPerson().Name);
          aussehen. Wobei die genauen Details davon abhängen was für eine Art von Factory du möchtest. Aus dem bißchen was ich hier zwischen den Zeilen lese würde ich mich wohl am Service Locator Pattern orientieren.

          Comment


          • #6
            Ha, ja genau das macht mehr Sinn
            Und auf Properties in den Interfaces hätte ich eigentlich auch kommen können ...
            (Hust Hust DÄMLICH ^^)

            Danke euch beiden vielmals, so gefällt mir das.

            Comment

            Working...
            X