HaRe - Home
Basis einer professionellen Softwareentwicklung
Es werden die grundlegendsten Voraussetzungen für jede x-beliebige Software-Entwicklung beschrieben. Dazu zählen
- vor allem eine Quellcodeverwaltung
- und u.U.
Abbildung eines professionellen Entwicklungsumfeldes
(bekannt als Continuous Integration).
Im Zuge der Entwicklung einer Software wechselt der Zustand des
Produkts immer wieder zwischen "im Umbau befindlich" und "stabil".
Während der Umbautphasen werden u.U. Teile verworfen, die
später möglicherweise in einem anderen Zusammenhang
wieder brauchbar wären und für die Produktion oder auch
Präsentationen werden die stabilen Versionen
benötigt.
Um effizient entwickeln zu können, sollten alle Artefakte, die
zu einem Projekt gehören schnell und einfach erreichbar
sein.
Diese Anforderungen werden durch die Verwendung einer
Quellcodeverwaltung (und einer Entwicklungsumgebung) abgedeckt.
In diesem Beispiel verwende ich CVS und Eclipse.
Für CVS spricht die weite Verbreitung und die von RCS gewohnte
Dateistruktur, die dem Administrator auch lokale Hacks
ermöglicht. In einem anderen Umfeld erscheint mir heute
Subversion die bessere Wahl.
Für Eclipse spricht der große Bekanntheitsgrad. Je nach
Anwendungsfall ist eine andere IDE empfehlenswert und die
Integration einer Quellcodeverwaltung ist praktisch in jeder IDE
enthalten.
Für Selbststudium wird für CVS das cvsbook empfohlen.
Quellcodeverwaltung
Achtung! Alle Daten werden auf /tmp abgelegt und werden somit üblicherweise beim nächsten Rechnerstart gelöscht. Sollte das nicht gewünscht sein, so sollte zumindest /tmp/cvsroot z.B. auf /var/lib/cvs geändert werden.
Auf /tmp ein Arbeitsverzeichnis mit ein paar Beispieldateien
erstellen.
Weiters ein Verzeichnis fü CVS erstellen und
initialisieren.
Starting A Repository ~$ mkdir /tmp/cvsroot ~$ cvs -d /tmp/cvsroot/ init ~$ ls /tmp/cvsroot/ CVSROOT ~$ ls /tmp/cvsroot/* checkoutlist cvswrappers,v notify posttag,v taginfo checkoutlist,v Emptydir notify,v postwatch taginfo,v commitinfo history postadmin postwatch,v val-tags commitinfo,v loginfo postadmin,v preproxy verifymsg config loginfo,v postproxy preproxy,v verifymsg,v config,v modules postproxy,v rcsinfo cvswrappers modules,v posttag rcsinfo,v Starting A New Project ~$ mkdir /tmp/test ; cd $_ /tmp/test$ mkdir dir1 dir2 /tmp/test$ touch test0 dir1/test1 dir2/test2 /tmp/test$ cvs -d /tmp/cvsroot/ import -m '' cvstest hare start /tmp/test$ ls /tmp/cvsroot/ CVSROOT cvstest /tmp/test$ ls /tmp/cvsroot/cvstest/* /tmp/cvsroot/cvstest/test0,v /tmp/cvsroot/cvstest/dir1: test1,v /tmp/cvsroot/cvstest/dir2: test2,v /tmp/test$ ls * test0 dir1: test1 dir2: test2 Checking Out A Working Copy /tmp/test$ cd .. /tmp$/ cvs -d /tmp/cvsroot/ checkout cvstest /tmp$ cd cvstest/ /tmp/cvstest$ ls * test0 CVS: Entries Repository Root dir1: CVS test1 dir2: CVS test2 /tmp/cvstest$ more CVS/* :::::::::::::: CVS/Entries :::::::::::::: /test0/1.1.1.1/Wed Apr 16 06:49:50 2008// D/dir1//// D/dir2//// :::::::::::::: CVS/Repository :::::::::::::: cvstest :::::::::::::: CVS/Root :::::::::::::: /tmp/cvsroot/ /tmp/cvstest$ echo "Neuer Text fuer Version 1.0" >> test0 /tmp/cvstest$ echo "Neuer Text fuer Version 1.0" >> dir1/test1 /tmp/cvstest$ cvs diff cvs diff: Diffing . Index: test0 =================================================================== RCS file: /tmp/cvsroot/cvstest/test0,v retrieving revision 1.1.1.1 diff -r1.1.1.1 test0 0a1 > Neuer Text fuer Version 1.0 cvs diff: Diffing dir1 Index: dir1/test1 =================================================================== RCS file: /tmp/cvsroot/cvstest/dir1/test1,v retrieving revision 1.1.1.1 diff -r1.1.1.1 test1 0a1 > Neuer Text fuer Version 1.0 cvs diff: Diffing dir2 /tmp/cvstest$ cvs commit -m 'Erste Aenderungen' /tmp/cvstest$ cvs tag Version-1_0 /tmp/cvstest$ cvs log -h cvs log: Logging . RCS file: /tmp/cvsroot/cvstest/test0,v Working file: test0 head: 1.2 branch: locks: strict access list: symbolic names: Version-1_0: 1.2 start: 1.1.1.1 hare: 1.1.1 keyword substitution: kv total revisions: 3 ============================================================================= cvs log: Logging dir1 RCS file: /tmp/cvsroot/cvstest/dir1/test1,v Working file: dir1/test1 head: 1.2 branch: locks: strict access list: symbolic names: Version-1_0: 1.2 start: 1.1.1.1 hare: 1.1.1 keyword substitution: kv total revisions: 3 ============================================================================= cvs log: Logging dir2 RCS file: /tmp/cvsroot/cvstest/dir2/test2,v Working file: dir2/test2 head: 1.1 branch: 1.1.1 locks: strict access list: symbolic names: Version-1_0: 1.1.1.1 start: 1.1.1.1 hare: 1.1.1 keyword substitution: kv total revisions: 2 =============================================================================Mit Absicht schon erste Änderungen für Version 2, obwohl am Server eigentlich Version 1 gewünscht sein wird.
/tmp/cvstest$ echo "Neuer Text fuer Version 2.0" >> dir1/test1 /tmp/cvstest$ echo "Neuer Text fuer Version 2.0" >> dir2/test2 /tmp/cvstest$ cvs commit -m "Erste Aenderungen fuer V2"Am Server, auf dem die Anwendung letztendlich laufen soll. So wie das Beispiel gemacht wurde ist es gleichgültig, ob am gleichen Rechner oder einem anderen Rechner gearbeitet wird.
Fälschlicherweise wird zuerst die Entwicklungsversion ausgecheckt und dann erst auf die Version 1.0 zurück gewechselt.
/tmp/cvstest$ mkdir /tmp/server ; cd $_ /tmp/server$ cvs -d :extssh:user@rechner:/tmp/cvsroot checkout cvstest /tmp/server$ cd cvstest/ /tmp/server/cvstest$ cat dir1/test1 Neuer Text fuer Version 1.0 Neuer Text fuer Version 2.0 /tmp/server/cvstest$ cvs update -r Version-1_0 /tmp/server/cvstest$ cat dir1/test1 Neuer Text fuer Version 1.0Version 2 fertig stellen und den Server auf Version 2 aktualisieren.
Wegen Problemen mit Version 2 danach wieder zurücksetzen auf Version 1.
/tmp/server/cvstest$ cd /tmp/cvstest /tmp/cvstest$ echo "Neuer Text fuer Version 2.0" >> test4 /tmp/cvstest$ cvs add test4 /tmp/cvstest$ cvs commit -m "Weitere Aenderungen fuer V2" /tmp/cvstest$ cvs tag Version-2_0 /tmp/cvstest$ cd /tmp/server/cvstest/ /tmp/server/cvstest$ cvs update -r Version-2_0 /tmp/server/cvstest$ ls CVS dir1 dir2 test0 test4 /tmp/server/cvstest$ cvs update -r Version-1_0 /tmp/server/cvstest$ ls CVS dir1 dir2 test0
Entwicklungsumgebung
EclipseOpen Perspective - CVS Repository Exploring
CVS Repositories - Rechtsklick - New - Repository Location
Host: localhost, Repository path: /tmp/cvsroot, Connection Type: extssh
bißchen herumblättern
dann HEAD/cvstest auschecken
rsnapshot
Mit rsnapshot kann sichergestellt werden, dass die Änderungen eines Tages regelmäßig, beispielsweise stündlich, automatisch gesichert werden, ohne viel Festplattenplatz oder CPU-Zeit zu verschwenden oder ein zusätzliches Speichermedium zu benötigen.
Debian und Derivate (u.a. Ubuntu)
# apt-get install rsnapshot
Next steps
Basierend auf der Quellcodeverwaltung sollten Tests (mit Alarmierung bei Problemen) und Softwareverteilung der Testversion automatisiert werden.
Bsp.: bei jedem Einchecken oder zumindest einmal nachts soll in
ein Testverzeichnis ein aktueller Snapshot geholt werden und das
Ergebnis der Tests per E-Mail verteilt werden. Es ist sinnvoll ein
positives Ergebnis nicht zu unterdrücken, da ansonsten eine
Fehlfunktion kaum bemerkt wird, allerdings sollte im Subject schon
erkennbar sein, ob es Fehler gab oder nicht.
Gerade bei einer Webanwendung kann ebenfalls automatisiert ein
Testsystem für den Kunden sehr einfach aktuell gehalten
werden. Auch hier sollte das Ergebnis der eventuell notwendigen
DB-Migrationsskripte und des Serverstarts per E-Mail verschickt
werden.
Typisches Anwendungsszenario
Ein Entwickler checkt seine Arbeit ein. Diese Aktion veranlasst
die Aktualisierung einer Testversion und die Unit-Tests starten.
Das Ergebnis der Unit-Tests wird dem Entwickler per E-Mail
übermittelt.
Jede Nacht wird automatisch ein job gestartet, der die
Testversion aktualisiert und die Unit-Tests startet. Das Ergebnis
der Unit-Tests wird allen Entwicklern per E-Mail
übermittelt.
Wenn die Tests fehlerfrei ablaufen, wird auch das Testsystem aktualisiert, das dem Kunden zur Verfügung steht.