Algorithmus-Test, objektorientiert
Pflichtenheft
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.
Prototyp
Die Eingabe wird aus zwei ganzen Zahlen bestehen, die Ausgabe aus einer ganzen Zahl, der
Rechenvorgang soll durch einen Button ausgelöst werden.
Objektorientierte Analyse
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.
Objektorientiertes Design
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.
Implementierung
Es folgt der Delphi-Quellcode, wobei das Fachkonzept mit der Klasse TggT in der Unit "uGgT.pas", die Benutzeroberflä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.
Test
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 sollten man alles testen, bis man zufrieden ist?