Tja, nou heb ik met mijn grote waffel wel wat intelligents geroepen maar hoe leg je dat uit
Goed ... als voorbeeld gaan we uit van een heel simpel email adres invullen, controleren en opslaan. Lekker triviaal. Logisch bekeken:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
| (New*)
|
|<---------.
[NewHTML] |
| |
(NewPost) |
| |
. |
(P)==>| (EmailError)
| |
[VerifyData] |
| nok> |
+--------->.
|
(CorrectEmail)
|
|<--------------------.
[save email] |
| nok> |
+---------> |
| | |
| (CanNotSave)(RetrySave)
| | |
| [RetryHTML] |
| | |
| (RetryPost) |
| . |
| (P)==>| |
| | |
| [HandleRetry] |
| | ok> |
| +--------->.
| |
(EmailSaved)(EmailAbort)
| |
|<---------+
[ReadyHTML]
|
<EOF> |
Ik heb me even in een statemachine uitgeleefd een beetje gecombineerd in een flow chart. '(P)' is een onderbreking van de flow door een 'Post'. States staan tussen '()' en acties staan tussen '[]'. Je begin dus altijd in de state New* als er nog geen state gezet is. Daarna, afhankelijk van de state ga je acties doen. In een PHP / Pseudo code wordt dit
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
| if( not is set following three variables )
{
$_SESSION['OldState'] = "NoState";
$_SESSION['CurState'] = "New";
$_SESSION['ErrorString'] ="";
}
OpenDatabase();
do
{
$_SESSION['OldState'] = $_SESSION['CurState'];
switch($_SESSION['CurState'])
{
case "New":
case "EmailError":
ActionNewHTML();
$_SESSION['CurState'] = "NewPost";
// waiting for user input, abort statemachine
$_SESSION['OldState'] = $_SESSION['CurState'];
break;
case "NewPost":
if( ActionVerifyData )
{
$_SESSION['CurState'] = "CorrectEmail";
}
else
{
$_SESSION['CurState'] = "EmailError";
}
break;
case "CorrectEmail":
case "RetrySave":
if(ActionSaveEmail)
{
$_SESSION['CurState'] = "EmailSaved";
}
else
{
$_SESSION['CurState'] = "CanNotSave";
}
case "CanNotSave": & case "RetryPost":
... laat zich raden ...
break;
case "EmailSaved":
case "EmailAbort":
ActionReadyHTML;
// Final state, no new state is set and statemachine will stop
header("ga terug naar wat ik hiervoor deed");
break;
default:
... error handling undefined state ...
// Undefined state, no new state will be set and statemachine will stop
break;
} }
while( $_SESSION['OldState'] != $_SESSION['CurState'] )
CloseDatabase();
exit(0); |
Dit zou ongeveer mijn VulEmailAdresIn.php pagina zijn. De acties voor het tonen van HTML code en alle controles zou ik in andere files onderbrengen maar kun je ook aan het einde van deze file toevoegen. Acties mogen alleen maar OK/NOK retrourneren. De actie die een fout constateert moet ook zorgen dat de fout gelogd word in $_SESSIOM['ErrorString'] zodat de volgende actie aan de hand van de state eventueel een mooie foutmelding rapporteerd.
Ik hoop dat bovenstaande code je helpt te begrijpen wat ik bedoel. Het voordeel van statemachines is de robuustere foutafhandeling en het eenvoudiger toevoegen van nieuwe functionaliteit. Het vereist wel even iets anders denken soms en voor kleinere systemen is het niet geschikt (zoals bijv. dit voorbeeld

). Debuggen vind ik simpel omdat de logische fouten zich vaak op dit niveau bevinden en de output in acties is weggewerkt. Het (in code) beschikbaar hebben van een flow/state diagram is wel aan te raden (ASCII draw programma?).
... gecensureerd ...