C# GUI wird zu groß

Ghost_Rider_R

Lieutenant
Registriert
Nov. 2009
Beiträge
799
Hallo zusammen,

ich habe speziell bei den grafischen Oberflächen (XAML mit Code-Behind) immer das Problem, das meine Code-Behind-Klassen schnell zu groß werden.

Normalerweise breche ich immer alles runter damit ich möglichst nicht über 150 Zeilen Code pro Klasse komme nur bei den grafischen Oberflächen ist das nicht so einfach umsetzbar, da viele Methoden auf Oberflächen-Elemente zugreifen müssen wie z. B. textBox.Text = "BinGeändert". Das kann man ja immer nur im GUI-Kontext durchführen.

Wie handhabt Ihr dieses Problem?

LG Ghost Rider
 
Ghost_Rider_R schrieb:
Normalerweise breche ich immer alles runter damit ich möglichst nicht über 150 Zeilen Code pro Klasse
warum?
 
  • Gefällt mir
Reaktionen: dewa und madmax2010
@KitKat::new() Damit die Klassen schön übersichtlich bleiben, wartbar, testbar, austauschbar etc. Die üblichen Design-Patterns wende ich hier überall konsequent an und erziele damit stets sehr gute Ergebnisse.

Nur im Bereich der GUIs tue ich mich schwer, da ich innerhalb der Methoden häufig auf Steuerelemente der GUIs zurückgreifen muss um z. B. Textboxen auszulesen etc.
 
Eine Klasse ist doch nicht nicht mehr testbar/warbar/austauschbar, nur weil sie 300 statt 150 Zeilen code hat.
 
  • Gefällt mir
Reaktionen: TomH22, Tornhoof, madmax2010 und 2 andere
Das ist soweit richtig nur wird es MIR zu unübersichtlich. Bei meinem aktuellen kleinen Projekt bin ich bereits bei 350 Zeilen und mit jedem Feature werden es ein paar Zeilen mehr, daher fände ich es schön, wenn ich das irgendwie kapseln könnte. Ist hier MVVM State of The Art? oder gibt es andere herangehensweisen?
 
Ghost_Rider_R schrieb:
Ist hier MVVM State of The Art? oder gibt es andere herangehensweisen?
Ja, Stand der Technik ist da MVVM (oder ein vergleichbares Konzept), also dass man effektiv keine Programmlogik in der Code-Behind hat. Stattdessen findet die Interaktion zwischen Programmlogik und dem in YAML geschriebenen UI über Bindings statt. Dann hat man auch nicht haufenweise Zeilen wie textBox.Text = "BinGeändert" und zudem kann man die Logik austauschen/ändern, ohne den Code des UI anzufassen. Außerdem kann man so die Logik besser testen, weil man dafür das UI nicht braucht und noch nichtmal ein System mit Bildausgabe.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: BeBur
Was @mibbio sagt. Wenn du hier soweit bist Codepflege zu betreiben und nicht mehr mit der Umsetzung kämpfst, setz dich intensiv mit MVVM auseinander und entkopple den ganzen Kram. Optimalerweise mit modernem .NET auch mit Dependency Injection, dann kann man das alles richtig schön auftrennen und muss sich nicht mehr um viel kümmern.
Wenn man dann noch Code sparen will, bietet sich das MVVM Toolkit mit Code Generatoren an, was den ganzen Boilerplate Code entfernt (ICommand Implementierungen, INotifyPropertyChanged Properties usw.).

Aber eins nach dem anderen, erstmal mit MVVM anfangen und verstehen, dann kann man immer noch weiter gehen wenn man das will. Das ist auf jeden Fall der richtige Ansatz hier.
 
  • Gefällt mir
Reaktionen: Krik
KitKat::new() schrieb:
Von den 150 musst dich aber glaub verabschieden
+1
auch Klassen mit 4-Stellig Zeilen können gut lesbar sein. Ebenso können solche mit 20 Zeilen absolut grausam sein.
 
  • Gefällt mir
Reaktionen: TomH22 und Tornhoof
Die Anzahl der Zeilen Code pro Klasse ist kein Indikator für die Wartbarkeit, Lesbarkeit, Korrektheit, oder wwi.
Das ist einfach nur ein Wert, den diverse Autoren, z.b. der Clean Code Autor gewählt haben.
 
  • Gefällt mir
Reaktionen: TomH22
@Nero1 und @mibbio ich versuche es nun nochmals mit MVVM umzusetzen. Das hatte ich in einer frühen Projektphase auch schon mal umgesetzt, dann aber wieder entfernt, weil es mir erstmal nicht vertraut vorkam, aber vielleicht muss ich mich hier einfach ein bisschen an das neue Konzept gewöhnen.

Außerdem arbeite ich bereits mit einem Dependency Container, Interfaces etc, und seit dem ich das alles so sauber trenne funktiniert mein Code überlicherweise auch immer sehr zuverlässig, ist übersichtlich, keine Seiteneffekt-Fehler etc.

Nur bei den GUI-Klassen ging mein Konzept nie auf, weil die vielen Events und Zugriffe auf die Steuerelemente der Oberfläche sich nicht auf dem mir bekannten weg entkoppeln ließen, aber mit MVVM ist dies ja möglich nur fühlt es sich noch sehr fremd an 😅
 
wenn du trennen willst, aus optischen Gründen, kannst du auch partielle Klassen nutzen. und dann sowas
halt Class1.EventHandler.cs, Class1.Xyz.cs oder so.

Das wird häufiger genutzt um z.b. Platformspezifischen Code zu trennen, also sowas wie
File.Windows.cs, File.Linux.cs, File.Macos.cs oder so
 
  • Gefällt mir
Reaktionen: Micke
@Tornhoof da habe ich auch schon dran gedacht, allerdings hat sich das für mich immer ein wenig nach Pfusch angefühlt, da man in den separaten Teilklassen dann keinen Überblick mehr hat, was in anderen Teilklassen steht. Das ist aber nur so ein Bauchgefühl, vielleicht ist das in der Praxis auch kein Problem. In jedem Fall vielen Dank für die Idee!
 
Was heißt schon Pfusch, früher hat man #regions genutzt für sowas. Partielle Klassen/Methoden/Properties usw. sind mittlerweile wieder modern, weil Source Generators das nutzen.

Für eine logische Trennung wie z.b. .Event.cs oder so würde ich da keine Probleme haben mit, gerade wenn da Unmengen an Boilerplate Code drin ist.
 
Das kann schon durchaus funktionieren, für mich hat es sich aber irgendwie nicht ,,richtig" angefühlt. Rein Objektiv könnte dein Ansatz durchaus funktionieren. Mich hat es vor allem interessiert, was denn hier der gängige und bewährte Weg in größeren Projekten ist, daher der Thread :-)
 
MVVM ist der Weg, Code Behind nur für die wirkliche UI-Logik, und die sollte normalerweise auf ein Bierdeckel passen. Oder eben in XAML Komponenten ausgelagert sein, die dann wieder genau ein Ding tun.

.xaml.cs
Code:
Model model{get;set;}
void Init(Model m){
model=m;
DataContext=this;
InitializeComponents();
}
xaml
Code:
<TextBlox Text="{Binding Path=model.StatusText,Mode=OneWay}"/>

EDIT: Und Events und Co kann man auch mit XAML MVVM binden Observable und PropertyChangedEvent für Code->UI. UI geht auch viel, z.B. Commands geht sehr gut mit der RelayCommand Klasse.
Code:
<Button Command="{Binding Path=DoFoo}">Do Foo</Button>
...
public class Model{
public ICommand DoFoo{get=>new RelayCommand(()=>{FooBar();})}
}
 
@Hancock ich ändere mein Projekt gerade nochmals in MVVM ab und bewerte das Projekt dann erneut. In jedem Fall muss man sich an dieses Konzept erst gewöhnen...

 
KitKat::new() schrieb:
Gibt's dafür eine Quellenangabe?
(das praktisch bekannteste Zitat dazu, S34 in Clean Code, zumindest in der Ausgabe die hier rumsteht)
“The first rule of functions is that they should be small. The second rule of functions is that they should be smaller than that.” — Robert C. Martin
(und wahrscheinlich auch das am häufigsten falsch genutzte :D)
Irgendwo gibts noch das Zitat, dass man maximal 20 oder 30 Functions per Class nehmen sollte, dann kam man irgendwo auf 300 Zeilen oder so.
Und nur der Vollständigkeithalber: https://qntm.org/clean bzgl. der Anwendbarkeit von Clean Code im aktuellen Jahrzehnt


Martin Lippert hat in https://www.amazon.com/Refactoring-Large-Software-Projects-Restructurings/dp/0470858923 etwas großzügiger gerechnet. 30 Zeilen (ohne Kommentare/Leerzeilen) pro Function, 30 Function per Class, also rund 900.
 
Zurück
Oben