Laden...

Code aus Klasse ausgliedern

Erstellt von adhome vor 4 Jahren Letzter Beitrag vor 4 Jahren 1.513 Views
A
adhome Themenstarter:in
3 Beiträge seit 2020
vor 4 Jahren
Code aus Klasse ausgliedern

Hallo,

ich hab mal eine Verständnisfrage zum Objektorientiertem Programmieren.
Vielleicht fehlt mir auch eine Technik.

Ich habe eine Klasse "Class1". Diese hat Member Variablen wie "mVar1" die von der aufrufenden Instanz initialisiert wurden und mit der nun die Klasse rumrechnen soll.
Es gibt aber viel Code und tausende Unterfunktionen und die Klasse wird sehr lang.
Ich dachte die vielen Unterfunktionen in Module auszulagern.
Nur wie greife ich nun von den Unterfunktionen in den Modulen auf die Variable mVar1 zu ohne die Objektinstanz umständlich immer weiter runter (tiefer) zu führen.

Kenne "Partial" womit ich die Klasse auf mehrere Dateien aufteilen kann.

Falls ich Klassen statt Module verwenden sollte, wie greife ich dort auf mVar1 besten zu?
Ich vermute mit runter reichen oder so.... Sieht aber alles recht umständlich aus.

Danke (;

16.806 Beiträge seit 2008
vor 4 Jahren

Hallo.

Diese hat Member Variablen wie "mVar1" die von der aufrufenden Instanz initialisiert wurden und mit der nun die Klasse rumrechnen soll.

Bitte keine Angewohnheiten aus anderen Sprachen in C# mitnehmen; das endet meist unglücklich.
In C# haben Variablennamen weder den Typ noch den Zugriffscontext enthalten.
"mVar" ist also fehl am Platz.

Siehe auch [Artikel] C#: Richtlinien für die Namensvergabe
Die ganze Community von C# orientiert sich weltweit an den Richtlinien von C#.
Es ist daher sehr praktisch und macht auch die Zusammenarbeit viel einfacher.

Daher bitte nimm nichts spezifisches aus C++ oder Delphi etc mit.

Es gibt aber viel Code und tausende Unterfunktionen und die Klasse wird sehr lang.
Ich dachte die vielen Unterfunktionen in Module auszulagern.

Auch hier; bitte nicht die Wege von anderen Sprachen 1:1 blind übernehmen.

Es bleibt Dir prinzipiell nichts anderes übrig als Dich mit OOP und den C# Sprachwerk zu beschäftigen.
Deine Fragen können im Prinzip nicht so einfach pauschal beantwortet werden.

Viel eher solltest Du Dich an Pattern und Prinzipien halten; zB KISS.
Es gibt keine Regel die besagt "ab 57 Zeilen musst Du die Klasse oder Methode splitten".

Kenne "Partial" womit ich die Klasse auf mehrere Dateien aufteilen kann.

Wenn Du partial wegen der Größe von Dateien verwendest, dann machst Du was falsch.
Der Urpsrung besteht darin, dass zB mit DSL-Tools wie T4 man C# Code generieren kann; also automatische Code Generierung.
Dieser automatisch generierte Code kann aber nicht bearbeitet werden, weil alle Änderungen beim nächsten Durchlauf natürlich überschrieben werden.
Mit partial hat man nun die Möglichkeit einen generierten Code zu "erweitern", ohne, dass bei einem neuen Durchlauf der generierte Code alles überschreibt.

Nur wie greife ich nun von den Unterfunktionen in den Modulen auf die Variable

In C# gibt es den Begriff eines "Moduls" nicht; daher kann ich Dir nicht folgen, was Du meinst.

Wenn Du sehr viel "reichst", dann hört sich das nicht so an, dass Du Architektur von Software 100% verstanden hast und wie man Pattern anwendet.
Das basiert prinzipiell aber auch auf viel Erfahrung; und dazu gehört auch viel ausprobieren und falsch machen.

Daher mein Tipp:

  • Beschäftige Dich wirklich damit wie C# funktioniert
  • Schau Dir wirklich OOP an
  • Beachte Grundpattern wie die 3 Schicht Architektur, Gang of Four und Prinzipien wie KISS-Prinzip, DRY/DIE, SOLID etc..
4.931 Beiträge seit 2008
vor 4 Jahren

Um was für eine konkrete Klasse handelt es sich, daß sie "tausende Unterfunktionen" hat? Dies dürfte wohl ein genereller Design-Fehler sein.

Üblicherweise sollte eine Membervariable nur von sehr wenigen Methoden aus beschrieben werden, so daß es reicht, diese in eine eigene Klasse auszulagern und zusätzlich einen Getter für diese Membervariable anzubeiten.
Also statt


class LangeKlasse
{
  Type mVar;

  // ganz viele Methoden
  // ...
}

erzeugst du eine eigene Klasse


class MyVarClass
{
   Type mVar;

   public Type Var { return mVar; } // bzw. gleich als Type Var { get; private set; }

   // nur relevante Methoden, welche mVar beschreiben
   // ...
}

und bindest diese dann in deine Hauptklasse ein (und greifst dann - falls erforderlich - mittels des Getters auf die Membervariable zu).

A
adhome Themenstarter:in
3 Beiträge seit 2020
vor 4 Jahren

@Abt: Super. Vielen Dank. Ich glaube du hast verstanden, wo mein Problem ist.
Ich hab irgendwie noch eine falsche Denkweise....

@Th69: Vielleicht ein plastischeres Beispiel:
Klasse Auto hat Instanzen der Klasse Autositz und Fahrer.
Nun will die Klasse Autositz rausfinden welcher Fahrer gerade im Auto ist.
Er müsste somit die Klasse Auto fragen. Nur wie greift Autositz auf Auto zu, wenn es nicht sowas wie eine Parent Eigenschaft gibt.

Bei Klassenstruktur hab ich sowas wie eine Baumansicht im Kopf. Nur fehlen die Parent Befehle um auf die Parents zuzugreifen...

Beim Ableiten gibts ja BASE.

301 Beiträge seit 2009
vor 4 Jahren

In der Regel kannst du sowas über einen Bounded Context bzw. Aggregates lösen.

Es ist nicht so als müsste dein Autositz jemanden fragen wer der Fahrer ist, viel mehr müsste dein Auto mitbekommen wenn der Fahrer gewechselt wird ( oder wo auch immer ) und diese Information auch sofort an den Autositz weitergeben. Somit bleibt die Zuständigkeit beim Fahrerwechsel ganz eindeutig beim Auto.

Schau dir am besten die Thematik zum Domain Driven Design an und ergänzend kann ich außerdem das Prinzip des Data Oriented Design empfehlen.

4.931 Beiträge seit 2008
vor 4 Jahren

@adhome: Du kannst dir auch mal meinen Artikel Kommunikation von 2 Forms durchlesen (da geht es aber auch generell um die Kommunikation zwischen 2 oder mehreren Klassen) - bes. den Abschnitt "Lösung: Verwendung von Eigenschaften (Properties) und Ereignissen (Events)".

A
adhome Themenstarter:in
3 Beiträge seit 2020
vor 4 Jahren

Wie ist es mit einem Manager Klasse die Statisch ist ?
Also eine Art Oberste Instanz die man immer fragen kann wer der aktuelle Fahrer ist und der die Hauptverwaltung übernimmt.
AutoManager.GetCurrentDriver

Falsche Denkweise oder würde in das Modell passen?

16.806 Beiträge seit 2008
vor 4 Jahren

Wie ist es mit einem Manager Klasse die Statisch ist ?

Statische Klassen haben gewisse Aufgaben; static ist aber nicht dazu da Design Fehler zu kaschieren.
Weiterhin sind statische Klassen nicht so einfach testbar bzw. machen Abhängigkeiten teilweise untestbar.
[Artikel] Unit-Tests: Einführung in das Unit-Testing mit VisualStudio

Daher: völlig falsche Denkweise.
Für Abhängigkeiten, die direkt existieren, gibts Dependency Injection; passt hier aber nicht, denn der Hinweis von KroaX mit dem Bounded Context ist hier 100% korrekt und passend.

Du wirst Dich mit Software Design auseinander setzen müssen.
Sprach-Keywords in C# sind nicht dazu da OOP Probleme zu lösen.

A
764 Beiträge seit 2007
vor 4 Jahren

Hallo adhome

Ich möchte dein Beispiel mal aufgreifen.

Klasse Auto hat Instanzen der Klasse Autositz und Fahrer.
Nun will die Klasse Autositz rausfinden welcher Fahrer gerade im Auto ist.
Er müsste somit die Klasse Auto fragen. Nur wie greift Autositz auf Auto zu, wenn es nicht sowas wie eine Parent Eigenschaft gibt.

Es gibt bei modernen Autos die Möglichkeit, die Sitzeinstellung zu speichern und per Knopfdruck auszuwählen. Das heißt der große Fahrer mit den langen Beinen muss sich nicht ins Auto zwängen, weil seine Frau vorher gefahren ist, sondern er drückt auf einen Knopf und der Sitz fährt automatisch auf seine Position.

Wenn ich die Anforderung so lese, dann kommt mir die Idee, dass wir eine Klasse SitzEinstellung brauchen. Die Klasse Sitz muss den Fahrer nicht kennen, sondern hat eine Methode FahreInPosition(Sitzeinstellung). Aufgerufen wird diese Methode (je nach Anwendungsfall) vom Auto, denn da ist ja auch der Knopf dran.

Durch diese Denke ergeben sich fast automatisch übersichtlichere Klassen, mit spezifischer Verantwortung.

Nach DomainDrivenDesign könnte in diesem Beispiel das Auto das AggregateRoot sein. Es gibt ein bestimmtes Auto (Entity), in das ein bestimmter Fahrer einsteigt (nur eine Id notwendig). SitzEinstellung wäre dann ein ValueObject, Sitz eventuell auch. Die Kommunikation mit der Umwelt, oder dem Programm wird über das AggregateRoot Auto gemacht.

DomainDrivenDesign soll nicht überall angewendet werden, gehört meiner Meinung nach aber zur Bettlektüre vom professionellen Entwickler, da es das Denken ungemein erweitert.

Gruß
Alf