Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Prüfsoftware möglichst objektorientiert programmieren... (https://www.delphipraxis.net/95669-pruefsoftware-moeglichst-objektorientiert-programmieren.html)

DelphiManiac 11. Jul 2007 10:46


Prüfsoftware möglichst objektorientiert programmieren...
 
Hallo ich bin dabei wie in Thread

http://www.delphipraxis.net/internal...t.php?t=112368

(Habe einen neuen Thread aufgemacht weil ich im alten zu unstrukturiert gefragt habe... sorry)

beschrieben eine Prüfsoftware für eine Hardwarekomponente zu entwickeln,

ich habe mir jetzt einige Anregungen zur Brust genommen und versucht umzusetzen, d.h. ich

habe z.Zt. folgendes Gebilde

Ich muss ja n-Test durchführen.

deswegenen habe ich eine Klasse TTest gebildet,
die schon Objekte der Klassen:
- TPrueflig (API zur Kommunikation mit dem Gerät)
- TMultimeter(API zur Kommunikation mit dem Messgerät)
- TKalibrator(API zur Kommunikation mit dem Kalibrator)

Jede Testklasse hat wie "hsg" vorgeschlagen hat eine Execute Methode um den Prüfvorgang zu tätigen.

Von diesen Klassen leite ich jeweils meine Prüfungen ab (wie im Beitrag von "Der_Unwissende")

Also zum Beispiel

TTestCom2Geraet = class (TTest)
..
Testet die Kommunikation über die Schnittstelle (ob das Gerät antwortet)



usw.usw

Nun habe ich noch eine Klasse
TControlTest gebildet, die die einzelnen Tests nacheinander ausführen soll,
also eine Klasse zur Steuerung des Testablaufs, dies mache ich über eine Objektliste und führe sie nacheinander aus.


meine Frage ist dieser Ansatz sinvoll, oder ggf. noch zu verbessern?

Gerne stelle ich hier auch ein paar aussagekräftigere Quellcodes oder ein Klassendiagramm rein.

Hoffe ich habt Lust und Muße mit mir zu diskutieren :)

Gruß
DelphiManiac

Relicted 11. Jul 2007 11:07

Re: Prüfsoftware möglichst objektorientiert programmieren...
 
huhu!

also für mich hört sich das sehr sinnvoll an..
in die TTest einfach ne execute methode rein und diese abstrakt deklarieren.
das erspart lästiges typecasten...

ich selber wende das bei parserstrukturen an. eigentlich genau das selbe.

eine idee wäre noch deine TestControl klasse als singleton objekt zu implementieren und in jede von TTest abgeleitete klasse einen initialization block zu machen, welcher die klasse direkt am TTestControl objekt anmeldet..
dazu bräuchtest du noch eine kleine funktion die das objekt bereitstellt...
dazu würde ich die struktur folgendermaßen wählen:

Delphi-Quellcode:
ITest = interface
  procedure Execute( .. );
end;

TTest = class( TInterfacedObject, ITest )
end;

TTest1 = class(TTest)
//...
public
  //...
  procedure Execute(...);
end;


function GetTest : ITest;

implementation

function GetTest : ITest;
begin
  result := TTest1.Create;
end;



initialization
  TestControl.RegisterTest(GetTest);
das ist bissl aus der struktur von dunit geklaut... :-)

gruß
reli

DelphiManiac 11. Jul 2007 11:32

Re: Prüfsoftware möglichst objektorientiert programmieren...
 
Hallo,

ja das dem Singleton Muster könnte ich anwenden, so, dass sich dann alle Objekte(Tests) am Testcontrol
anmelden gar keine schlechte Idee, ich glaube ich muss mir DUnit doch mal genauer angucken, habs
nur überflogen, da es schon sehr komplex war in meinen Augen.

Mein Problem bei der Durchführung der Test ist wahrscheinlich nicht die Kommunikation mit den Geräten, wohl
eher die visuell Darstellung des Prüfablaufes.
Ich will z.B.: ein Prüfobjekt deklarieren, dass Messwerte liesst und Werte an das Gerät schreibt.

Wie kann ich denn dies am geschicktesten machen, ohne konkrete Implementierungen in meiner Unit vorzunehmen,

ich will natürlich nicht sowas machen:

Delphi-Quellcode:
frmMainGUI.LabelMesswert.Caption:=IntToStr(Geraet.GetMesswert);
Am liebsten wäre mir an der Stelle eine lose Kopplung, das heißt ich will nicht die Logik der Darstellung mit in meine Tests bauen sondern dieses der GUI-Klasse überlassen, wie sie es darstellt.

Danke euch!

Relicted 11. Jul 2007 11:40

Re: Prüfsoftware möglichst objektorientiert programmieren...
 
du könntest informationen in die testklasse ansich anschreiben. meinetwegen noch eine abstrakte methode die ein record oder ein objekt zurückgeben soll, welches dann mit den infos gefüllt ist die du visualisieren willst.
das objekt kann dann von deiner form aus über das singleton abgerufen und visualisiert werden..

ich weiß leider nicht inwieweit sich die informationen gleichen...
du könntest natürlich auch einfach ein event definieren und beim ersten zugriff auf das singleton übergeben, sodass die infos die du haben willst ( ich denke da an eine log ) über das event ans formular weitergereicht werden und das formular dann meinetwegen den krempel in ein memo kloppt... :-)

gruß
reli

DelphiManiac 11. Jul 2007 12:14

Re: Prüfsoftware möglichst objektorientiert programmieren...
 
Hi Relicted

also habe u.a. folgende Tests / Vorgänge

Flashen des uC
Info: - Fortschritt (am besten Progressbar)

Kalibrieren der Analogausgänge
- aktueller AnalogAusgangswert
- vorgegebener Wert

usw. usw.

Meinst du ich soll ein Event basteln?

also eine Art Callback Funktion, die der GUI Daten übergibt?

Danke dir!

Relicted 11. Jul 2007 12:26

Re: Prüfsoftware möglichst objektorientiert programmieren...
 
Jau würd ich machen...
Delphi-Quellcode:
TProgressEvent = procedure( min,max,act : integer; sInfo : string ) of object;
von dem event braucht dann jedes TTest Objekt ne property und natürlich ne member... machst sie am besten protected die member dann kann auch jeder abgeleitete test weiterhin drauf zugreifen.

dann brauch deine handlerklasse auch noch so eine procedure wie:
Delphi-Quellcode:
procedure SetProgressEvent( Event : TProgressEvent );
in der wird dann jedem angemeldeten Test das event übergeben..
ich würde z.B. 2 events an die handlerklasse weitergeben.. eins für overall (gesteuert vom handler selbst) und eine für die einzelnen tests wo die ihren progress anzeigen können... auf die form dann dementsprechend auch 2 progressbars.. gesamt und einzelner test.

und wenn du nun ansich immer die selben daten pro test angezeigt haben willst dann mach dir nen record:
Delphi-Quellcode:
type
  TInfoRec = record
    aktuellerAnalogAusgangswert : integer;
    vorgegebenerWert : integer;
    //....
  end;

DelphiManiac 11. Jul 2007 13:33

Re: Prüfsoftware möglichst objektorientiert programmieren...
 
Hallo,

ja mit dem ProgressEvent könnte ich das ganz Gut steuern...

Habe nur das Problem, dass ich zum Beispiel eine Funktion habe, die Paramterschreibt,
aber erst zurückkommt, wenn sie alle Parameter geschrieben hat, evtl. muss ich diese
so um bauen, dass sie immer nur einen Parameter schreibt, und ich diese dann n-mal aufrufe,
so, dass ich danach meinen ProgressEvent aufrufen kann.

Wie meinst du dass?

Zitat:

in der wird dann jedem angemeldeten Test das event übergeben..
ich würde z.B. 2 events an die handlerklasse weitergeben.. eins für overall (gesteuert vom handler selbst) und eine für die einzelnen tests wo die ihren progress anzeigen können... auf die form dann dementsprechend auch 2 progressbars.. gesamt und einzelner test.
Also ich habe jetzt in meiner abstrakten Testklasse eine Event, dass die GUI über den Fortschritt eines Tests informiert.
Den Gesamtfortschritt kann ja nur meine ControlTest-Klasse wissen, das bedeutet doch, dass ich ihr auch noch ein Eventproperty
verpassen muss, oder???

Danke dir!

Relicted 11. Jul 2007 13:41

Re: Prüfsoftware möglichst objektorientiert programmieren...
 
richtig... macht halt nen schönen eindruck wenn man weiß wie viel man insgesammt scho geschafft hat :-)

DelphiManiac 11. Jul 2007 15:20

Re: Prüfsoftware möglichst objektorientiert programmieren...
 
Ja da hast du Recht,...

meine Anwendung wird langsam.

Mal ne andere Frage ich rufe ja das
Event folgendermaßen auf:

Delphi-Quellcode:
if Assigned(FProgressEvent) then
begin
  FProgressEvent(0,100,0,'');
end;
Muss ja prüfen, ob der Methodenzeiger auch wirklich auf eine Methode zeigt und nicht auf
Delphi-Quellcode:
NIL
Kann man das auch schöner formulieren, oder ist das so der einzige Weg?

Gracias

Relicted 11. Jul 2007 15:30

Re: Prüfsoftware möglichst objektorientiert programmieren...
 
ich mache es immer so dass ich mir ne hilfsmethode mache (private) die ich aufrufe und in der dann steht
Delphi-Quellcode:
procedure PrintPrivate( ... );
begin
  if Assigned( FProgressEvent ) then
    FProgressEvent(  ... );
end;

DelphiManiac 24. Jul 2007 15:16

Re: Prüfsoftware möglichst objektorientiert programmieren...
 
Hallo @all


wollte euch mal auf dem Laufendem halten, was meine Prüfsoftware angeht, und mit euch ein wenig
diskutieren, wie und was man optimieren / ändern kann / sollte.


Habe ja, denke wie viele das Problem, dass ich meine Datenhaltung und Logik von meiner Darstellung trennen will,
das habe ich auch sehr strikt gemacht, die GUI kennt bei meiner Prüfsoftware eigentlich nur das Objekt
zur Prüfungsverwaltung (das die Prüfungen ausführt).

Das heißt meine TTestControl Klasse verwaltet Prüfobjekte (vom Typ TTest) in einer Liste, die es dann wenn es
aufgefordert wird nacheinander startet.

Die GUI (bzw) der Controller der GUI erzeugt nun, die zu testenden Tests und übergibt sie den TTestcontrol Objekt

sieht dann ungefähr so aus:

Delphi-Quellcode:
  with FrmMainGUI do
  begin
    einIniFile:=TIniFile.Create(ProgrammDataset.IniName);
    einControlTest.ClearTest; // Liste leeren
    einControlTest.OnShowFortschrittGesamt:=FrmMainGUI.ShowFortSchrittTestGesamt;
    if cbCom2EPTPruef.Checked then
    begin
      einIniFile.WriteInteger('TestConfig','Com2EPTPruef',1);
      einTest:=TTestCommu2EPTPruef.Create;
      einTest.OnShowProgress:=FrmMainGUI.ShowFortSchrittTest;
      einControlTest.AddTest(einTest);
    end
    else
    begin
      einIniFile.WriteInteger('TestConfig','Com2EPTPruef',0);
    end;
    if cbComm2Calibrator.Checked then
    begin
      einIniFile.WriteInteger('TestConfig','Com2Calibrator',1);  
      einTest:=TTestCommu2Calibrator.Create;
      einTest.OnShowProgress:=FrmMainGUI.ShowFortSchrittTest;
      einControlTest.AddTest(einTest);
    end
    else
    begin
      einIniFile.WriteInteger('TestConfig','Com2Calibrator',0);
    end;
    if cbComm2Multimeter.Checked then
    begin
      einIniFile.WriteInteger('TestConfig','Com2Multimeter',1);  
      einTest:=TTestCommu2Multimeter.Create;
      einTest.OnShowProgress:=FrmMainGUI.ShowFortSchrittTest;
      einControlTest.AddTest(einTest);
    end
    else
    begin
      einIniFile.WriteInteger('TestConfig','Com2Multimeter',0);
    end;
    if cbComm2EPT.Checked then
    begin
      //
    end;
    if cbUSBControllerParamet.Checked then
    begin
      einIniFile.WriteInteger('TestConfig','USBControllerParamtetrieren',1);  
      einTest:=TTestProgramFTDI.Create;
      einTest.OnShowProgress:=FrmMainGUI.ShowFortSchrittTest;
      einControlTest.AddTest(einTest);
    end
    else
    begin
      einIniFile.WriteInteger('TestConfig','USBControllerParamtetrieren',0);
    end;
    if cbFlash.Checked then
    begin
      einIniFile.WriteInteger('TestConfig','Flashen',1);
      einTest:=TTestFlashADuC.Create(ProgrammDataset.FlashPfad);
      einTest.OnShowProgress:=FrmMainGUI.ShowFortSchrittTest;
      einControlTest.AddTest(einTest);
    end
    else
    begin
       einIniFile.WriteInteger('TestConfig','Flashen',0);
    end;
    if cbParameter.Checked then
    begin
      einTest:=TTestWriteParameter.Create(ProgrammDataset.Parameterdatei);
      einTest.OnShowProgress:=FrmMainGUI.ShowFortSchrittTest;
      einControlTest.AddTest(einTest);
      einIniFile.WriteInteger('TestConfig','ParameterUebertragen',1);
    end
    else
    begin
      einIniFile.WriteInteger('TestConfig','ParameterUebertragen',0);
    end;
    if cbDisplayTest.Checked then
    begin
      einIniFile.WriteInteger('TestConfig','DisplayTastenTest',1);
      einTest:=TTestTasten.Create;
      einTest.OnShowProgress:=FrmMainGUI.ShowFortSchrittTest;
      einControlTest.AddTest(einTest);
    end
    else
    begin
       einIniFile.WriteInteger('TestConfig','DisplayTastenTest',0);
    end;
    if cbPruefeRelais.Checked then
    begin
      einIniFile.WriteInteger('TestConfig','RelaisTest',1);
      einTest:=TTestRelais.Create;
      einTest.OnShowProgress:=FrmMainGUI.ShowFortSchrittTest;
      einControlTest.AddTest(einTest);
    end
    else
    begin
      einIniFile.WriteInteger('TestConfig','RelaisTest',0);
    end;
    if cbDataLoggerClock.Checked then
    begin
      einIniFile.WriteInteger('TestConfig','DatenloggerSetTimeDate',1);
      einTest:=TTestDataLoggerClock.Create;
      einTest.OnShowProgress:=FrmMainGUI.ShowFortSchrittTest;
      einControlTest.AddTest(einTest);
    end
    else
    begin
      einIniFile.WriteInteger('TestConfig','DatenloggerSetTimeDate',0);
    end;
    if cbKalibriereAnalogEingang.Checked then
    begin
      einIniFile.WriteInteger('TestConfig','AnalogEingangKalibrierung',1);
      einTest:=TTestKalibriereAnalogEingang.Create;
      einTest.OnShowProgress:=FrmMainGUI.ShowFortSchrittTest;
      TTestKalibriereAnalogEingang(einTest).OnDigitEvent:=frmMainGUI.ShowDigtTest;;
      einControlTest.AddTest(einTest);
    end
    else
    begin
      einIniFile.WriteInteger('TestConfig','AnalogEingangKalibrierung',0);
    end;
    if cbKalibriereCTEingang.Checked then
    begin
      einIniFile.WriteInteger('TestConfig','CTEingangKalibrierung',1);  
      einTest:=TTestKalibriereCTEingang.Create;
      einTest.OnShowProgress:=FrmMainGUI.ShowFortSchrittTest;
      TTestKalibriereCTEingang(einTest).OnDigitEvent:=frmMainGUI.ShowDigtTest;;
      einControlTest.AddTest(einTest);
    end
    else
    begin
      einIniFile.WriteInteger('TestConfig','CTEingangKalibrierung',0);
    end;

    if cbOLCTTest.Checked then
    begin
      einIniFile.WriteInteger('TestConfig','OLCTTest',1);
      einTest:=TTestOLCTModul.Create;
      einTest.OnShowProgress:=FrmMainGUI.ShowFortSchrittTest;
      einControlTest.AddTest(einTest);
    end
    else
    begin
      einIniFile.WriteInteger('TestConfig','OLCTTest',0);
    end;
    if cbPT100Kalibrierung.Checked then
    begin
      einIniFile.WriteInteger('TestConfig','PT100Kalibrierung',1);
      einTest:=TTestKalibrierePT100Eingang.Create;
      TTestKalibrierePT100Eingang(einTest).OnDigitEvent:=frmMainGUI.ShowDigtTest;;    
      einTest.OnShowProgress:=FrmMainGUI.ShowFortSchrittTest;
      einControlTest.AddTest(einTest);
    end
    else
    begin
      einIniFile.WriteInteger('TestConfig','PT100Kalibrierung',0);
    end;
    if cbAnalogOut1.Checked then
    begin
      einIniFile.WriteInteger('TestConfig','AnalogAusgang1Kalibrierung',1);
      einTest:=TTestKalibriereAnalogAusgang.Create(1);
//      TTestKalibrierePT100Eingang(einTest).OnDigitEvent:=frmMainGUI.ShowDigtTest;;
      einTest.OnShowProgress:=FrmMainGUI.ShowFortSchrittTest;
      einControlTest.AddTest(einTest);
    end
    else
    begin
      einIniFile.WriteInteger('TestConfig','AnalogAusgang1Kalibrierung',0);
    end;
    if cbAnalogOut2.Checked then
    begin
      einIniFile.WriteInteger('TestConfig','AnalogAusgang2Kalibrierung',1);
      einTest:=TTestKalibriereAnalogAusgang.Create(2);
//      TTestKalibrierePT100Eingang(einTest).OnDigitEvent:=frmMainGUI.ShowDigtTest;;
      einTest.OnShowProgress:=FrmMainGUI.ShowFortSchrittTest;
      einControlTest.AddTest(einTest);
    end
    else
    begin
      einIniFile.WriteInteger('TestConfig','AnalogAusgang2Kalibrierung',0);
    end;
  end;
end;

Gut, die Logik (was ein Test machen muss) kennt nur das Testobjekt, genauso wie die Daten, die es erzeugt testet, oder
sonst was damit macht (zB.: kalbrieren).

Ich habe nun ein Event, an das die GUI sich anmelden kann und dann Daten übergeben bekommt zur Anzeige.

Mein Problem ist nun, da die Tests ja sehr unterschiedlich sind (d.h. auch unterschiedliche Daten) muss das Event ja
auch überall anders aussehen, und dann muss ich ja sehr viele Events erzeugen usw...

Kann man das irgendwie Objektorientiert besser lösen,
bin über jeden Vorschlag dankbar

Gruß
DelphiManiac

DelphiManiac 27. Jul 2007 21:01

Re: Prüfsoftware möglichst objektorientiert programmieren...
 
*push*


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:41 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz