Suche Menschen die meinen C#-Code kritisieren!

Kokujou schrieb:
Aber man kann auch nicht jedes bischen nachgoogeln
Oh doch xD entweder bei den üblichen Verdächtigen suchen oder dokus lesen.
Weist du warum ich als Entwickler 3 Monitore habe? Weil ich rechts und Links neben meinen Code direkt die Dokus und die Suchmaschinen offen habe (Okay... Musik und der ein oder andere Messanger braucht auch etwas Platz ;D).
Bei manchen Sprachen und Frameworks brauchst du das mehr, ebi anderen weniger. Aber man verbingt schon recht viel Zeit damit danach zu suchen, ob andere auch bereits das Problem hatten und adaptiert deren Lösungen.
 
Ja viel. Aber nicht alles. Bei dir gibts sicher auch vieles was du einfach als gegeben hinnimmst. Stell dir mal vor ich würde dir sagen dass es jetzt ne neue Methode für getter und setter gibt wo man keine Extra Variable korrigieren muss wo der Compiler die Arbeit macht - wie auch immer das jetzt genau von statten geht.

Da würdest du doch auch nicht im Traum nachdenken. Oder googelst du bei jeder if-Anweisung die du machst nach obs jetzt vielleicht ne schönere Art und Weise gibt die zu gestalten?

Ich hab ja sogar gehört dass man foreach vermeiden soll. Wäre ich nie drauf gekommen da nachzugoogeln weil es für mich einfach so schön wirkte. Und sogar mein VS schlägt mir das hier und da vor. Aber angeblich soll das total ineffizient und unpraktikabel sein. Hab ich zumindest mal gehört. Man googelt erst etwas nach wenn es sich als Problem erweist, wenn du irgendwo nicht weiter weißt.
 
@Crast ist es eigentlich ein guter Stil, wenn man ne Klasse nur für Funktionen hat? Also quasi alle Funktionen nur in ne andere Datei schiebt, zwecks Übersichtlichkeit? Oder sollte man sich da immer was anderes einfallen lassen?
 
TL;TR
It depends!

Erstmla kurz zum Terminus: Die Klassen die du meinst schimpfen sich UtilityClass oder HelperClass. Es sind Strukturen, die nur statische Methoden haben und keinen State kapseln, also nicht Instanziert werden um Daten zu gruppieren und zu schützen. Sie bieten allgemeine Funktionen, die überall gebraucht werden können.
Sie entstehen oftmals, wenn man das DRY-Prinzip verfolg.
Es gibt viele Build-In Classes die dieses Konzept verfolgen, z. B. die Math-Class. Entsprechend können sie nicht so schlecht sein, oder etwa doch?

Da ich weiß, dass du versucht dich in der Welt von OOP zurecht zu finden, bezieht sich meine Antwort auch auf OOP.
Nimmt man die Meinungen, die an in Fachliteratur in Blogs von Entwicklern zu dem Thema gefunden werden können, zusammen erhält man etwa die Aussage, dass diese Klassen in den meisten Fällen von einem schlechten Stil zeugen.
Die Begründung ist, dass diese Klassen nicht in dem Konzept der objekt-orientierten Welt passen. Stattdessen sind sie ein Überbleibsel der prozeduralen Programmirung.
Allerdings wird auch an einigen Stellen betont, dass es nicht gut ist Objekte zu erstellen, ohne das diese einen Zustand haben.

Oft ist man der Meinung, dass eine Funktion so generisch ist, dass sie zu keiner Klasse passt, doch am Ende verwendet man sie genau an einer, oder vllt zwei Stellen. Es passiert auch oft, dass eine Methode, bei genaueren hinschauen, zwei untershiedliche Sachen macht, die zu zwei unterschiedlichen Klassen gehören.
Kurz: Die meistene Methoden sind speziell genug, um sie einem Objekt zuordnen zu können.

Im Allgemeinen kann man aber bei OOP jede Methode, auch statische Methoden, eine Klasse zuweisen. Da ist es dann auch in Ordnung, wenn sie Input und Output haben und nichts an einem Zustand verändern diese Methoden statisch zu machen. Ein Beispiel dafür sind z. B. Methoden die ein Objekt parsen und dabei ein anderes Objekt zurück geben, ohne den Input zuverändern.


Ich persönlich habe eine sehr große Abneigung gegen Util-Classes. Und der Grund ist ganz einfach: Erfahrung.
Bei uns auf der Arbeit wurde von einer Abteilung vor etwa 6 Jahren ein Projekt eröffnet, das im Namen "Util" hat. In dieses Projekt wurden alle Funktionen reingepackt, die sie meinten in mehreren Projekten verwenden zu können oder schlicht nicht direkt im Code haben wollten. Nach gerade mal zwei Jahren dauerte ein Build dieses Projekts über 6 Stunden und keiner hatte einen Überblick was das Projekt alles beherbergt hat. Viele andere Kollegen erstellen ebenfalls ihre "privaten" Util-Klassen, wo keiner von was weiß und die Funktionen werden meist nur in einem Projekt und an einer Stelle verwendet.
Ich selbst versuche Util-Klassen zu vermeiden. An manchen Stellen kommt man allerdings nicht drum herum (oder ich bin zufaul mir was schöneres zu überlegen und versehe die Klasse mit einem //Todo).
Doch sobald eine Klasse ein "General", "Util", "Helper", oder "Common" (nur Beispiele) im Namen hat, gehen bei mir die Alarmglocken an und ein leichte Gefühl von Übelkeit überkommt mich.


Du kannst gerne ein paar deiner Methoden, die du einer Util-Klasse zuweisen würdest hier posten, zw die Util-Klasse selbst. Dann können wir diese gemeinsam auflösen.
 
  • Gefällt mir
Reaktionen: BeBur
Ich rede eher von partial classes die zwar auch nicht instanziiert werden, weil in Unity Klassen die von monoBehaviour erben quasi je einen Main-Loop verkörpern sowie Start und Wake Funtkionen aber joa ^^ offiziell nicht statisch.
Es ging in der Frage also wirklich nur um die Lesbarkit, dass man z.B. zwecks Kontext-Trennung alle virtuellen funktionen, die mit Karten zutun haben in die VCards.cs packt und alle die mit graphischer Animation der verbundenen Objekte zutun haben in die Cards3D.cs oder so ^^

Ich versuche ja im Momnet auf alles statische weitesgehend zu verzichten, an einigen Stellen geht, an anderen nicht. Besonders diese Erweiterungsmethoden a la Linq liebe ich.
Denn die machen quasi dass was ich IMMER wollte.
Es ist quasi als würdest du ne Vererbung machen und dann die Funktion als Instanz-Funktion hinzufgen.
Genau das wllte ich bei Unity ständig machen, bei Listen, Basisklassen, Arrays.
Teils weil man von einigen Unity-Klassen nicht erben DARF weil das ganze nicht mehr funtkionieren würde,
Teils weil es mir zu blöd ist von einer Klasse zu Erben nur um eine Eigenschaft oder eine Funktion hinzuzufügen, dann aber Rückwirkend den ganzen Code umschreiben zu müssen.
Eigenschaftsnamen kann man bei VS ja leicht ersetzen, aber Reihenersetzung der Datentypen wäre mir neu.
 
partial class dient eigentlich nur dem aufteilen einer Klasse in mehrere Dateien.
Habe z.B. eine Bibliothek welche zum ansprechen einer REST API dient. Zur besseren Übersicht habe ich die Implementierung dann eben mittels partial class auf mehrere Dateien aufgeteilt(eine pro Entität). Dadurch habe ich nicht mehr eine Datei mit mehreren Tausend Zeilen sondern vier mit ca. tausend Zeilen und eine mit 50 Zeilen.
partial class sagt nichts darüber aus wie etwas Instanziert wird.

Der Erfahrung von @Crast bzgl. dieser statischen Util Klassen kann ich mich nur anschließen.
 
  • Gefällt mir
Reaktionen: Crast
Und bevor man so einen Spruch bringt sollte man sich vielleicht selber mal Gedanken über das S in SOLID machen!

Zum einen hab ich mich im Faktor ein wenig vertan, es sind aktuell zusammen nur 991 Zeilen^^
Zum anderen, die Zuständigkeit[wofür das S(Single Responsibility] in SOLID steht) der Klasse liegt darin die Endpunkte der REST API mit dem entsprechenden Model aufzurufen.
Es gibt drei Entitäten für die es jeweils CRUD Methoden in synchroner und asynchroner Form gibt. Was willst da aufteilen? Eine Klasse für jede Entität? Sorry, aber das würde die Arbeit mit der Client Klasse nicht einfacher machen und auch nicht für bessere Übersicht sorgen. Vor allem da es ziemlich einfacher Code ist(baue Request, sende Request mit injiziertem HttpClient und mach was mit dem Response)
 
Ja eben! Ihr sagtet ja ich soll ausgliedern also mach ich das für alles was nicht in ner extra Klasse zusammenfassbar ist... Es dient also nur den von euch in vielen posts so angeschriebenen Codingstyle und ich wollte jetz wissen ob es jetzt auch guter Stil ist in so ne partial class nur Methoden zu haben.
Was haltet ihr eigentlich von der neuen Klasse YakuManager? Ich hab dafür ne eher negative Kritik bekommen obwohl ich fand sie war eigentlich sehr gelungen...
Angeblich sollen solche Manager-Klassen schlechter Stil sein >.< Dabei wollte ich nur ne Klasse einbauen die quasi alle Anzeigen dieser regelt.
 
Partielle Klassen verwende ich hauptsächlich, wenn ich die eigentliche Klasse nicht verändern darf / kann. Das kommt vor allem bei automatisch generiertem Code vor, zum Beispiel in einem Projekt, wo wir das Entity Framework mit Database First nutzen. Wenn die Entities neu generiert werden, wären sonst alle meine Änderungen verschwunden.
Ich schätze mal, das wird bei Unity ähnlich sein?!

Ich finde deinen vorletzten Post aber etwas verwirrend, du wirfst da viel durcheinander.
Ich würde mal sagen: Ja, grundsätzlich ist es schon mal positiv ähnliche Dinge am gleichen Ort zu haben. Am Besten wäre dennoch sich mal zu überlegen, ob man das nicht OO hinbekommt.
Helper-Klassen, die maßlos wachsen können und alles Mögliche enthalten, sind mir auch ein Graus. Bei neuen Projekten springe ich sofort auf, wenn jemand sowas anlegt und zerschlage (refactore) das. Wie Crast schon sagte: Meistens gehört es doch irgendwo hin.
 
automatisch generierter Code... Also sowas hab ich nichtmal.
In Unity hat man eine Basisklasse genannt MonoBehaviour, von der erbt man damit Routinen wie Start() Awake() und vor allem Update() aufgerufen werden. und dann kann man direkt anfangen. Ich arbeite daran alles in eigenständige Klassen auszugrenzen und die Komponenten von Unity zu benutzen aber auch so sind die Klassen verdammt fett und mit Funktionen vollgestellt. Also wollte ich sie der Übersichtlichkeit ausgelidern

Ja solche Helper-Klassen verwende ich auch gar nicht (mehr). Generell versuche ich auf Statik zu verzichten. Das einzige was ich habe sind Extension Classes und ich kann nicht oft genug sagen wie sehr ich sie liebe! Die benutze ich aber auch nur wenn es nicht anders geht. z.B. hab ich ein int[]-Array die Repräsentation eines Spielzuges gegeben. Also bau ich ne Extension auf nem int[] der diese Spielzüge auswertet, ist dann halt nur für dieses Projekt gültig. Dasselbe für Animationen. Das sieht auch im Code schöner aus ^^
 
Ach du meinst Extensions... ja die sind super. Aber:
Kokujou schrieb:
z.B. hab ich ein int[]-Array die Repräsentation eines Spielzuges
Warum ist das dann kein Spielzeug-Objekt? Schon kannst du dem nämlich deine gewünschte Methode geben.
Eine Extension ist allgemeingültig für alle deine int[], dementsprechend sollte das keine speziellen Inhalte bedingen.
 
  • Gefällt mir
Reaktionen: new Account() und Crast
Könnte ich aber ich bin sicher wenn ich mich reinlese gibt es einen absolut plausiblen Grund warum ich es nicht tue :p
So ist es einfacher und kompakter. Theoretisch kannst du in jede Funktion irgendeinen mist reinschreiben der nicht valide ist :p
 
Fonce schrieb:
Und bevor man so einen Spruch bringt sollte man sich vielleicht selber mal Gedanken über das S in SOLID machen!
Angriff ist die beste Verteidigung oder was? Macht nichtmal Sinn (für mich)

Du siehst ja selbst ein, dass 4k+ Zeilen pro Klasse Code Smell sind, da du extra noch betonst, dass du dich geirrt hast mit den 4k Zeilen und dich dann noch rechtfertigst, dass ein Aufteilen deiner Meinung nach wenig sinnvoll ist (ist ja OK, manchmal ist ein anderer Weg der beste

Fonce schrieb:
Eine Klasse für jede Entität? Sorry, aber das würde die Arbeit mit der Client Klasse nicht einfacher machen und auch nicht für bessere Übersicht sorgen. Vor allem da es ziemlich einfacher Code ist(baue Request, sende Request mit injiziertem HttpClient und mach was mit dem Response)
Auch wenn ich mich jetzt ohne Details auf dünnem Eis bewege, ist das vielleicht tatsächlich der richtige Weg. Das Repository Pattern ist nich umsonst ein sehr verbreitetes Pattern. Kombiniert mit dem Aggregate Root Pattern (hat tatsächlich einen Namen :D ) schaut dann auch der Client vernünftig aus und sorgt außerdem für bessere Useability des Clients, da eine logische Unterteilung stattfindet:

client.Books.Add(Book)
client.Books.Remove(Book)
client.Movies.GetAll()

Dann hast du Client = "Interface", und pro Entity eine Klasse. In separaten Dateien sind sie ja eh schon.


Enurian schrieb:
Partielle Klassen verwende ich hauptsächlich, wenn ich die eigentliche Klasse nicht verändern darf / kann.
Ich weiß nicht, ob du Extensionmethods kennst, aber oft sind diese bei ähnlichen Zwecken auch hilfreich.
 
  • Gefällt mir
Reaktionen: Crast
new Account() schrieb:
Ich weiß nicht, ob du Extensionmethods kennst, aber oft sind diese bei ähnlichen Zwecken auch hilfreich.

preiset die ExtensionMethods. Sie sind himmlisch. ehrlich ich liebe sie! Es ist quasi die Rechtfertigung für meine geliebten globalen Funktionen :p Nein Spaß bei Seite. Aber das ist echt ne tolle Erfindung.
Nur falls einer noch nicht weiß wies geht (ich hab's auch erst nicht geglaubt dass es so einfach ist):

Statische Funktionen in einer statischen Klasse, die als Paramter den Vorsatz this haben können auf jeder Instanz des folgenden Typen aufgerufen werden.

C#:
public static class $Name$
{
    public static $Rückgabetyp$ $Funktion$(this $Basistyp$ $Name$, [...]) {...}
}
[...]
$Basistyp$ $Variable$;
$Variable$.$Funktion$([...]);

Ich bin übrigens kurz davor das ganze Netzwerk-Zeug abzudocken was mir später sehr helfen wird... Aber dafür werde ich die komplette Hauptklasse warscheinlich wechseln. Ich habe gerade gemerkt wie sinnlos die ganze Main-Klasse eigentlich ist da die meisten Funktionen auf der Spielfeld-Klasse operieren. Also kann ich das auch zu nem NetworkBehaviour machen und dann mittels partial classes auslagern.

Es ist ein echter Konflikt ich soll möglichst viele Klassen irgendwie auslagern, dabei aber gleichzeitig Statik vermeiden und Manager-Klassen auch gleich. Wobei ich echt nicht sicher bin was mit Manager-Klassen eigentlich gemeint ist... Vielleicht hat der Kritiker sich auch nur an dem Namen aufgehangen XD
 
Zuletzt bearbeitet:
Ist es eigentlich ein "Guter Stil" wenn man zwei partial classes in einer Datei hat?

Ich hab gerade eine Klasse für Funktionen eingerichtet, die für die Konversation zweier Klassen da sind. Und da hätte man jetzt ein paar Funktionen in der einen und nochn paar in der anderen die aber thematisch zusammengehören^^
 
Würde ich nicht machen. Pro Klasse eine Datei.
 
Und noch eine Frage:

Statik als eine Art Enumeration.

ich habe gerade eine Sammlung von Funktionen zum Thema Animation gemacht. Welche davon ich aufrufe entscheide ich per Zufall. Ich trage sie dafür alle in eine Liste ein. Jetzt der Punkt. Ihr verwendet ja auch Enumerationen und Consts zur Vermeidung von Typos, kann man ein ähnliches Prinzip anwenden und quasi eine statische Klasse bauen sodass man nur Klasse.funktion1, Klasse.funktion2 schreibt?
 
Schreibe ein Interface mit "funktion", dann erstellst du eine Animations-Klasse pro gewünschter Funktion, die das Interface implementiert.
Schreibe eine (statische) Factory-Klasse, der du die Zufallszahl übergibst. Diese liefert dann eine Instanz der gewünschten Animations-Klasse zurück.
 
  • Gefällt mir
Reaktionen: new Account()
Also statt eine Klasse einzubauen habe ich stattdessen für jede Funktion eine Klasse. Also verxfacht sich mein code ohne dass dabei irgendein Nutzen entstünde. und das soll jetzt guter Stil sein? :o

ne Art interface baue ich ja schon ein indem ich ne Liste der Variable Func<Sprite, IEnumerator> erstelle. Also eine Funktion die nen IENumerator zurückgibt (Unity Coroutine) und dafür das nächste Bild, was ja für die Animation essenziell ist annimmt.

Und in meiner Version kann ich wenigstens über den Index gehen... Du hast z.B. gar nicht gesagt wie ich jetzt die Zahlen darauf mappe, welche Klasse ich aufrufe. So benutze ich die Zahl als Index der Liste.

Aber wenn ich das gerade richtig lese, müsste ich dann nen switch-case-block draus machen oder noch shlimmer mit if/else. Das ist doch Wahnsinn!
 
Zurück
Oben