Codingstil: Wie sieht euer Projekt-Design aus?
Übersicht

![]() |
FetzeBetreff: Codingstil: Wie sieht euer Projekt-Design aus? |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hi Leute.
Ich stelle bei mir mit wachsender Erfahrung im Codedesign größerer Projekte eine zunehmende Unfähigkeit fest, kleine Projekte einfach mal eben "quick'n'dirty" zusammenzuhacken. Es ist weniger eine konkrete Unfähigkeit als mehr die Tatsache, dass ich mich sehr am Riemen reißen muss, um nicht unmengen von overengineereten Klassenkonstrukten zu produzieren. Die Schwierigkeit besteht darin, einem Projekt eine angemessene Designkomplexität im Inneren zuzuordnen und sich an diese auch zu halten. Beispiele für geringe Designkomplexität: --> Ein paar globale Programmfunktionen für MainLoop, Hauptmenü, Ladevorgang, etc. --> Wenn nötig, ein oder zwei Klassen für Objekte im Spiel --> Spielercode, etc. direkt im Hauptprogramm Beispiele für hohe Komplexität: --> Keine vorgegebenen Klassen zur Bearbeitung von Einzelfunktionen des Programms sondern ein dynamisches Task-System --> Kein manuelles Einladen des Contents, sondern ein ContentProvider, der alle vorhandenen Resourcen erfasst und bei Bedarf einlädt und herausgibt --> Komplexe Vererbungshierarchie von Spielobjekten à la IPositionable --> GameObject --> ControllableObject --> Ship --> Automatisierte Serialisierung, beispielsweise durch Aufspaltung jedes Objekts in "Spielobjekt" und "Datenobjekt" wobei das Datenobjekt rein primitive Datentypen enthält und Teil des Spielobjekts ist. --> Blueprinting-System für Massenproduktion von Objekten bestimmter Typen (zB. Raumschifftypen) --> Auslagerung aller Contentdaten in externe Dateien. --> etc. Wie handhabt ihr das? Habt ihr für euch klare Design-Indizien gefunden, die euch sagen "Junge, das ist jetzt aber sehr overengineered"? Habt ihr Taktiken entwickelt, die euch davon abhalten, euch zu viele Gedanken über Codekomponenten zu machen, die das im Rahmen des Projekts überhaupt nicht verdient haben? |
||
konstantin |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Bei mir schlaegt sich das eigentlich eher in der Wahl der Programmiersprache nieder. Wenn ich 'quick-n-dirty' was zusammen kloppen moechte, lande ich meist irgendwo bei BB oder Perl, da mach ich mir dann nur selten Gedanken ueber das eigentliche Design - am Ende kommt eh nur Code-Wurstbrei raus. ![]() Ansonsten erfordern grosse Projekte meist auch die dazu passende Programmiersprache, und ich persoenlich habe die Erfahrung gemacht, dass man zum Beispiel fuer ein Projekt in C zwangslaeufig vernuenftige Strukturen benoetigt, sonst steht man nach ein paar Tagen ziemlich im Regen. Akribisches Layout ist aber meiner Meinung nach eher was fuer von vornherein gross angelegte Projekte, bei denen man eventuell auch mit vielen anderen zusammen arbeitet. Fuer den heimgebrauch reicht es ja, wenn man den Code nach ein paar Wochen noch selbst versteht - und die Performance stimmt. |
||
n-Halbleiter |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Fetze, ziemlich genau diese Indizien habe ich bei mir auch festgestellt. Wenn man größere Projekte angeht, wird geplant. Und dieses Overengineering, wie du es beschreibst, ist eines der Produkte des Planens, denke ich. Für kleine Projekte ist die Wartbarkeit erstmal egal, da man im Nachhinein vermutlich sowieso nichts ändert, ansonsten ist die Wart- und Austauschbarkeit der Komponenten ja essentiell...
Gedanken über das Design musste ich mir z.B. bei Ploing nicht machen, jedoch bei meinem Core schon. Hier sehe ich auch den Kontrast von "quick'n'dirty" zu geplantem Design, der sich in ebenjenen Kriterien für hohe bzw. niedrige Komplexität niederschlägt. Wenn ich ein kleines Spiel zusammenschustere, dann verfalle ich meist in ein planloses Verhalten: Ich schreibe eine Komponente in mein (meist einziges (!)) Sourcefile, teste, debugge wenn es notwendig ist und mache mich an eine neue Komponente. Wenn ich dann im Nachhinein eine Komponente modifizieren möchte, dann läuft dies häufig darauf hinaus, dass ich viel Source neuschreiben muss... Es ist eine gewachsene Struktur, bei großen Projekten ist es dann geplant. Dies sieht man auf den ersten Blick im Source, zumindest war das bisher bei mir immer so. Die gewachsene Struktur hat den Vorteil, dass sie schnell(er) gecodet ist als die geplante, allerdings ist - wie ja oben schon angemerkt - die Wartbarkeit des Codes deutlich geringer. |
||
mfg, Calvin
Maschine: Intel Core2 Duo E6750, 4GB DDR2-Ram, ATI Radeon HD4850, Win 7 x64 und Ubuntu 12.04 64-Bit Ploing! Blog "Die Seele einer jeden Ordnung ist ein großer Papierkorb." - Kurt Tucholsky (09.01.1890 - 21.12.1935) |
![]() |
ZaP |
![]() Antworten mit Zitat ![]() |
---|---|---|
Kommt bei mir auf die Sprache an, die ich benutze... BB ist meistens sehr schlampig strukturiert, alles andere ist hingegen meist ganz sauber und übersichtlich (und vorallem auskommentiert) Dabei achte ich idr stark darauf, dass alles uniform und aufgeräumt ist, z.B. ganz oben natürlich Includes und Header, Systemglobale, usw. und nach jedem Funktionsdeckel eine Leerzeile (wenn keine { ), und solche Dinge. | ||
Starfare: Worklog, Website (download) |
![]() |
Nicdel |
![]() Antworten mit Zitat ![]() |
---|---|---|
Bei mir liegts auch an der Programmiersprache. Wenn ich schnell was machen will, dann mit BB und unordentlich. Für größere Projekte nehme ich dann BMax, damit kann man einfach schöner programmieren ![]() |
||
Desktop: Intel Pentium 4 2650 Mhz, 2 GB RAM, ATI Radeon HD 3850 512 MB, Windows XP
Notebook: Intel Core i7 720 QM 1.6 Ghz, 4 GB DDR3 RAM, nVidia 230M GT, Windows 7 |
![]() |
Triton |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich fange an, vollende die ersten 80% innerhalb kürzester Zeit, brauche für das Bugfixing der nächsten 10% doppelt so lange und für jedes folgende Prozentchen nochmal doppelt so lange.
Klingt witzig, ist aber eigentlich traurig, weils wahr ist ![]() Bei meinem Aktuellen Projekt (der ultimativen Stringrechenbibliothek) steh ich immerhin bei 99% und da versuche ich alles so einfach wie möglich zu halten. D.h. einfache Gliederung in eine Includedatei in der jede Rechenfunktion einfach eine Function darstellt, nur Arrays und einfache Variablen. Das ist vorallem für den Speed von enormer Bedeutung. Dann noch den Code ordentlich einrücken, vor und nach Functions ein paar Leerzeilen und dann sieht das schon ganz gut aus und kann trotzdem viel. Ich habe die Erfahrung in diesem Projekt gemacht, dass der komplexere, vermeintlich bessere Algorithmus oft die Flexibilität mit Geschwindigkeit erkauft. 90% der Zeit die ich in diese Stringrechenbibliothek investiert habe, hatten mit der vereinfachung und der erhöhung der Geschwindikeit zu tun. |
||
Coding: silizium-net.de | Portfolio: Triton.ch.vu |
![]() |
Silver_Knee |
![]() Antworten mit Zitat ![]() |
---|---|---|
Also ich hab inzwischen glaub ich die ganze bandbreite an Projektmanagement gesehen.
Der erste cnRS-Code von Evolver war komplett für ein Raumschiff ausgelegt. Es hat alles funktioniert aber es war ultra fix. Ein 2. Raumschiff und das komplette system musste neu geschrieben werden. Der 2. cnRS-Code von mir war dann schon strukturiert. Types für jede Kleinigkeit, Kampf gegen undynamische Arrays, ohne auf die idee der Banks zu kommen. trotzdem war alles noch relativ hardcoded und unübersichtlich. Der code in 1000enden dateien aufgesplittet, nur damit es professionell aussieht hat mich umgebracht. Aktuell arbeiten Timbo und ich an der 3. Generation. Thema schwarzer bildschirm. mehr als 300 zeilen und was sieht man: schwarzer bildschirm und im debuglog steht connection established. Dafür diesmal strukturiert ins kleinste detail. Das Konzept umfasst mehrere Paint-Grafiken und ich hab so langsam das gefühl es könnte was werden auch wenn man immernoch schwarzen bildschirm hat. |
||
![]() |
Fetze |
![]() Antworten mit Zitat ![]() |
---|---|---|
Zitat: Ich habe die Erfahrung in diesem Projekt gemacht, dass der komplexere, vermeintlich bessere Algorithmus
oft die Flexibilität mit Geschwindigkeit erkauft. Ja, die Erfahrung habe ich auch gemacht; wenn es um performancekritische Utility-Funktionen geht, taste ich mich zwar mit schön durchdachten Algorithmen heran... aber verzichte bei der darauf folgenden Codeoptimierung vollständig auf Design. Hier ist es am Ende relativ egal, wie das Codedesign aussieht, da der Code sich ja in einer abgeschlossenen und zumeist extrem kleinen Komponente befindet; Erweiterbarkeit spielt da oft einfach keine Rolle, Geschwindigkeit aber schon. Wenn es um größere Projekte geht, ist der performanceseitige Verwaltungsoverhead für Codedesignkram (zB. wenn man Manager für verschiedene Objekttypen anlegt oder ein Task-System einbaut) oft minimal, wenn man dabei den ohnehin vorhandenen Zeitaufwand zur Berechnung eines Frames im Auge behält. Ein Designkonzept, das sich aber an einer performancekritischen Stelle befindet (zB. im Inneren einer allgemeinen GameObject-Klasse), muss dann doch erhöhten Anforderungen genügen. Verlangsamt es den Code zu sehr, ist es schlicht nicht praktikabel, ergo: Raus damit! Ein Beispiel: Wenn ein GameObject zwecks Serialisierungsvereinfachung all seine primitiven Daten(typen) in einem eingekapselten Description-Objekt abspeichert, muss der Zugriff auf diese schnell genug vonstatten gehen. Würde man das Beispielsweise durch ein Dictionary<string,object> realisieren, wäre der performance overhead viel zu groß und das Konzept damit wertlos. Durch direkten Zugriff des GameObjects auf die Member eines als struct angelegten Description-Objects (ohne Umweg über Properties oder Getter-Funktionen) ist der Overhead hingegen nicht vorhanden, das Designkonzept genügt in dem Fall also seinen erhöhten Anforderungen. |
||
n-Halbleiter |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Genau, die sicher finalen Teile können auch schonmal etwas unschöner aussehen, wenn sie dafür schön Performance und alles bieten. ![]() |
||
mfg, Calvin
Maschine: Intel Core2 Duo E6750, 4GB DDR2-Ram, ATI Radeon HD4850, Win 7 x64 und Ubuntu 12.04 64-Bit Ploing! Blog "Die Seele einer jeden Ordnung ist ein großer Papierkorb." - Kurt Tucholsky (09.01.1890 - 21.12.1935) |
![]() |
ComNik |
![]() Antworten mit Zitat ![]() |
---|---|---|
Stichwort Verwaltungsoverhead.
Das ist für mich das beste Mittel mich nicht in Vererbung und zu vielen Klassen zu verlieren. Zum Beispiel habe ich für mein aktuelles ziemlich großes Spieleprojekt eine sehr komplexe KI designt die praktisch unendlich erweiterbar ist... Ich stürze mich dann immer tiefer in "geniale" Ideen und denk mir dann an einem Punkt "Oh Verdammt das werden aber viele Klassen ![]() Aber ansonsten gerne viele Klassen und viel Design. Kleine schnelle Tests werden bei mir automatisch sehr "dirty" weil ich es nicht abwarten kann Ergebnisse zu sehen (SEHEN nicht FÜHLEN) ![]() lg ComNik |
||
WIP: Vorx.Engine |
![]() |
Jolinah |
![]() Antworten mit Zitat ![]() |
---|---|---|
Das geht wohl jedem ähnlich ![]() Ein Grund dafür ist bei mir, dass ich das Designen einfach zu gerne mache. Hier muss man sich wohl einfach zusammenreissen und sich dazu überwinden auch mal wieder "unschönen" Code zu schreiben ![]() |
||
![]() |
mpmxyz |
![]() Antworten mit Zitat ![]() |
---|---|---|
Abgesehen von meinen frühen Anfängen kann man meinen Großprojektstil in zwei Phasen einteilen:
ohne OOP-Ahnungen: Das Projekt ist langsam zusammen mit meiner Programmiererfahrung angewachsen. Es herrschte eine gewisse Zeit lang kein großer Plan. Als ich welche hatte, waren sie eher selten aufgeschrieben. Relativ schnell war ich mir allerdings sicher, dass das Spiel variabel werden soll. Damit kam eine Neuerung: Ich fing an, zumindest "Standards" zu protokollieren, da ich für Objektinformationen Banks nutzte - sie schienen damals schneller als Types zu sein - und ich mir für deren Informationen Offsets und Datentypen merken musste. Doch auch das wurde schnell zu ineffizient und ich fang an, die Offsets in nach einem gewissen System erstellten Konstanten zu speichern. Das Projekt wurde langsam strukturierter und es gab endlich eine Art To-Do-Liste. Trotzdem starb dieses Projekt. Das lag zum Einen daran, dass ich mir immer noch die Datentypen der in Banks abgespeicherten Daten merken musste und die langen Konstanten für die Offsets ziemlich umständlich waren, zum Anderen aber daran, dass das Projekt immer noch aus allen möglichen Programmierstilen bestand. Gegen den Aufwand der Banks habe ich einen Precompiler geschrieben, der ziemlich Hardgecodet ist und einige Coderedundanzen enthält. Die für diesen Precompiler notwendigen Inis und meine ersten OOP-Ahnungen - eigentlich war OOP für mich immer noch ziemlich unbekannt - sorgten dafür, dass ich mein Projekt noch einmal anfing. mit OOP-Ahnungen: Als erstes kamen die Inis. Diese waren eine sehr detaillierte To-Do-Liste und halfen mir sehr, einen ordentlichen Stil zu halten und gewisse Standardabläufe durchzuplanen. In relativ kurzer Zeit habe ich 26 Code-Dateien mit insgesamt 162 KiB bzw. grob geschätzten 5000 Zeilen Code fertiggestellt, der das war, was er sein sollte: eine Leistungsfähige und flexible Grafikengine. Seit dem Anfang dieses Schuljahres war dann aber meine Freizeit wieder eingeschränkter und ich hatte mich auf ein Nebenprojekt konzentriert, welches ich erst später in meinem Hauptprojekt hätte verwenden können. Während dieser Zeit kam aber die OOP-Erleuchtung; ich hatte mir in der Schule OOP in Java angeeignet und dieses dann später noch einmal 'richtig' gelernt. Auch, wenn ich B3D verwendete, hatte ich versucht, meinen Programmierstil möglichst objektorientiert zu gestalten. Die Banks sah ich langsam als Objekte, einige Funktionen konnte ich mir gut als Objektmethoden vorstellen und ich hatte schon einige "gefakte Vererbungen" genutzt. Nun habe ich BlitzMax getestet und mein Codingstil ist weiter in Richtung OOP gerutscht. Aber für die Zukunft muss ich mir noch überlegen, wie es weitergeht. mfG mpmxyz |
||
Moin Moin!
Projekte: DBPC CodeCruncher Mandelbrot-Renderer |
BIG BUG |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Zitat: Ein Grund dafür ist bei mir, dass ich das Designen einfach zu gerne mache. Hier muss man sich wohl einfach zusammenreissen und sich dazu überwinden auch mal wieder "unschönen" Code zu schreiben Wink
Jo, den richtigen Zwischenweg zu finden ist manchmal gar nicht so leicht. Ein tiefgründiges Design ist auch nicht unbedingt übersichtlicher/leichter wartbar, z.B. ist ein LoadImage leichter zu verstehen als ein Ressourcenmanager. Letztendlich hängt viel davon ab, wie komplex ein Softwareprodukt am Ende sein soll. Termine sind natürlich ein weiterer Punkt, wobei ein sauberes Grunddesign nicht unter Termindruck leiden darf. Kleinere unabhängige Dinge können notfalls auch "hingeschmiert" werden. Ich denke dies ist insgesamt ein Punkt wo Erfahrung eine große Rolle spielt. Und es freut einen schon wenn man Jahre später noch etwas implementieren möchte/muss und das ursprüngliche Design dies dann tatsächlich einfach macht. |
||
B3D-Exporter für Cinema4D!(V1.4)
MD2-Exporter für Cinema4D!(final) |
![]() |
ozzi789 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Also wenn ich mal nur kurz code, dann wie bei den Meisten ziemlich ungeplant und einfach drauflos.
Seit ich Programmieren (C#) als Schulfach habe, mache ich sogar Struktogramme bei grösseren Projekten, der Ablauf -Idee -Mögliche Probleme finden und lösen (anhand des Struktogramms, meistens lass ich mir vor dem Einschlafen alles durch den Kopf gehn) -Anfang Coden -Schauen ob man sich ans Struktogramm hält, falls nicht, entscheiden ob man einen Fehler gemacht hat und dann entweder den Code oder das SG verbessern Und das wiederholt sich solange bis es fertig ist. Allgemein arbeite ich sehr gerne mit Types.. habe mir auch angewöhnt sozusagen nichts mehr in die Hauptschleife zu packen als funktions aufrufe und zmb Bilder laden usw in eine Include, viel schöner so ![]() |
||
0x2B || ! 0x2B
C# | C++13 | Java 7 | PHP 5 |
![]() |
Arrangemonk |
![]() Antworten mit Zitat ![]() |
---|---|---|
interfaces, implementierende klassen, alles ziemlich abstakt gehalten
aber ich mach ja auch keine spiele |
||
ingeneur |
![]() |
Markus2 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich konzentriere mich auf einzelne Funktionen das die perfekt sind und das machen was sie sollen und
auch zurück geben ob sie das getan haben was sie sollten . Je kürzer je besser aber auch gleichzeitig das man alles gut versteht . Wenn man alles ordentlich macht spart man sich später eine menge Arbeit und Fehlersuche . Ein Baum wächst langsam , es macht keinen Sinn direkt alles auf einmal anzufangen . Und man muß in der Lage sein immer das ganze Programm zu verstehen (im groben) , den Ablauf um Kopf laufen zu lassen , zu simulieren , voraussagen zu machen . Wenn man eine Aufgabe hat zoomt man in die Komplexität rein , konzentriert sich auf dieses Umfeld , zoomt wieder raus und wieder wo anders rein . Wenn man lange nicht am Programm gearbeitet hat ist es von Vorteil sich einen Ablaufplan zu machen, also wann wo welche Funktion benutzt wird untereinander schreiben . |
||
![]() |
Jamagin |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich mache mir bei meinen Projekten immer zuerst ein Konzept, ein Schema (Ablaufplan oder Flußdiagramm) wie auch immer das heißen mag und ich habe mir von Beginn an angeeignet sauber zu programmieren. Ich kommentiere fast alles, damit ich auch nach längerer Codeabwesenheit wieder schnell ins Programm finde.
Nach und nach wird der Code optimiert, zusammengefasst und Teile davon wieder in den Müll geworfen. Letztendlich hab ich dann ein sauber, gut durchstrukturiertes Programm. Das da natürlich viel Zeit drauf geht ist klar, aber wenn ich schnell was hinwurstel und es nimmt irgendwann Form an oder es artet sich doch zu etwas größeren, dann hat man noch mehr Zeitverlust. Nichts geht über ein klar gegliedertes Designdokument, wo alles festgehalten wird. Aber jeder macht das sowieso auf seine Art. Ich fahre ganz gut damit, das Hauptprogramm oder die Mainloop halte ich so kurz wie möglich und da kommen ausschließlich nur Funktionsaufrufe hin. So bin ich sehr flexibel. Auch vermeide ich Goto und Gosub's wo es nur geht! lg. Jamagin ![]() |
||
Bevor du etwas neues beginnst, erledige das alte |
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group