powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / ASSERT всегда, не только под DEBUG - совет для ленивых
7 сообщений из 7, страница 1 из 1
ASSERT всегда, не только под DEBUG - совет для ленивых
    #38251244
Rostislav D. Kudryashov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
ASSERT всегда, не только под DEBUG - совет для ленивых
    #38251289
tanglir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Rostislav D. Kudryashov,

а зачем кросспостить?
...
Рейтинг: 0 / 0
ASSERT всегда, не только под DEBUG - совет для ленивых
    #38251632
Rostislav D. Kudryashov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пожалуй, строка
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
ASSERT всегда, не только под DEBUG - совет для ленивых
    #38252269
piva
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Это все к чему и кому Вы рассказываете? или это беседа самого с собой ?
...
Рейтинг: 0 / 0
ASSERT всегда, не только под DEBUG - совет для ленивых
    #38252421
Rostislav D. Kudryashov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот это промашка! Вычисление 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
ASSERT всегда, не только под DEBUG - совет для ленивых
    #38252557
Rostislav D. Kudryashov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А вот это инерция мышления! В первой версии по необходимости было использовано 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
ASSERT всегда, не только под DEBUG - совет для ленивых
    #38252571
Sergey Ch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pivaЭто все к чему и кому Вы рассказываете? или это беседа самого с собой ?
Есть подозрение что персональный блог был спутан с форумом...

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


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