Re[26]: Что вы предлагаете на замену эксепшенов?
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 29.11.05 15:56
Оценка:
Здравствуйте, 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.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.