Wie ein groesseres Project angehen?
-
Da ich mich in "reinem" C++ inzwischen halbwegs gut zurecht finde, habe ich mal ein ein groesseres Project gedacht, also nicht immer nur den "ewigen Taschenrechner" ...
Wie aber gehe ich so ein Projekt als Anfaenger an?Also, ich habe mir folgendes ueberlegt:
Die Projektidee steht, mit anderen Worten, das Ziel ist bekannt. Allerdings habe ich bisher von grafischen Oberflaechen keine grosse Ahnung.
Ich koennte doch zunaechst mal alle wesentlichen Funktionen (Module) im 'Textmode' schreiben, denn ich arbeite ohnehin unter - und NUR - unter Linux. Also alles was rechnet, auf Datenbanken zugreift und letztlich auch Daten ausgibt.
Wenn das im Textmode (Console) dann so halbwegs klappt, dann waere der naechste Schritt das dann in einer grafischen Oberflaeche zusammen zu bringen.
Macht das so einen Sinn, oder muss ich dann praktisch alle Module noch mal neu schreiben?
Gruss
Guenther
immer noch in: Davao City, Philippines, Planet Earth
-
Das macht durchaus Sinn. Achte nur darauf, dass du eine abstrakte Ausgabe hast, dann kannst du ganz schnell von Konsole auf GUI umsteigen.
-
Michael E. schrieb:
Achte nur darauf, dass du eine abstrakte Ausgabe hast, dann kannst du ganz schnell von Konsole auf GUI umsteigen.
Hmm, was bitte meinst Du mit "abstrakte Ausgabe"?
-
Ich würde ein Projekt nicht von der Ausgabe abhängig machen.
Viel vernünftiger ist ein sauberes Klassen- und Schnittstellen-Design.
Und diese enthalten eine Benutzer-Schnittstelle, die dann konkret grafisch oder als Konsole ausfallen mag. Sich grundätzlich erst die Buttons zu übelegen und danach funktional die Operationen dahinter setzen bringt nur Mehrarbeit und Frustration mit sich.
-
crashterpiece schrieb:
Viel vernünftiger ist ein sauberes Klassen- und Schnittstellen-Design.
Tja, das sagt mir als Anfaenger leider recht wenig ...
crashterpiece schrieb:
Und diese enthalten eine Benutzer-Schnittstelle, die dann konkret grafisch oder als Konsole ausfallen mag. Sich grundätzlich erst die Buttons zu übelegen und danach funktional die Operationen dahinter setzen bringt nur Mehrarbeit und Frustration mit sich.
Letzteres wuerde ich natuerlich gern vermeiden.
Ein Beispiel: Bisher kann ich eine Kundennummer eingeben, die sucht mir dann die entsprechenden Daten in einer Datenbank und gibt mir diese - sofern gefunden - auf dem Bildschirm aus, wenn auch bisher in reinem Textmode.
Ist das jetzt ein grosses Problem, das spaeter mal als GUI darszustellen, also mit grafischer Oberflaeche, ohne alles noch mal neu zu schreiben?
-
Anfänger? Lass das mit der GUI
Kümmer dich lieber um sauberes Design, spiel ein bisschen rum (kommt automatisch, weil du mit deinem Aufbau nicht zufrieden sein wirst) und schau dir ein paar Design Patterns an.
-
Versuche, deine Funktionen und Klassen so aufzubauen, daß sie nicht direkt mit Eingabe- oder Ausgabeobjekten (IO) arbeiten.
Diese Klassen sollten z.B. niemals 'cin' und 'cout' direkt verwenden, denn die gibt es bei einer GUI dann nicht mehr.
Du mußt dann evtl. deine Funktionen (bzw. Klassenmethoden) mit zusätzlichen Parametern versehen, z.B. eine String-Variable, in der die Daten geschrieben werden.Hier ein Beispiel:
// Hauptprogramm, welches nachher durch eine GUI ersetzt werden kann int main() { std::string sInput; cin >> sInput; cout >> Calc(sInput); } // dein eigenes Berechnungsmodul (ohne IO) std::string Calc(const std::string &s) { std::string sCalc = s; // do something with sCalc return sCalc; }Du kannst auch std::vector oder std::list oder andere Klassen verwenden, welche nur mit dem Hauptspeicher arbeiten (also ohne IO), z.B. für Datenbankfunktionalität.
Bzgl. der IO-Streams solltest du dich evtl. auch mit Datei Ein- und Ausgabe beschäftigen, denn dann kannst du ebenfalls abstrahieren.
Du könntest die obere Funktion 'main' so umschreiben, daß sie nur so aussieht:
int main() { DoCalc(cin, cout); }Nun kannst du dann eine Funktion implementieren, welche von der konkreten EIn- und Ausgabe unabhängig ist:
#include <iostream> void DoCalc(std::istream &is, std::ostream &os) { std::string sInput; is >> sInput; os >> Calc(sInput); }Nun kannst du diese Funktion auch mit Datei-Streams aufrufen, z.B.
#include <fstream> int main() { std::ifstream iff("input.txt"); std::ofstream off("output.txt"); DoCalc(iff, off); }So das war's jetzt ersteinmal zum Thema Schnittstellen-Programmierung.
Bis zum nächsten Mal -)
-
Ich stimme meinen Vorrednern natürlich voll und ganz zu, allerdings bieten manche GUI-Toolkits eben mehr als nur eine grafische Oberfläche. So kannst du mit Qt auch Datenbanken ansteuern. Und dann läuft das halt alles schön nach einem Schema.
Was ich damit sagen will: es ist vielleicht nicht verkehrt, sich jetzt schon für 'nen GUI-Aufsatz zu entscheiden und dann verstärkt in die Richtung zu gehen und auch die anderen Funktionen zu nutzen. Welche Vorteile du mit Qt bei Datenbanken hast, kann ich dir leider nicht sagen. Ich stehe auch noch ganz am Anfang...
-
Ich stimme meinen Vorrednern eigentlich auch zu. Für Schnittstellen, bzw. portieren zwischen verschiedenen GUIs (bzw. von der Konsole zu einer GUI) empfehle ich dir ein MVC-Modell. Kannst vielleicht mal im Inet nach MVC suchen, gibt da überall verschiedene Einträge. Eigentlich geht es darum, Daten von der Ausgabe zu trennen. MVC steht schliesslich auch für Model View Controller, also Modell Ansicht Steuereinheit.
Was ich dir aber auch empfehlen kann, hüpf ins kalte Wasser! Also mir hat das unheimlich geholfen. Ich bin voller optimismus und gross gekotzt an mein erstes grosses Projekt ran. Es hat am Ende funktioniert, aber ich habe viel gelernt und nach einem Jahr support wusste ich dann auch nochmals einiges mehr

Ansonsten gibt es auch Bücher zur Projektplanung. Da kann man natürlich sehr ins komplexe gehen. Zum Beispiel Gantt-Charts, wann du was und wie fertig haben willst, welcher Arbeit von was abhängt usw. ^^
Zwei Tipps vielleicht noch: UML und Codebeschriftung

Ansonsten, das Thema ist eben riesig. Buch kaufen oder einfach mal probieren und lernen

Grüssli
-
versuch dir bei sowas immer klar zu machen, wo programmlogik steckt, wo daten rumgeschubst werden und wo interaktion mit dem benutzer stattfindet. MVC deckt nur ein teilgebiet davon ab.
wenn man beispielsweise eine ID auf gültigkeit überprüfen möchte, besteht das ganze aus drei teilaufgaben:
- beschaffung der ID
- berechnung der gültigkeit
- präsentation des ergebnissesdie berechnung der gültigkeit ist reine programmlogik. das ist ein modul, welches man problemlos völlig abstrakt implementieren kann.
boolean validate(std::string id);das ding kann nichts weiter, als eine id auf gültigkeit zu prüfen. jetzt möchte man die methode natürlich mit daten füttern. woher bekommt man die? zum testen steckt man da vielleicht nen hart kodierten string rein. für seine konsolenanwendung liest man die evtl. aus cin, oder übergibt sie als programm parameter. wenn man das stückchen logik in eine GUI anwendung klebt, kommt die eingabe vielleicht aus einer textbox.
und ähnlich siehts mit der präsentation aus. die kann in eine datei geschoben werden, oder auf der konsole passieren oder vielleicht ein grüner button im GUI.
wenn man eine anwendung sauber gestaltet und darauf achtet, logik und I/O immer strikt voneinander zu trennen, dann ist es völlig problemlos möglich, ein und dieselbe anwendung einmal als konsolenanwendung und einmal als GUI anwendung auszuliefern.
-
im allgemeinen finde ich es sinnvoll, wenn nicht nur das ziel fest steht, sondern auch diverse planungen.
wenn man sich im vornherein gedanken darüber macht, wie man alles an gehn will (stichwort UML), dann ist die implementierung eigentlich nebensache. bei einer guten planung schreibt man seine klassendiagramme, MSCs etc einfach ab und es läuft. allerdings nimmt eben die planung recht viel zeit in anspruch, was einen auch wieder davon ab hält. hatte mal in java n projekt, in dem ich zwei wochen vor "abgabe" mein komplettes internes klassenkonzept über den haufen geschmissen habe. das war nicht ideal und ich hätte es mir mit gescheiter planung sparen können, allerdings hatte ich die schnittstellen so definiert, dass das austauschen des ganzen konzeptes nicht das problem war.
-
Was die Abstrakte Ausgeb angeht: such mal im netz nach "MVC-paradigma" oder "model-viewer-controller" - da findest du eine Idee dessen, was gemeint war. Trenne deine Programmlogik so weit wie moeglich von Ein- und Ausgabe, dann ists am Ende einfacher, letztere zu ersetzen (z.B. Konsole durch GUI)
-
Ein wirkliches gutes Projekt steht schon, bevor die erste Zeile Code implementiert wurde.
Oder: Wer bei Projekten stets an das Programmieren denkt, der wird nie weit kommen.
Klassische Arbeitsschritte sind:
Analyse - Was gibt es bereits, wie wird das gemacht
Anforderungen - Was muss das Programm können
Design - Wie muss es das leisten
Konstruktion - Wie baue ich die Module / Klassen etc auf
Implementierung
Testen
LaunchMit guten Tools lassen sich die Design- und Konstruktionsschritte zB direkt als Code-Rahmen für ein Programm ausgeben
die eigentliche Implementierung ist dann nur Wischi-waschi
weniger Wochen
-
ich würde allerdings während der implementierung halt die einzelnen module / submodule etc jeweils eingängig testen
-
Wenn du noch nie was mit GUI gemacht hast, dann mach erst mal ein paar GUI Übungsprogramme. Dann siehst du wie das funktioniert und kommst auch ein bisschen von der "Konsolendenkweise" weg.
Einigermasen vernünftiges Design (MVC,...) wirst du beim ersten mal sowieso nicht gleich hin bekommen. Natürlich ist es gut MVC zukennen, aber ohne verständnis für das was ein UI kann und wie es funktioniert, wirst du es sehr wahrscheinlich nicht verstehen bzw. richtig umsetzen können.
-
Zwischendurch schon mal ein grosse DANKESCHOEN fuer Eure Muehe und die offensichtlich tollen Ratschlaege.
Ich werd's mir nachher mal in Ruhe durchlesen und mich dann noch mal mit einem Fazit melden.
Gruss
Guenther
-
Neben all dem, was ich beim Studium der vielen guten Ratschlaege gelernt und/oder begriffen habe, scheint es mir besonders wichtig zu sein, dass bei meinen naechsten Schritte mein Hauptaugenmerk wirklich auf die strikte Trennung von Logik und I/O gerichtet sein sollte. Etwas, was ich aber 'relativ' einfach umsetzen kann, da ich intuitiv den Grossteil meiner Programmlogik ohnehin schon in jeweils einzelne Funktionen gelegt habe.
Ich denke aber auch, dass es tatsaechlkich hilfreich sein duerfte, wenn ich mich daneben in den naechsten Tagen mal ein kleines GUI Projekt wage, also einfach nur so zum Test, damit ich's 'mal gesehen habe'. Das sollte mir helfen, das Ganze noch ein wenig besser verstehen zu koennen.
Aber wie gesagt, nur zum Test und nur mal zwischendurch. Ansonsten werde ich weiter meine Funktionen entwickeln, bei denen ich Ein- und Ausgabe in die main() 'auslagere' und natuerlich hoffen, dass ich dann spaeter wirklich all diese Funktionen ohne grosse Aenderungen in die geplante GUI Version uebernehmen kann.
Ansonsten heisst es fuer mich 'ueben, ueben, ueben ...', denn bekanntlich ist es die Uebung, die den Meister macht! Und an manchen Tagen laeuft's wirklich schon recht gut. Es gibt aber natuerlich auch Tage, da bin ich leicht am Zweifeln, weil ploetzlich ueberhaupt nichts klappt. So wie gestern, als ich versucht habe ein Programm mit
g++ -v -o example -lncurses example.cppstatt mit
g++ -v -o example example.cpp -lncurseszu uebersetzen und mich dann wundere, dass der Linker immer die fehlende Library anmeckert ...

Aber nun gut, dass sind die Fehler, aus denen man(n) lernt ...
Nochmals vielen Dank fuer Eure Hilfe ...

Guenther
-
das ist der grund, warum es IDEs gibt
wenn man weiss, dass der compiler mit "g++ in.c -o out" aufgerufen wird, hat man genug gelernt und kanns ab da einem IDE überlassen.
-
gboelter schrieb:
Es gibt aber natuerlich auch Tage, da bin ich leicht am Zweifeln, weil ploetzlich ueberhaupt nichts klappt.
Die wird es immer geben, passiert mir auch nach ~4 Jahren mit C++ immer wieder mal

-
weiß net, finde von hand compilieren eh schwachsinnig, außer du hast genau 1 file zu compilieren
nimm halt zur not einfach make, des is echt schön, kann man so richtig lustige logik einbauen (und makefiles zusammen stöpseln, die keiner mehr lesen kann :D)