Testbasierte SW-Entwicklung - public.fh

Werbung
Die verschiedenen Programmierparadigmen von C++
© Helmke
Clicker-“Abstimmung“
Kennen Sie testbasierte Software-Entwicklung/test-first?
1. Häh???
2. Habe ich schon mal gehört, aber im Moment nicht präsent.
3. Ja und lassen Sie mich kurz denken, dann erkläre ich es der
gesamten Vorlesung
4. Ja, das machen wir in unserer Gruppe schon seit Jahren
5. Ja bin ich mit vertraut, aber ich sehe die Vorteile nicht.
WS 2015/16
V 4.01; © Hon. Prof. Helmke
1
Die verschiedenen Programmierparadigmen von C++
© Helmke
Clicker-“Abstimmung“
Sagt, Ihnen „Think, Red-Bar, Green-Bar, Refactor“ im Sinne von
testbasierter Softwareentwicklung etwas?
1. Häh???
2. Habe ich schon mal gehört, aber im Moment nicht präsent.
3. Ja und lassen Sie mich kurz denken, dann erkläre ich es der
gesamten Vorlesung
WS 2015/16
V 4.01; © Hon. Prof. Helmke
2
Die verschiedenen Programmierparadigmen von C++
© Helmke
Lernziele
•
•
WS 2015/16
Was bedeutet „Test first“?
Was bedeuten „Think, Red Bar, Green Bar, Think“?
V 4.01; © Hon. Prof. Helmke
3
Die verschiedenen Programmierparadigmen von C++
© Helmke
Testbasierte Software-Entwicklung
Think
Red Bar
Green Bar
Refactor
WS 2015/16
V 4.01; © Hon. Prof. Helmke
4
Die verschiedenen Programmierparadigmen von C++
© Helmke
Beispiel bzw. Wiederholung: Funktion, die auf Primzahl testet
Think
Red Bar
Green Bar
Aufgabe: Implementierung einer
Funktion „istPrim“, die ermittelt,
ob das Argument eine Primzahl
ist oder nicht.
bool istPrim(int zahl);
Refactor
/** 2 und 3 sind Primzahlen,
4 nicht.
Bei den größeren Zahlen gilt: Zahlen, die
durch 2 und 3 teilbar sind, sind keine Primzahlen.
*/
bool istPrim(int zahl);
WS 2015/16
V 4.01; © Hon. Prof. Helmke
5
Die verschiedenen Programmierparadigmen von C++
© Helmke
Red Bar: Einfacher Testfall
/** istPrim wird für 2 und 3 aufgerufen,
true wird jeweils erwartet
istPrim wird für 4 aufgerufen, false wird
erwartet
*/
bool testPrim234() {
bool testPrim234();
bool result = true;
result = (true == istPrim(2)) && result;
result = (true == istPrim(3)) && result;
result = (false == istPrim(4)) && result;
bool istPrim(int zahl){
return result;
return false;
}
}
WS 2015/16
V 4.01; © Hon. Prof. Helmke
6
Die verschiedenen Programmierparadigmen von C++
© Helmke
Red Bar: Hauptprogramm
int main() {
Noch scheitert der Test.
if (true== testPrim234 ()) {
cout << "Alle Tests erfolgreich.\n";
}
else {
cout << "Tests gescheitert.\n";
}
}
WS 2015/16
V 4.01; © Hon. Prof. Helmke
7
Die verschiedenen Programmierparadigmen von C++
© Helmke
Green Bar:
bool istPrim(int zahl){
if (2== zahl) {return true;}
if (3== zahl) {return true;}
Tests laufen nun
return false;
(green bar).
}
WS 2015/16
V 4.01; © Hon. Prof. Helmke
8
Die verschiedenen Programmierparadigmen von C++
© Helmke
Hauptprogramm: Komplexerer Fall
int main() {
Noch scheitert der Test.
if ((true== testPrim234 ()) &&
(true== testPrim56Etc ()) {
{
cout << "Alle Tests erfolgreich.\n";
}
else {
cout << "Tests gescheitert.\n";
}
}
WS 2015/16
V 4.01; © Hon. Prof. Helmke
9
Die verschiedenen Programmierparadigmen von C++
© Helmke
Red Bar: Testfälle 5 bis 10
/** istPrim wird für 5 bis 10 aufgerufen,
true, false, true, false, false, false wird
erwartet
*/
bool testPrim56Etc();
bool testPrim56Etc() {
bool result = true;
result = (true == istPrim(5)) && result;
result = (false == istPrim(6)) && result;
result = (true == istPrim(7)) && result;
result = (false == istPrim(8)) && result;
bool istPrim(int zahl){
result = (false == istPrim(9)) && result;
if (2== zahl) {return true;}
result = (false == istPrim(10)) && result;
if (3== zahl) {return true;}
return result;
return false;
}
}
WS 2015/16
V 4.01; © Hon. Prof. Helmke
10
Die verschiedenen Programmierparadigmen von C++
© Helmke
Green Bar:?
/** Teile zahl durch alle Zahlen 2, 3, 5, 7, 9, 11, ...
bis Wurzel(zahl). Wenn eine davon Teiler von Zahl ist,
dann ist zahl keine Primzahl, sonst Rückgabe true
\param[in] zahl
\return true, wenn zahl Primzahl
Notizen:
*/
• 3 mit for-Schleife zusammenfassen
bool istPrim(int zahl){
if (2== zahl) {return true;}
• für -1, 0, 1 prüfen
if (3== zahl) {return true;}
• für große Zahlen auch Tests bauen
if (0== (zahl%2)) {return false;}
int wurzel = static_cast<int>( sqrt(static_cast<double>(zahl)));
for (int i=3; i < wurzel; i=i+2) {
if ( 0== (zahl%i)) {
return false;
}
Tests scheitern noch beim Wert 9!
}// for i
return true;
}
WS 2015/16
V 4.01; © Hon. Prof. Helmke
11
Die verschiedenen Programmierparadigmen von C++
© Helmke
Green Bar:
/** Teile zahl durch alle Zahlen 2, 3, 5, 7, 9, 11, ...
bis Wurzel(zahl). Wenn eine davon Teiler von Zahl ist,
dann ist zahl keine Primzahl, sonst Rückgabe true
\param[in] zahl
\return true, wenn zahl Primzahl
*/
Tests laufen
nun
bool istPrim(int zahl){
(green bar).
if (2== zahl) {return true;}
if (3== zahl) {return true;}
if (0== (zahl%2)) {return false;}
int ende = 1 + static_cast<int>( sqrt(static_cast<double>(zahl)));
for (int i=3; i < ende; i=i+2) {
if ( 0== (zahl%i)) {
return false;
Notizen:
}
• 3 mit for-Schleife zusammenfassen
}// for i
• für -1, 0, 1 prüfen
return true;
• für große Zahlen auch Tests bauen
}
WS 2015/16
V 4.01; © Hon. Prof. Helmke
12
Die verschiedenen Programmierparadigmen von C++
© Helmke
Refactoring: 3 mit for-Schleife zusammenfassen
/** Teile zahl durch alle Zahlen 2, 3, 5, 7, 9, 11, ...
bis Wurzel(zahl). Wenn eine davon Teiler von Zahl ist,
dann ist zahl keine Primzahl, sonst Rückgabe true
\param[in] zahl
\return true, wenn zahl Primzahl
*/
bool istPrim(int zahl){
if (2== zahl) {return true;}
if (0== (zahl%2)) {return false;}
int ende = 1 + static_cast<int>( sqrt(static_cast<double>(zahl)));
for (int i=3; i < ende; i=i+2) {
if ( 0== (zahl%i)) {
return false;
}
Notizen:
}// for i
• für -1, 0, 1 prüfen
return true;
• für große Zahlen auch Tests bauen
}
WS 2015/16
V 4.01; © Hon. Prof. Helmke
13
Die verschiedenen Programmierparadigmen von C++
© Helmke
Red Bar: Testfälle Zahlen bis einschließlich 1
/* Es wird für -2, -1, 0, 1 auf prim geprüft.*/
bool testPrimLess2() {
bool result = true;
result = (false == istPrim(-2)) && result;
result = (false == istPrim(-1)) && result;
result = (false == istPrim(0)) && result;
result = (false == istPrim(1)) && result;
return result;
bool istPrim(int zahl){
}
if (2== zahl) {return true;}
if (0== (zahl%2)) {return false;}
int ende = 1 + static_cast<int>(sqrt(static_cast<double>(zahl)));
for (int i=5; i < wurzel; i=i+2) {
if ( 0== (zahl%i)) {
return false;
}
}// for i
return true;
}
WS 2015/16
V 4.01; © Hon. Prof. Helmke
14
Die verschiedenen Programmierparadigmen von C++
© Helmke
Green Bar:
bool istPrim(int zahl){
if (zahl < 2) {return false;}
if (2== zahl) {return true;}
if (0== (zahl%2)) {return false;}
int ende = 1 + static_cast<int>(sqrt(static_cast<double>(zahl)));
for (int i=3; i < ende; i=i+2) {
if ( 0== (zahl%i)) {
return false;
Tests laufen nun
}
(green bar).
}// for i
return true;
}
Notizen:
•für große Zahlen prüfen
WS 2015/16
V 4.01; © Hon. Prof. Helmke
15
Die verschiedenen Programmierparadigmen von C++
© Helmke
Hauptprogramm: Komplexerer Fall
int main() {
if ( (true== testPrim234 ()) &&
(true== testPrim56Etc ()) &&
(true== testPrimLess2 ()) &&
(true== testPrimBig ()) ){
cout << "Alle Tests erfolgreich.\n";
}
else {
cout << "Tests gescheitert.\n";
}
}
WS 2015/16
V 4.01; © Hon. Prof. Helmke
16
Die verschiedenen Programmierparadigmen von C++
© Helmke
Noch ein Test: Test für ausgewählte große Zahlen
/* Es wird für 961, 8191, 10011001 auf prim geprüft.*/
bool testPrimBig() {
bool result = true;
result = (false == istPrim(961)) && result;
result = (true == istPrim(8191)) && result;
result = (false == istPrim(1001001)) && result;
return result;
}
bool istPrim(int zahl){
if (zahl < 2) {return false;}
if (2== zahl) {return true;}
if (0== (zahl%2)) {return false;}
int ende = 1 + static_cast<int>(sqrt(static_cast<double>(zahl)));
for (int i=3; i < ende; i=i+2) {
if ( 0== (zahl%i)) {
return false;
}
}// for i
return true;
}
WS 2015/16
V 4.01; © Hon. Prof. Helmke
17
Die verschiedenen Programmierparadigmen von C++
© Helmke
Noch ein Beispiel: Funktion „istPalindrom“
WS 2015/16
V 4.01; © Hon. Prof. Helmke
18
Die verschiedenen Programmierparadigmen von C++
© Helmke
Testbasierte Software-Entwicklung
Think
Red Bar
Green Bar
Refactor
WS 2015/16
V 4.01; © Hon. Prof. Helmke
19
Die verschiedenen Programmierparadigmen von C++
© Helmke
Refactoring
Von Refactoring spricht man allgemein, wenn man Änderungen am Code
vornimmt, ohne seine Funktionalität zu verändern. Refactoring
dient somit lediglich dazu, Code übersichtlicher,
wartungsfreundlicher und damit weniger fehleranfällig zu machen.
Refactoring wird aber meist einer Erweiterung der Funktionalität
vorgeschaltet.Es gibt neben der Aufspaltung einer großen Funktion
in kleinere Funktionen weitere Refactoring-Techniken.
Wir werden im Folgenden noch einige kennen lernen. Details können aber
dem Lehrbuch von Fowler zum Refactoring entnommen werden.
Martin Fowler: Refactoring -- Improving the Design of Existing Code,
Addison Wesley, 2002
WS 2015/16
V 4.01; © Hon. Prof. Helmke
20
Die verschiedenen Programmierparadigmen von C++
© Helmke
Refactoring und Erweiterung von Programmen
„Never change a running system“ gilt nicht.
Wir haben automatisch ablaufende Tests.
Wir dokumentieren eine neue Funktionalität zuerst.
Dann schreiben wir noch einen Test für die neue Funktionalität oder auch
mehrere.
Anschließend implementieren wir die Funktionalität.
Wir führen die Tests aus
--- und hoffen --- !!!
Nein, es ist ein systematisches Vorgehen, was zwar auch nicht fehlerfrei
ist, aber ziemlich sicher die Fehler aufdeckt.
WS 2015/16
V 4.01; © Hon. Prof. Helmke
21
Die verschiedenen Programmierparadigmen von C++
© Helmke
Beispiel Getränkemarkt
Sie geben im Getränkemarkt Ihre leeren Flaschen in Kisten ab.
Implementieren Sie eine Funktion BerechnePfand, die Ihnen
ermittelt, wie viel Pfand Sie für B abgegebene Bierflaschen und S
abgegebene Saftflaschen erhalten. Für eine Bierflasche gibt es 8
Cent Pfand und für eine Saftflasche 15 Cent. Bedenken Sie, dass
jeweils 6 Saftflaschen bzw. 24 Bierflaschen in einen Kasten passen
und Sie für jeden abgegebenen Kasten dann auch zusätzlich zum
Flaschenpfand 1 Euro 50 Cent erhalten.
Gehen Sie bei der Lösung der Aufgabe in den Schritten vor
•
Konkretisierung des Problems
•
Entwicklung der Lösung
•
Implementierung von Test und Lösung
•
(Testen, Fehlersuche und Funktionserweiterung)
WS 2015/16
V 4.01; © Hon. Prof. Helmke
23
Die verschiedenen Programmierparadigmen von C++
© Helmke
Beispiel Bäcker
Sie kaufen in der Bäckerei normale Brötchen und Vollkornbrötchen sowie
die dazu erforderlichen Tüten. Implementieren Sie eine
BerechnePreis, die Ihnen ermittelt, wie viel Sie für N normale
Brötchen und V Vollkornbrötchen bezahlen.
10 Brötchen passen jeweils (maximal) in eine Tüte.
Ein normales Brötchen kostet 25 Cent, ein Vollkornbrötchen kostet 50
Cent. Die Tüte kostet jeweils 5 Cent.
Wie viel müssen Sie somit insgesamt bezahlen?
Gehen Sie bei der Lösung der Aufgabe in den Schritten vor
•
Konkretisierung des Problems
•
Entwicklung der Lösung
•
Implementierung von Test und Lösung
•
(Testen, Fehlersuche und Funktionserweiterung)
WS 2015/16
V 4.01; © Hon. Prof. Helmke
29
Herunterladen