HSG |
|
Dieser Text ist drei Jahre alt und wird noch überarbeitet. Er ist nicht so zu verstehen, dass jeder Test eines Algorithmus auf diese Art erfolgen soll.
Algorithmen und ihr Test nehmen einen breiten Raum in der Informatik ein. Es soll ein typisches Algorithmen-Testprogramm objektorientiert entwickelt werden. Als Beispiel könnte man den Euklidischen Algorithmus wählen. Doch widerspricht nicht schon die Auswahl eines speziellen Algorithmus dem Prinzip der Kapselung von Daten und Methoden?
Es soll also ein Programm zum Testen eines Algorithmus zur Berechnung des ggT erstellt werden.
Die Eingabe wird aus zwei ganzen Zahlen bestehen, die Ausgabe aus einer ganzen Zahl, der Rechenvorgang soll durch einen Button ausgelöst werden.
Der Prototyp spiegelt die Benutzeroberfläche, das GUI wieder. Sie repräsentiert die Views und den Controls des MVC-Konzepts.
Der Model-Teil, das Fachkonzept soll natürlich von der GUI getrennt werden.
Objekte sollen nach Zuständigkeiten ausgewählt werden, die Zuständigkeit für die Berechnung des ggT erhält ein "ggT-Objekt" oGgT, die zugehörige Klasse soll TggT heißen. TggT braucht eigentlich nur den Algorithmus zu kapseln, das wäre eine Klasse ohne Datenfelder. Manchmal kann es aber nützlich sein, wenn das zuständige Objekt die Eingangsdaten behält.
Das Formular-Objekt Form1 wird für Erzeugung und Vernichtung aller anderer Objekte verantwortlich gemacht. Es steht in der Hierarchie höher, es "hat" die anderen Objekte. Mit UMLEd wurde folgendes Klassendiagramm erstellt:
Im Sinne einer integrierten Dokumentation kann man auch die Möglichkeiten von UmlEd (Datei: ggTooP.urd) benutzen, Anmerkungen zu Objekten, Attributen und Methoden zu machen.
In dieser Phase erfolgt die Auswahl bzw. der Entwurf der benötigten Algorithmen. Es sei zunächst der Euklidische Algorithmus ausgewählt. Zu einer guten Dokumentation gehört jetzt die Erläuterung des Algorithmus (Struktogramm, Fundstellen usw.).
Als nächstes steht die Auswahl der zu benutzenden Klassenbibliothekenan. Im Beispiel soll die Delphi-VCL benutzt werden. Natürlich setzt diese Benutzung ein Mindestmaß an Vertrautheit voraus, was hier erwartet wird.
Beim "Zusammenschieben" der Benutzeroberfläche in der Delphi-IDE hantiert man bewusst oder unbewusst mit Objekten, deren Klassen in diversen Units bereitgehalten werden. Auch das Hauptformular ist ein Objekt, das bei der Erzeugung einer neuen Anwendung automatisch "da ist". Man muss sich um Erzeugung und Vernichtung dieser ganzen Objekte nicht kümmern, das Delphi-System trifft automatisch die nötigen Vorkehrungen. Teils sieht man das am automatisch erzeugten Code, teils werden im Hintergrund Objektattribute und Referenzen gesetzt ohne dass man das merkt.
Es folgt der Delphi-Quellcode, wobei das Fachkonzept mit der Klasse TggT in der Unit "uGgT.pas", die Benutzungsoberfläche in der Unit "uGUI.pas" zu finden ist.
unit uGgt; { ggT-OOP, mk, 4.2.03 } interface type TggT = class(TObject) private Fa,Fb : integer; public procedure SetA(z : integer); procedure SetB(z : integer); function GetggT : integer; end; implementation procedure TggT.SetA(z : integer); begin Fa := z; end; procedure TggT.SetB(z : integer); begin Fb := z; end; function TggT.GetggT : integer; function Euklid(m,n : integer) : integer; var r : integer; begin repeat r := m mod n; if r = 0 then result := n else begin m := n; n := r end; until r = 0; end; begin result := Euklid(Fa,Fb); end; end.
unit uGUI; { ggT-OOP, mk, 4.2.03 } interface uses Forms, StdCtrls , sysUtils , Controls, Classes, uGgt; { 1. Fachkonzept-Unit einbinden } type TForm1 = class(TForm) eA: TEdit; lA: TLabel; eB: TEdit; lB: TLabel; eGgT: TEdit; lGgT: TLabel; bBerechne: TButton; procedure bBerechneClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private oGgT : TggT; { 2. Referenzvariable deklarieren } public { Public declarations } end; var Form1 : TForm1; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); begin oGgT := TggT.Create; { 3. Objekt erzeugen } end; procedure TForm1.bBerechneClick(Sender: TObject); var a,b,g : integer; begin a := StrToInt(eA.Text); b := StrToInt(eB.Text); oGgT.SetA(a); oGgT.SetB(b); { 4. Objekt vorbereiten } g:= oGgT.GetggT; { 5. Anfrage an Objekt stellen } eGgT.Text := IntToStr(g); end; procedure TForm1.FormDestroy(Sender: TObject); begin oGgT.free; { 6. Speicherplatz freigeben } end; end.
Getestet wurde:
a | b | Ausgabe | ggT(a,b) |
512 | 400 | 16 | 16 |
19 | 23 | 1 | 1 |
24 | 15 | 3 | 3 |
Der Test mit ausgewählten Zahlenpaaren scheint die korrekte Funktion zu bestätigen. Doch was passiert für negative Eingaben, für die Eingabe 0, für sehr große, für unsinnige Eingaben? Was sollte man alles testen, bis man zufrieden ist?