Forum: Mikrocontroller und Digitale Elektronik Programm wie am besten strukturieren und dokumentieren?


von Ingo (Gast)


Lesenswert?

Hallo,

Ich möchte demnächst ein größeres Projekt gemeinsam mit einem Freund 
angehen. Wir haben uns vorgenommen dies mal absolut sauber und 
transparent sowie einfach wartbar zu programmieren. Programmiert wird 
mit der CoIDE ein STM32F415.

Jetzt ein paar Fragen:
1. Gibts es ein gutes Tool mit dem man die Softwareversionen sauber 
dokumentieren kann (Versionsnummer, Änderungen, To-Do etc)? Excel evtl.?

2. Sind globale Variablen nötig bzw. lassen sie sich überhaupt 
vermeiden? Ich würde halt alles Modular aufbauen wollen, das heißt jeder 
Hardwareabchnitt bekommt ein eigenes Modul (Source-File) und die Daten 
werden über Pointer geändert bzw. ausgetauscht.

3. Was muss vereinbart werden wenn zwei Leute an einem Programm 
arbeiten? Codestyle? Und was noch?


Ingo

von Mark B. (markbrandis)


Lesenswert?

Ingo schrieb:
> 3. Was muss vereinbart werden wenn zwei Leute an einem Programm
> arbeiten? Codestyle? Und was noch?

Versionsverwaltung für den Sourcecode --> z.B. Git oder Subversion 
verwenden

von Ralph (Gast)


Lesenswert?

Ingo schrieb:
> Wir haben uns vorgenommen dies mal absolut sauber und
> transparent sowie einfach wartbar zu programmieren

Gute Idee

zu 1.
Ja gibt es.
sieh hier:
http://en.wikipedia.org/wiki/Comparison_of_revision_control_software

Excel ist da eine sehr schlechte Idee.

zu 2.
Ohne Globale Variablen werdet ihr in den Modulen nicht auskommen.
Aber die wenigsten werden über EXTERN den anderen Modulen bekannt 
gegeben.

Pointer sind so ne Sachen. Dadurch werden solche Zugriffe über Module 
hinweg zwar einfach möglich, sie bieten aber auch ein Potenzial um 
Schaden anzurichten. zb, der Pointer zeigt auf ein Byte aber geschrieben 
wird ein Word.
Meiner Meinung nach sind Funktionsaufrufe in diesem Fall besser.
zb ein Modul bietet eine globale Funktion um einen Zähler zu setzen.

void SetCounterValue(Uint16 Value)

Diese Funktion ist Global verfügbar und jedes andere Modul ruft genau 
diese Funktion auf um den Zähler zu setzen.
Damit ist sichergestellt das die Variablengrößen sauber zusammen passen.

Genauso dann auch mit den Lesezugriffen verfahren.
Also alle Variablen die von anderen Modulen gelesen oder geschrieben 
werde sollen werden in eigene Funktionen eingepackt.

Das gleiche dann auch für Aktionen wie zb einen Pin setzen oder einen 
Timer starten.

zu3.
Codestyle, ja sicher.  (Wie)

Wer macht was und wann ? sonst kann es leicht passieren das Arbeiten 
doppelt gemacht werden, bzw gar nicht weil jeder denkt der andere macht 
es.
Das heißt also eine Planung und Verteilung von Arbeitspaketen.

von Ingo (Gast)


Lesenswert?

Ja, dass mit den Funktionsaufrufen hatte ich auch so ähnlich vor.
Welches Programm für eine Versionsverwaltung ist denn zu empfehlen?


Vielen Dank schonmal...


Ingo

von MS (Gast)


Lesenswert?

Ralph schrieb:
> zu 2.
> Ohne Globale Variablen werdet ihr in den Modulen nicht auskommen.

Warum nicht? Im Idealfall kommt man ganz ohne globale Variablen aus. Das 
sollte man anstreben und es ist auch möglich.

> Aber die wenigsten werden über EXTERN den anderen Modulen bekannt
> gegeben.

Diesen Satz verstehe ich nicht. Abhängigkeiten sollten die Module 
jedenfalls von außen (z.B. vom Aufrufer) übergeben bekommen, und sich 
nicht selbst suchen müssen.


Du kannst dir auch einmal “testgetriebene Entwicklung“. Die hilft eine 
saubere Architektur aufzuziehen.

von Fabian O. (xfr)


Lesenswert?

Ingo schrieb:
> Welches Programm für eine Versionsverwaltung ist denn zu empfehlen?

Die beiden verbreiteten sind SVN und Git. Git bietet für 
Fortgeschrittene mehr Möglichkeiten. Aber wenn ihr vorher noch nie mit 
Versionsverwaltung gearbeitet habt, tut ihr euch mit SVN wahrscheinlich 
leichter.


> Sind globale Variablen nötig bzw. lassen sie sich überhaupt
> vermeiden?
Sie lassen sich komplett vermeiden. Schau mal in diesen Beitrag: 
Beitrag "Re: Sauber Programmieren mit Interrupts"

Kurzfassung: Nur modul-globale Variablen (static) und in Funktionen 
lokale Stackvariablen verwenden.


> Ich würde halt alles Modular aufbauen wollen, das heißt jeder
> Hardwareabchnitt bekommt ein eigenes Modul (Source-File)

Guter Ansatz.

> und die Daten werden über Pointer geändert bzw. ausgetauscht.

Nicht so gut, zumindest nicht als grundsätzliche Vorgehensweise. Für 
jede Variable bzw. jedes Datum sollte in jedem Programmzustand nur genau 
ein Modul zugriffsberichtigt sein. Das stellt man am einfachsten sicher, 
indem die Daten nach außen nur "by value" übergeben werden:
1
static int counter;
2
3
int get_counter(void) {
4
  return counter;
5
}
6
7
void set_counter(int value) {
8
  counter = value;
9
}

Ein anderes Modul hat auf die Weise keine Chance, die Variable counter 
unerwartet zu modifizieren. Man kann in die get- und set-Funktionen 
gegebenfalls zusätzliche Überprüfungen einbauen oder den Aufruf an ein 
anderes Modul bzw. Hardware delegieren.

Man sollte allerdings hellhörig werden, wenn man auf eine Modulvariable 
sowohl per get- als auch per set-Funktion zugreifen kann. Oft wäre ein 
anderes Interface passender, hier zum Beispiel:
1
static int counter;
2
3
int get_counter(void) {
4
  return counter;
5
}
6
7
void counter_increase(void) {
8
  if (counter < INT_MAX) {
9
    counter++;
10
  }
11
}
12
13
void counter_decrease(void) {
14
  if (counter > INT_MIN) {  
15
    counter--;
16
  }
17
}

Das geht natürlich nur mit kleinen Datentypen. Größeren Strukturen by 
value übergeben wäre ineffizient, da kommt man um Zeiger nicht rum. 
Trotzdem sollte man festlegen, wer die Zuständigkeit über die Daten an 
dem Zeiger hat. Wenn beispielsweise Modul A einen Zeiger auf eine eigene 
Modulvariable a_x an das Modul B übergibt, wechselt die Zuständigkeit 
über a_x von Modul A nach B. Das heißt, Modul A darf nicht mehr auf a_x 
zugreifen, solange B an den Daten arbeitet:
1
// Modul A
2
3
static int a_x;
4
5
void eine_funktion(void) {
6
  mach_etwas(&a_x);
7
}
1
// Modul B
2
3
void mach_etwas(int* p) {
4
  *p = 5;
5
}

Man muss also festlegen, wie lange B die Zuständigkeit behält. 
Sinnvollerweise beschränkt man sich auf die Dauer das Funktionsaufrufs. 
B darf also nur innerhalb der Funktion mach_etwas() auf die Daten des 
Zeigers zugreifen. B darf sich den Zeiger nicht irgendwo speichern und 
später wieder von alleine auf die Daten zugreifen. Das sollte in der 
Dokumentation zu mach_etwas() erwähnt werden oder als Standard im 
Projekt festgelegt werden.

In anderen Fällen kann es sinnvoll sein, dass B die Zuständigkeit länger 
behält. B speichert sich also den Zeicher, bis es ihn über eine 
Callbackfunktion zurück gibt oder ihm der Zeiger über ein andere 
Funktion entzogen wird. Währenddessen darf kein anderes Modul (auch 
nicht A) etwas mit den Daten machen. Das gehört natürlich ebenfalls 
dokumentiert und muss eingehalten werden.


> 3. Was muss vereinbart werden wenn zwei Leute an einem Programm
> arbeiten? Codestyle? Und was noch?

Das wichtigste ist, sich Gedanken um die Gesamtarchitektur und die 
Schnittstellen zwischen den Modulen zu machen. Stichwort: Lose Kopplung, 
starke Bindung. Was zusammen gehört, muss zusammengefasst und gekapselt 
sein. Die Schnittstelle eines Moduls gibt nur die Informationen bekannt, 
die der Programmierer braucht, um es zu benutzen. Die Schnittstelle ist 
so zu gestalten, dass die Benutzung des Moduls so klar und einfach wie 
möglich ist (und nicht etwa so, wie sich die Funktion innerhalb des 
Moduls am leichtesten programmieren lässt!). Außerdem klare Bezeichner 
wählen und sauber dokumentieren. Dem Benutzer des Moduls muss nach einem 
Blick ins Header-File klar sein, wie er das Modul zu benutzen hat, ohne 
den dazugehörigen Quellcode zu kennen.

Wenn es sich nicht von alleine ergibt wäre es auch sinnvoll, 
Zuständigkeiten zu vereinbaren. Das heißt, für jedes Modul ist ein 
Entwickler federführend. Änderungen an dem Modul, abgesehen von 
offensichtlichen Bugfixes, müssen mit dem für das Modul Zuständigen 
abgesprochen werden. Derjenige kann dadurch verhindern, dass an das 
Modul mit der Zeit immer neue, kleine Hacks und Erweiterungen 
drangebastelt werden, die da eigentlich nicht hingehören. Außerdem 
müssen sich bei Schnittstellenänderungen immer alle Betroffenen 
absprechen oder zumindest informiert werden. Deshalb lohnt es sich, 
ordentlich Zeit in den Entwurf einer sauberen und stabilen Schnittstelle 
zu stecken, die man im Idealfall nie mehr ändern muss.

Einen Codestyle zu vereinbaren ist auf jeden Fall sinnvoll, damit der 
Code einheitlich aussieht. Das ist nicht nur eine ästhetische Frage, 
sondern hilft auch Fehler leichter zu finden und zu vermeiden.

von Hans Ulli K. (Gast)


Lesenswert?

Ingo schrieb:
> Hallo,
>
>
> Jetzt ein paar Fragen:
> 1. Gibts es ein gutes Tool mit dem man die Softwareversionen sauber
> dokumentieren kann (Versionsnummer, Änderungen, To-Do etc)? Excel evtl.?
>

Meine Empfehlung ist git.
Ich hatte mal ein wenig mit SVN (Subversion) gearbeit, Bin aber nacher 
auf git umgestiegen.
Wenn zwei oder mehr Leute an einem Projekt arbeiten ist es mit SVN sehr 
schwierig die einzelnen Zweige (Test/Bugfix usw.9 wieder zusammen zu 
führen.

Was bei git auch noch ein Vorteil ist, du branchst zum Arbeiten 
(commiten und Co.) kein Netzwerk, alles ist lokal auf deiner Platte. 
Erst wenn du es willst man du einen push und lädst die Sache auf 
deinen/euren Server hoch.


>
> 3. Was muss vereinbart werden wenn zwei Leute an einem Programm
> arbeiten? Codestyle? Und was noch?
>

Schau mal im linux Quellcode unter
Documentation/CodingStyle

von Rolf Magnus (Gast)


Lesenswert?

Ingo schrieb:
> Jetzt ein paar Fragen:
> 1. Gibts es ein gutes Tool mit dem man die Softwareversionen sauber
> dokumentieren kann (Versionsnummer, Änderungen, To-Do etc)? Excel evtl.?

z.B. trac zusammen mit SVN.

von Dennis (Gast)


Lesenswert?

@Fabian O. (xfr)

Danke dir für den super Beitrag, so gut erklärt hat es mir bisher auch 
noch keiner!

von Ingo (Gast)


Lesenswert?

Hallo Fabian, besten Dank für den ausführlichen Beitrag. Ich bin 
gespannt ob sich das alles so umsetzen lässt?

Ich werde mir Git und SVN mal anschauen. Vielen Dank!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.