Гость
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / ASSERT всегда, не только под DEBUG - совет для ленивых / 7 сообщений из 7, страница 1 из 1
08.05.2013, 09:39
    #38251244
Rostislav D. Kudryashov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ASSERT всегда, не только под DEBUG - совет для ленивых
ASSERT штука хорошая, но плоха она тем, что работает только в режиме отладки. А ведь ошибки надо ловить и в производственных условиях.
Традиция, идущая от программирования в "C", предлагает 1) числовой код для каждой ошибки; 2) классификацию ошибок по рубрикам; 3) фиксированное текстовое сообщение для каждого кода с возможностью вставки "по случаю", вносящей конкретику сбоя. И для всего этого надо держать заголовочные файлы *.H. Эта традиция не учитывает возможностей Фокса и создаёт ненужные препятствия для кодирования проверок в тексте программы. Как правило, если сбой приключился, то код его номера делу не поможет.
В минимальном (и достаточном) варианте, всё что требуется написать для проверки на ошибку, это AssertIt ('Условие').
Программа AssertIt() проверит условие, и если оно нарушено, выбросит пользовательское исключение с кодом 2071 со всей необходимой информацией. Ваш перехватчик TRY ... CATCH TO m.Exception_lo ... только должен выбрать информацию из поля m.Exception_lo.UserValue.
Код: plaintext
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.
FUNCTION AssertIt (m.Expr_tc)
*---------------------------------------
* Проверяет условие m.Expr_tc. Если нарушено, то выдаёт исключение с номером
* текущей строки, именем модуля и его файла, а также LineContens строки.
* Имеется в виду вызов из AssertIt ('Условие').
****************************************
LOCAL m.Msg_lc, m.Res_ll, m.Err_ln, m.Err_lo, m.K_ln, m.Stk_la[1], m.Cont_lc;
 ,m.Excpt_lo AS EXCEPTION
m.Msg_lc = ''
m.Err_ln = 0
TRY
  m.Res_ll = EVALUATE(m.Expr_tc)
CATCH TO m.Excpt_lo
  m.Msg_lc = m.Excpt_lo.Message + CHR(13)+CHR(10) + SPACE (6)
  m.Err_ln = m.Excpt_lo.ErrorNo
ENDTRY
IF EMPTY (m.Msg_lc) AND m.Res_ll
  RETURN
ENDIF
m.K_ln = ASTACKINFO (m.Stk_la) - 1
m.Cont_lc = m.Stk_la [m.K_ln, 6]
IF LEN (m.Cont_lc) > 40
  m.Cont_lc = LEFT (m.Cont_lc, 40) + '...'
ENDIF
m.Excpt_lo = NEWOBJECT ('EXCEPTION')
m.Excpt_lo.LineNo = m.Stk_la [m.K_ln, 5]
m.Excpt_lo.Procedure = m.Stk_la [m.K_ln, 3] + ' (';
 + JUSTFNAME (m.Stk_la [m.K_ln, 4]) + ')'
m.Excpt_lo.ErrorNo = IIF (EMPTY (m.Err_ln), 0, m.Err_ln)
m.Excpt_lo.Message = IIF (EMPTY (m.Msg_lc), '', m.Msg_lc) + m.Cont_lc
THROW m.Excpt_lo
ENDFUNC && AssertIt
...
Рейтинг: 0 / 0
08.05.2013, 10:05
    #38251289
tanglir
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ASSERT всегда, не только под DEBUG - совет для ленивых
Rostislav D. Kudryashov,

а зачем кросспостить?
...
Рейтинг: 0 / 0
08.05.2013, 12:52
    #38251632
Rostislav D. Kudryashov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ASSERT всегда, не только под DEBUG - совет для ленивых
Пожалуй, строка
m.Excpt_lo.Message = IIF (EMPTY (m.Msg_lc), '', m.Msg_lc) + m.Cont_lc
выглядит излишеством. Сгодится более простое
m.Excpt_lo.Message = m.Msg_lc + m.Cont_lc
...
Рейтинг: 0 / 0
08.05.2013, 18:41
    #38252269
piva
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ASSERT всегда, не только под DEBUG - совет для ленивых
Это все к чему и кому Вы рассказываете? или это беседа самого с собой ?
...
Рейтинг: 0 / 0
08.05.2013, 22:58
    #38252421
Rostislav D. Kudryashov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ASSERT всегда, не только под DEBUG - совет для ленивых
Вот это промашка! Вычисление EVALUATE () в AssertIt() не сработает, если в него входят переменные, описанные в вызывающей программе как LOCAL. Так что для спасения идеи придётся воспользоваться не столь изящной реализацией, выполняя проверку условия прямо в программе, где описаны переменные. Но всё равно, Фокс несравненнен!
Код: plaintext
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.
FUNCTION ThrowIt(m.Err_tn)
*---------------------------------------
* Выдаёт исключение с номером текущей строки, именем текущего модуля
* и его файла и сообщением с выборкой EVALUATE (..) из LineContens.
* Имеется в виду вызов из IIF (EVAL('Условие'),0,ThrowIt(m.Err_ln)).
* Наличие m.Err_tn необязательно.
****************************************
LOCAL m.K_ln, m.Stk_la[1], m.Cont_lc, m.I_ln, m.J_ln, m.Excp_lo
m.K_ln = ASTACKINFO (m.Stk_la) - 1
m.Cont_lc = m.Stk_la [m.K_ln, 6]
m.I_ln = AT ('EVAL', UPPER (m.Cont_lc))
m.J_ln = RAT (')', m.Cont_lc, 3)
IF m.I_ln > 0
  m.J_ln = IIF (m.J_ln > 0, m.J_ln, LEN (m.Cont_lc))
  m.Cont_lc = SUBSTR (m.Cont_lc, m.I_ln;
                              ,m.J_ln - m.I_ln + 1)
ENDIF
m.Excp_lo = NEWOBJECT ('EXCEPTION')
m.Excp_lo.LineNo = m.Stk_la [m.K_ln, 5]
m.Excp_lo.Procedure = m.Stk_la [m.K_ln, 3];
  + ' (' + JUSTFNAME (m.Stk_la [m.K_ln, 2]) + ')'
m.Excp_lo.ErrorNo = IIF (EMPTY (m.Err_tn), 0, m.Err_tn)
m.Excp_lo.Message = m.Cont_lc
THROW m.Excp_lo
ENDFUNC && Throw_It
...
Рейтинг: 0 / 0
09.05.2013, 11:07
    #38252557
Rostislav D. Kudryashov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ASSERT всегда, не только под DEBUG - совет для ленивых
А вот это инерция мышления! В первой версии по необходимости было использовано EVALUATE(). И по инерции, некритически, перенесено во вторую версию, где оно совершенно излишне.
Более разумная реализация должна выглядеть вот как.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
FUNCTION ThrowIt (m.Err_tn, m.Msg_tc)
*---------------------------------------
* Выдаёт исключение с номером текущей строки, именем текущего модуля
* и его файла, номером и сообщением ошибки и выборкой из LineContens.
* Имеется в виду вызов из IIF (Условие, 0, ThrowIt (m.Err_ln, m.Msg_tc)).
* Наличие m.Err_tn и m.Msg_tc необязательно.
****************************************
LOCAL m.K_ln, m.Stk_la[1], m.Cont_lc, m.J_ln, m.Excp_lo
m.K_ln = ASTACKINFO (m.Stk_la) - 1
m.Cont_lc = m.Stk_la [m.K_ln, 6]
m.J_ln = RAT ('THROWIT', UPPER (m.Cont_lc))
m.Cont_lc = LEFT (m.Cont_lc, m.J_ln - 1)
m.J_ln = RAT (',', m.Cont_lc, 2)
m.J_ln = IIF (m.J_ln > 0, m.J_ln, LEN (m.Cont_lc))
m.Cont_lc = LEFT (m.Cont_lc, m.J_ln - 1)
m.Excp_lo = NEWOBJECT ('EXCEPTION')
m.Excp_lo.LineNo = m.Stk_la [m.K_ln, 5]
m.Excp_lo.Procedure = m.Stk_la [m.K_ln, 3];
  + ' (' + JUSTFNAME (m.Stk_la [m.K_ln, 2]) + ')'
m.Excp_lo.ErrorNo = IIF (EMPTY (m.Err_tn), 0, m.Err_tn)
m.Excp_lo.Message = IIF (EMPTY (m.Msg_tc), '', m.Msg_tc)
m.Excp_lo.LineContents = m.Cont_lc + ' ...'
THROW m.Excp_lo
ENDFUNC && ThrowIt
...
Рейтинг: 0 / 0
09.05.2013, 11:55
    #38252571
Sergey Ch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ASSERT всегда, не только под DEBUG - совет для ленивых
pivaЭто все к чему и кому Вы рассказываете? или это беседа самого с собой ?
Есть подозрение что персональный блог был спутан с форумом...

На SQL.RU есть специальное место для блогов и статей...
...
Рейтинг: 0 / 0
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / ASSERT всегда, не только под DEBUG - совет для ленивых / 7 сообщений из 7, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]