Здравствуйте, IT, Вы писали:
IT>Сейчас чего-нибудь изобразим.
Написали Вы много, но принципиальной разницы с предыдущим примером нет.
MODULE RsdnUI;
IMPORT StdLog, Errors := RsdnErrors, AccountManager := RsdnAccountManager;
PROCEDURE WithdrawalAndGetBalance*;
VAR newBalance: REAL; err: Errors.List;
BEGIN
IF AccountManager.WithdrawalAndGetBalance("12345", 1.0E2, newBalance, err) THEN
StdLog.String("New balance is: "); StdLog.Real(newBalance); StdLog.Ln
ELSE
StdLog.String("Oops: "); StdLog.Ln;
Errors.Print(err)
END
END WithdrawalAndGetBalance;
END RsdnUI.
MODULE RsdnAccountManager;
IMPORT Errors := RsdnErrors;
TYPE
AccountService = RECORD
(*...*)
END;
AccountDataAccessor = RECORD
(*...*)
END;
...
PROCEDURE (VAR this: AccountService) WithdrawalAndGetBalance (accountNumber: ARRAY OF CHAR; amount: REAL; OUT rest: REAL; VAR err: Errors.List): BOOLEAN, NEW;
VAR r: BOOLEAN; accessor: AccountDataAccessor;
(*...*)
PROCEDURE Do (): BOOLEAN;
VAR ignored: Errors.List; (* ignored errors for steal-methods *)
BEGIN
IF accessor.GetBalance(accountNumber, rest, err) THEN
IF rest >= amount THEN
IF accessor.ChargeForService(accountNumber, 10, err) THEN
rest := rest - amount - 10;
IF (rest > 1.0E6) & accessor.StealSomeForMe(accountNumber, 1.15, ignored) THEN rest := rest - 1.15 END;
IF (rest > 1.0E7) & accessor.StealSomeForHomelessPeople(accountNumber, 1.15, ignored) THEN rest := rest - 1.15 END;
RETURN accessor.SetBalance(accountNumber, rest, err)
END
ELSE
err := Errors.NewList(Errors.NewError("You are freaking bankrupt!"), err); (* Вот такое вот "кидание исключения" *)
END
END;
RETURN FALSE
END Do;
(*...*)
BEGIN r := ValidateAccountNumber(accountNumber, err) & ValidateAmount(amount, err);
IF r THEN
accessor.Init;
r := accessor.BeginTransaction(err) & Do() & accessor.CommitTransaction(err);
accessor.Close
END;
RETURN r
END WithdrawalAndGetBalance;
...
PROCEDURE WithdrawalAndGetBalance* (accountNumber: ARRAY OF CHAR; amount: REAL; OUT rest: REAL; VAR err: Errors.List): BOOLEAN;
VAR r: BOOLEAN; service: AccountService;
BEGIN r := ValidateAccountNumber(accountNumber, err) & ValidateAmount(amount, err);
IF r THEN
service.Init;
r := service.WithdrawalAndGetBalance(accountNumber, amount, rest, err);
service.Close
END;
RETURN r
END WithdrawalAndGetBalance;
...
END RsdnAccountManager.
MODULE RsdnErrors;
IMPORT StdLog;
CONST
max = 256;
TYPE
Error* = POINTER TO EXTENSIBLE RECORD
desc*: ARRAY max OF CHAR;
END;
List* = POINTER TO RECORD
head-: Error;
tail-: List
END;
PROCEDURE NewError* (desc: ARRAY OF CHAR): Error;
VAR e: Error;
BEGIN ASSERT(LEN(desc) < max, 20);
NEW(e); e.desc := desc$; RETURN e
END NewError;
PROCEDURE NewList* (head: Error; tail: List): List;
VAR u: List;
BEGIN ASSERT(head # NIL, 20);
NEW(u); u.head := head; u.tail := tail; RETURN u
END NewList;
PROCEDURE Print* (err: List);
BEGIN
WHILE err # NIL DO
StdLog.String(err.head.desc); StdLog.Ln; err := err.tail
END
END Print;
END RsdnErrors.