Oberon space

General Category => Общий раздел => Тема начата: valexey от Апрель 17, 2012, 11:16:24 pm

Название: Обработка "ошибок".
Отправлено: valexey от Апрель 17, 2012, 11:16:24 pm
Предположим у нас нет никаких исключений. Также у нас нет монад и вообще мы не можем использовать выражения (expressions) чтобы связать вычисения, только чистые statement'ы. И у нас есть код, последовательность вызова функций. Каждая функция возвращает код ошибки. Если код nil, значит все хорошо и нужно продолжать вычисления дальше. Если же нет, то нужно напечатать что-то в лог и прекратить вычисление.

Если делать тупо в лоб, то получается как-то так:
err = f1()
if (nil == err) {
    err = f2()
    if (nil == err) {
        err = f3()
        if (nil == err) {
        ...
        }
    } else {
        logError();
    }
} else {
    logError();
}
То есть куча вложенных if'ов на ровном месте и радостное перемешивание кода логики с кодом обработки ошибок.

Есть такой распространненный паттерн решения этой задачки:
err = f1()
if (err!=nil) {
    logError()
    return
}
err = f2()
if (err!=nil) {
    logError()
    return
}
err = f3()
if (err!=nil) {
    logError()
    return
}
Откровенно говоря, он мне тоже не нравится (хотя читается несколько лучше предыдущего) - код и логика опять смешаны. И опять туча дублирующегося кода.

Кто как справлялся с таким вот когда (и если) доводилось сталкиваться?
Название: Re: Обреботка "ошибок".
Отправлено: Peter Almazov от Апрель 18, 2012, 03:25:36 am
Кто как справлялся с таким вот когда (и если) доводилось сталкиваться?
Сталкивался многократно. Как справлялся - никак.  :(
Название: Re: Обреботка "ошибок".
Отправлено: vlad от Апрель 18, 2012, 05:09:03 am
Кто как справлялся с таким вот когда (и если) доводилось сталкиваться?

Если выбирать из зол - то я бы выбрал досрочные ретурны. Либо варианты с проверками на кажом шаге (еслм надо до
Название: Re: Обреботка "ошибок".
Отправлено: vlad от Апрель 18, 2012, 05:12:10 am
(опять форум сглючил)

Кто как справлялся с таким вот когда (и если) доводилось сталкиваться?

Если выбирать из зол - то я бы выбрал досрочные ретурны. Либо вариант с проверками на кажом шаге (если надо дойти до конца функции):
err = f1();
if (!err)
   err = f2();
if (!err)
    err = f3();
Название: Re: Обреботка "ошибок".
Отправлено: adva от Апрель 18, 2012, 06:20:37 am
Во втором случае, чтобы понять что после первой (n - ной) ошибки дальше не отрабатывает, приходится просматривать весь код до конца, в первом случае сразу понятно. Хотя я использую оба варианта.

Наверное как вариант, можно предложить в каждую функцию передавать параметр ошибки, и если он есть, то внутри функции уже не отрабатывать. В этом случае в каждой вложенной функции будет только одна подобная проверка ,что имхо достаточно разграничит логику от обработки ошибок
Название: Re: Обреботка "ошибок".
Отправлено: kemiisto от Апрель 18, 2012, 07:25:05 am
Наверное как вариант, можно предложить в каждую функцию передавать параметр ошибки, и если он есть, то внутри функции уже не отрабатывать.
Передавать не всегда обязательно. Можно просто иметь некую "глобальную" переменную err, например, поле объекта, а вызываться будут его методы.
Название: Re: Обработка "ошибок".
Отправлено: valexey от Апрель 18, 2012, 08:08:55 am
Во втором случае, чтобы понять что после первой (n - ной) ошибки дальше не отрабатывает, приходится просматривать весь код до конца, в первом случае сразу понятно. Хотя я использую оба варианта.
Во втором случае тоже не надо, а вот в варианте влада - надо. То есть в третьем случае.

Наверное как вариант, можно предложить в каждую функцию передавать параметр ошибки, и если он есть, то внутри функции уже не отрабатывать. В этом случае в каждой вложенной функции будет только одна подобная проверка ,что имхо достаточно разграничит логику от обработки ошибок
Не, к сожалению не пойдет - функции эти не только мои, но и библиотечные, которые я менять не могу.
Название: Re: Обработка "ошибок".
Отправлено: Valery Solovey от Апрель 18, 2012, 08:16:31 am
Можно ещё вот так извратиться.
if (f1() == nil &&
      f2() == nil &&
      f3() == nil) {
        ...
} else {
    logError();
}
Название: Re: Обработка "ошибок".
Отправлено: valexey от Апрель 18, 2012, 08:26:14 am
Можно ещё вот так извратиться.
if (f1() == nil &&
      f2() == nil &&
      f3() == nil) {
        ...
} else {
    logError();
}
А это уже противоречит изначальной постановке задачи, ибо связывает вычисления через выражение. :-)

Поясню почему такое ограничение наложено - у нас ведь скорее всего будут не просто вызовы функций, но и другие statement'ы между ними. То есть без обработки ошибок это нечто вроде:
f1()
a:=c-d
f2()
g; v; z;
f3()
Название: Re: Обработка "ошибок".
Отправлено: Valery Solovey от Апрель 18, 2012, 08:29:55 am
Можно ещё вот так извратиться.
if (f1() == nil &&
      f2() == nil &&
      f3() == nil) {
        ...
} else {
    logError();
}
А это уже противоречит изначальной постановке задачи, ибо связывает вычисления через выражение. :-)
Как раз-таки изначальной постановке задачи оно не противоречит : ).
Название: Re: Обработка "ошибок".
Отправлено: Valery Solovey от Апрель 18, 2012, 08:34:34 am
А можно ещё так:
err = f1()
if (nil == err) {
    wrap_f2()
} else {
    logError();
}
, где wrap_f2() - это обёртка над f2(), прилегающими командами и обработкой ошибки. (Там внутри ещё будет вызван wrap_f3()).
Название: Re: Обработка "ошибок".
Отправлено: valexey от Апрель 18, 2012, 08:38:55 am
Цитата: Valery Solovey link=topic=226.msg5114#msg5114
раз-таки изначальной постановке задачи оно не противоречит : ).

Противоречит.
Цитировать
Предположим у нас нет никаких исключений. Также у нас нет монад и вообще мы не можем использовать выражения (expressions) чтобы связать вычисения, только чистые statement'ы.
Название: Re: Обработка "ошибок".
Отправлено: Romiras от Апрель 18, 2012, 09:02:38 am
Предположим у нас нет никаких исключений. Также у нас нет монад и вообще мы не можем использовать выражения (expressions) чтобы связать вычисения, только чистые statement'ы. И у нас есть код, последовательность вызова функций. Каждая функция возвращает код ошибки. Если код nil, значит все хорошо и нужно продолжать вычисления дальше. Если же нет, то нужно напечатать что-то в лог и прекратить вычисление.

Если делать тупо в лоб, то получается как-то так:
err = f1()
if (nil == err) {
    err = f2()
    if (nil == err) {
        err = f3()
        if (nil == err) {
        ...
        }
    } else {
        logError();
    }
} else {
    logError();
}
То есть куча вложенных if'ов на ровном месте и радостное перемешивание кода логики с кодом обработки ошибок.

Есть такой распространненный паттерн решения этой задачки:
err = f1()
if (err!=nil) {
    logError()
    return
}
err = f2()
if (err!=nil) {
    logError()
    return
}
err = f3()
if (err!=nil) {
    logError()
    return
}
Откровенно говоря, он мне тоже не нравится (хотя читается несколько лучше предыдущего) - код и логика опять смешаны. И опять туча дублирующегося кода.

Кто как справлялся с таким вот когда (и если) доводилось сталкиваться?

Вот мой вариант обработки ошибок:
MODULE PrivErrTypes;

CONST
OK* = 0;
ERR_NO_MEM* = 101;
ERR_INVALID_MODE* = 201;

TYPE
ErrorStatus* = POINTER TO RECORD
code*: INTEGER;
location*: INTEGER;
END;

END PrivErrTypes.

MODULE PrivErrChecks;

IMPORT ETypes := PrivErrTypes, StdLog;

VAR
res: ETypes.ErrorStatus;
p: POINTER TO ARRAY 100 OF REAL;
a: INTEGER;

PROCEDURE Message(IN s: ARRAY OF CHAR);
BEGIN
StdLog.String(s); StdLog.Ln
END Message;

PROCEDURE LogReport;
VAR s: ARRAY 256 OF CHAR;
BEGIN
IF res.code # ETypes.OK THEN
CASE res.code OF
ETypes.ERR_NO_MEM: s := "No enough memory for completing of operation."
| ETypes.ERR_INVALID_MODE: s := "Invalid mode."
END;
Message("ERROR: " + s$)
END
END LogReport;


PROCEDURE Check1Passed (): BOOLEAN;
BEGIN
NEW(p);
IF p = NIL THEN
res.code := ETypes.ERR_NO_MEM; res.location := 0C1H
END;
RETURN res.code = ETypes.OK
END Check1Passed;

PROCEDURE Check2Passed (): BOOLEAN;
BEGIN
IF a < 0 THEN
res.code := ETypes.ERR_INVALID_MODE; res.location := 0C2H
END;
RETURN res.code = ETypes.OK
END Check2Passed;


PROCEDURE Run*;
VAR passed: BOOLEAN;
BEGIN
res.code := ETypes.OK; res.location := 0;

passed := Check1Passed();
passed := passed & Check2Passed();

IF passed THEN
Message("All tests passed successfully!")
ELSE
LogReport
END
END Run;

BEGIN
IF res = NIL THEN NEW(res) END;

a := -1; (* causing test to fail *)
END PrivErrChecks.

! PrivErrChecks.Run
Название: Re: Обработка "ошибок".
Отправлено: Romiras от Апрель 18, 2012, 09:10:01 am
Ага. Я слишком вскользь прочёл. Тут речь о каких-то монадах.
Пускай valexey сам решает подходит или нет.  ;)
Название: Re: Обработка "ошибок".
Отправлено: valexey от Апрель 18, 2012, 09:17:51 am
Вот мой вариант обработки ошибок:
...
passed := Check1Passed();
passed := passed & Check2Passed();
...
Опять связывание вычислений через выражение. Не годится по выше изложенным соображениям. Также не годится в случае если функция возвращает больше одного значения (в некоторых языках так можно):
err, res = f1()
В этом случае f1() засунуть в качестве операнда выражения уже не получится.
Название: Re: Обработка "ошибок".
Отправлено: valexey от Апрель 18, 2012, 09:19:26 am
Ага. Я слишком вскользь прочёл. Тут речь о каких-то монадах.
Пускай valexey сам решает подходит или нет.  ;)
Ненене, монады как раз нельзя :-) Твой код:
passed := Check1Passed();
passed := passed & Check2Passed();
Это и есть по сути монада. То есть связывание вычислений через выражение.
Название: Re: Обработка "ошибок".
Отправлено: Romiras от Апрель 18, 2012, 09:34:28 am
А эти ограничения имеют практический или теоретический (академический) характер?
Чем они обоснованы? Ведь операцию умножения тоже можно запретить. Но нафига?
Название: Re: Обработка "ошибок".
Отправлено: valexey от Апрель 18, 2012, 09:54:13 am
А эти ограничения имеют практический или теоретический (академический) характер?
Чем они обоснованы? Ведь операцию умножения тоже можно запретить. Но нафига?
Ограничения чисто практические. Причины с примерами я приводил выше.
Название: Re: Обработка "ошибок".
Отправлено: kemiisto от Апрель 18, 2012, 10:03:40 am
Ещё как вариант (пускай и не всегда применимый) - действовать как большинтсво компиляторов при синтаксическом разборе. Встретил ошибку - не беда, добавил в список и пошёл дальше. В конце прохода (или при накомплении некого критического числа ошибок) - остановился и выплюнул накопленный список. Кому надо :D , знает куда смотреть.
Название: Re: Обработка "ошибок".
Отправлено: Romiras от Апрель 18, 2012, 10:14:21 am
Ага. Я слишком вскользь прочёл. Тут речь о каких-то монадах.
Пускай valexey сам решает подходит или нет.  ;)
Ненене, монады как раз нельзя :-) Твой код:
passed := Check1Passed();
passed := passed & Check2Passed();
Это и есть по сути монада. То есть связывание вычислений через выражение.
Откуда взят запрет на связывание вычислений через выражения? Если он взят с потолка, то мой вариант должен подойти.
Название: Re: Обработка "ошибок".
Отправлено: Romiras от Апрель 18, 2012, 10:17:32 am
Вот мой вариант обработки ошибок:
...
passed := Check1Passed();
passed := passed & Check2Passed();
...
Опять связывание вычислений через выражение. Не годится по выше изложенным соображениям. Также не годится в случае если функция возвращает больше одного значения (в некоторых языках так можно):
err, res = f1()
В этом случае f1() засунуть в качестве операнда выражения уже не получится.
В предложенных мною конструкциях (внутри булевой функции) можно использовать любые комбинации других возвращающих функций. Главное, вернуть статус: Успех или Неудача.
Название: Re: Обработка "ошибок".
Отправлено: valexey от Апрель 18, 2012, 11:45:59 am
В предложенных мною конструкциях (внутри булевой функции) можно использовать любые комбинации других возвращающих функций. Главное, вернуть статус: Успех или Неудача.
Тогда придется в эти булевы функции заворачивать каждые две-пять строчек интересующего кода. То есть этих вспомогательных функций будет примерно столько же сколько строк кода без обработки ошибок. По моему, это слишком большой оверхед.

Собственно это первое что я пытался сделать когда начал бороться за читабельность кода.

PS. Вот в такие вот моменты я жутко завидую тем кто пишет на хаскелле.
Название: Re: Обработка "ошибок".
Отправлено: alexus от Апрель 18, 2012, 11:48:55 am
PS. Вот в такие вот моменты я жутко завидую тем кто пишет на хаскелле.
... или на ассемблере... одна простая "макро-обёрка" вызова... и радуемся... :)
Название: Re: Обработка "ошибок".
Отправлено: valexey от Апрель 18, 2012, 12:04:52 pm
PS. Вот в такие вот моменты я жутко завидую тем кто пишет на хаскелле.
... или на ассемблере... одна простая "макро-обёрка" вызова... и радуемся... :)
Ну, не ассемблере, а таки макроасме :-) Но а вообще любому языку можно с макросистемой я в данном случае сильно завидую - тут даже макросов Сишных хватит. Но увы, в целевом языке нет ни макросов ни парадигмы "все есть выражение". То есть такой дубовенький императивный язычок. Сильно более дубовый в этом плане нежели Си.
Название: Re: Обработка "ошибок".
Отправлено: adva от Апрель 18, 2012, 01:23:27 pm
А есть ли возможность вызывать код в виде строки (привожу аналог из 1С):

ФункцияОбертка(Вычислить("ВызываемаяФункция"), Выполнить("ДополнительныйТекстОбработкиКода")). В данном случае все можно сделать в одной функции, правда код будет в виде текста, что не очень удобно
Название: Re: Обработка "ошибок".
Отправлено: valexey от Апрель 18, 2012, 01:27:33 pm
А есть ли возможность вызывать код в виде строки (привожу аналог из 1С):

ФункцияОбертка(Вычислить("ВызываемаяФункция"), Выполнить("ДополнительныйТекстОбработкиКода")). В данном случае все можно сделать в одной функции, правда код будет в виде текста, что не очень удобно
Нет, функции eval (http://en.wikipedia.org/wiki/Eval) нет. Просто потому, что в этом случае пришлось тащить с собой компилятор.
Название: Re: Обработка "ошибок".
Отправлено: DIzer от Апрель 18, 2012, 01:56:13 pm
Не пронял, зачем нужна переменная еrr (по смыслу содержит указатель возвращаемый мелкими функциями....) вполне можно и без него ..  или нет?
Название: Re: Обработка "ошибок".
Отправлено: valexey от Апрель 18, 2012, 01:57:23 pm
Не пронял, зачем нужна переменная еrr (по смыслу содержит указатель возвращаемый мелкими функциями....) вполне можно и без него ..  или нет?
Это код ошибки. И функции не мелкие.
Название: Re: Обработка "ошибок".
Отправлено: DIzer от Апрель 18, 2012, 02:05:07 pm
Уродский код, и потом,  я про то, что он нигде не используется... а насчет того, большие функции или маленькие пофигу - один черт каждая вызывается ровно один раз (либо не вызывается вообще)...
Название: Re: Обработка "ошибок".
Отправлено: valexey от Апрель 18, 2012, 02:15:41 pm
Уродский код, и потом,  я про то, что он нигде не используется... а насчет того, большие функции или маленькие пофигу - один черт каждая вызывается ровно один раз (либо не вызывается вообще)...
Ничего не понял. Он используется (как минимум его проверяют на nil). Для пущего использования замени logError() на logError(err);

err = f1()
if (nil == err) {
    err = f2()
    if (nil == err) {
        err = f3()
        if (nil == err) {
        ...
        }
    } else {
        logError(err);
    }
} else {
    logError(err);
}
Название: Re: Обработка "ошибок".
Отправлено: valexey от Апрель 18, 2012, 02:16:31 pm
Уродский код, и потом,  я про то, что он нигде не используется... а насчет того, большие функции или маленькие пофигу - один черт каждая вызывается ровно один раз (либо не вызывается вообще)...
Или ты про какой код вообще? Те функции что у меня (f1, f2, f3 ...) используются много где, ибо библиотечны.
Название: Re: Обработка "ошибок".
Отправлено: Romiras от Апрель 18, 2012, 02:37:06 pm
В предложенных мною конструкциях (внутри булевой функции) можно использовать любые комбинации других возвращающих функций. Главное, вернуть статус: Успех или Неудача.
Тогда придется в эти булевы функции заворачивать каждые две-пять строчек интересующего кода. То есть этих вспомогательных функций будет примерно столько же сколько строк кода без обработки ошибок. По моему, это слишком большой оверхед.

Собственно это первое что я пытался сделать когда начал бороться за читабельность кода.

PS. Вот в такие вот моменты я жутко завидую тем кто пишет на хаскелле.
В приведённом мною код проверок выглядит "линейно". Его легче читать и воспринимать, чем древовидный, с отступами.
А что подразумевается под "оверхедом"?

P.S. Попробую подумать о других вариантах позже вечером.
Название: Re: Обработка "ошибок".
Отправлено: DIzer от Апрель 18, 2012, 02:37:48 pm
А теперь понятно, (недоумевал почему не использовался  if (f0() !=nil ) напрямую.... но ладно, вы привели 2 неэквивалентных способа  -
Первый  ДОПУСКАЕТ выполнение  инструкций  внутри процедуры ПОСЛЕ блока if ов, второй НЕТ.
Имеет смысл выделить блок второго способа в Отдельную функцию возвращающую код

 ErrCode Check(){
}


А вашей основной функции будет нечто:   Log(Check())...
Название: Re: Обработка "ошибок".
Отправлено: DIzer от Апрель 18, 2012, 02:42:31 pm
т.е. в этом случае вы получаете желаемое разделение (ценой небольшой работы ручками)
Название: Re: Обработка "ошибок".
Отправлено: DIzer от Апрель 18, 2012, 02:48:05 pm
Почему уродский - НЕНАВИЖУ когда в качестве  значений по алгоритму осмысленных констант используются предопределенные константы  общего вида - nil, NULL уж лучше "магические" числа 
Название: Re: Обработка "ошибок".
Отправлено: valexey от Апрель 18, 2012, 02:53:05 pm
А теперь понятно, (недоумевал почему не использовался  if (f0() !=nil ) напрямую.... но ладно, вы привели 2 неэквивалентных способа  -
Первый  ДОПУСКАЕТ выполнение  инструкций  внутри процедуры ПОСЛЕ блока if ов, второй НЕТ.
Это уже мелочи - один к другому приводится простым засовыванием блока в функцию. Это рраз. Два - даже в случае с return'ами во многих языках я смогу гарантировать исполнение определенного кода перед завершением работы данной функции где бы этот return не приключился.
Название: Re: Обработка "ошибок".
Отправлено: DIzer от Апрель 18, 2012, 02:54:34 pm
См. сообщение выше... что вам не нравится  в предложенном способе?
Название: Re: Обработка "ошибок".
Отправлено: valexey от Апрель 18, 2012, 02:54:46 pm
Имеет смысл выделить блок второго способа в Отдельную функцию возвращающую код

 ErrCode Check(){
}


А вашей основной функции будет нечто:   Log(Check())...
От этого второй способ красивей (читабельней) не станет. Либо я что-то не понял в предложеном методе. Дай пожалуйста переделанный код второго способа.
Название: Re: Обработка "ошибок".
Отправлено: DIzer от Апрель 18, 2012, 03:05:04 pm
ErrCode Check(){
err = f1();
if (err!=nil) {
    return err;
}
err = f2();
if (err!=nil) {
    return err;
}
err = f3();
if (err!=nil) {
    return err;
}
}

.... в основной  процедуре
.....
.....
merr=Check();
......
Log(merr);
....
Название: Re: Обработка "ошибок".
Отправлено: valexey от Апрель 18, 2012, 03:08:58 pm
ErrCode Check(){
err = f1();
if (err!=nil) {
    return err;
}
err = f2();
if (err!=nil) {
    return err;
}
err = f3();
if (err!=nil) {
    return err;
}
}

.... в основной  процедуре
.....
.....
merr=Check();
......
Log(merr);
....
Это не решает проблему нечитабельности тела функции Check.
Название: Re: Обработка "ошибок".
Отправлено: DIzer от Апрель 18, 2012, 03:11:43 pm
Зато решает проблему - вашу проблему разделения логики минимальными средствами
 :D Ваше желание конфетку съесть и на ...  сесть похвально...  но надо быть реалистом.   :(
Название: Re: Обработка "ошибок".
Отправлено: valexey от Апрель 18, 2012, 03:18:48 pm
Зато решает проблему - вашу проблему разделения логики минимальными средствами
 :D Ваше желание конфетку съесть и на ...  сесть похвально...  но надо быть реалистом.   :(
Нет не решает. Вся логика радостно оказывается в функции Check. Логика в коде, если выкинуть обработку ошибок, ровно вот такая:
f1()
f2()
f3()
(аргументы в функции подставить по вкусу)

Вместо этого мне предлагается писать такое:
err = f1();
if (err!=nil) {
    return err;
}
err = f2();
if (err!=nil) {
    return err;
}
err = f3();
if (err!=nil) {
    return err;
}
Где логика радостно перемешана с обработкой ошибок.
Название: Re: Обработка "ошибок".
Отправлено: DIzer от Апрель 18, 2012, 03:21:58 pm
Вот это
f1()
f2()
f3()

и то что у вас в шапке топика - СОВЕРШЕННО РАЗЛИЧНЫЕ ВЕЩИ (вы уж разберитесь с тем что вам нужно,..)
Название: Re: Обработка "ошибок".
Отправлено: vlad от Апрель 18, 2012, 03:37:48 pm
Где логика радостно перемешана с обработкой ошибок.

В поставленных условиях (исключений нет, макросов нет, вообще ничего нет) трудно изобрести что-то новое. Чисто вкусовые вариации... Если бы можно было компилятор покрутить, то можно было бы пофантазировать... хотя кончилось бы все скорее всего поддержкой исключений.
Название: Re: Обработка "ошибок".
Отправлено: valexey от Апрель 18, 2012, 03:44:08 pm
Вот это
f1()
f2()
f3()

и то что у вас в шапке топика - СОВЕРШЕННО РАЗЛИЧНЫЕ ВЕЩИ (вы уж разберитесь с тем что вам нужно,..)
Одно и то же. Мне нужно что бы f2 выполнялось когда f1 успешен. и так далее. Но эта связка (условность выполнение f2) это не логика приложения. То есть это не то, что должно выпирать.
Название: Re: Обработка "ошибок".
Отправлено: DIzer от Апрель 18, 2012, 03:46:04 pm
не правильная постановка вопроса - уместнее использовать фразу "добиться оптимального решения" - оно всегда есть в КОНКРЕТНОМ случае - а уж вопрос насколько оно оптимальное... я вот , например, почитал в этом топике мнение Алексея.... ну и высказался ... насчет "конфетки".
Название: Re: Обработка "ошибок".
Отправлено: valexey от Апрель 18, 2012, 03:49:28 pm
Где логика радостно перемешана с обработкой ошибок.

В поставленных условиях (исключений нет, макросов нет, вообще ничего нет) трудно изобрести что-то новое. Чисто вкусовые вариации... Если бы можно было компилятор покрутить, то можно было бы пофантазировать... хотя кончилось бы все скорее всего поддержкой исключений.
Ну, defer есть :-) Еще паника есть (которую можно поймать - похоже на исключения). Но мне кажется что паниковать по поводу и без - плохой тон. Функции высшего порядка есть :-)
Название: Re: Обработка "ошибок".
Отправлено: DIzer от Апрель 18, 2012, 03:52:11 pm
Вот это
f1()
f2()
f3()

и то что у вас в шапке топика - СОВЕРШЕННО РАЗЛИЧНЫЕ ВЕЩИ (вы уж разберитесь с тем что вам нужно,..)
Одно и то же. Мне нужно что бы f2 выполнялось когда f1 успешен. и так далее. Но эта связка (условность выполнение f2) это не логика приложения. То есть это не то, что должно выпирать.
Охох... Алексей .. если вам нужно 3 вызова подряд - if по ЛОГИКЕ не нужны... ЕСЛИ НЕТ то НИКУДА ВЫ ОТ НИХ НЕ ДЕНЕТЕСЬ в особенности если вы должны сделать что то ПОСЛЕ  этих  вызовов - это есть ЛОГИКА АЛГОРИТМА. у вас к ЛОГИКЕ ОБРАБОТКИ ОШИБКИ относится вызов функции Log() который я убрал из логики алгоритма... И хватит... на это... достало - вы...это.... довольно неконструктивны....
Название: Re: Обработка "ошибок".
Отправлено: valexey от Апрель 18, 2012, 03:58:39 pm
Охох... Алексей .. если вам нужно 3 вызова подряд - if по ЛОГИКЕ не нужны... ЕСЛИ НЕТ то НИКУДА ВЫ ОТ НИХ НЕ ДЕНЕТЕСЬ в особенности если вы должны сделать что то ПОСЛЕ  этих  вызовов - это есть ЛОГИКА АЛГОРИТМА. у вас к ЛОГИКЕ ОБРАБОТКИ ОШИБКИ относится вызов функции Log() который я убрал из логики алгоритма... И хватит... на это... достало - вы...это.... довольно неконструктивны....
Ну да, ну да. Это все равно что писать вместо вот такого:
if (a&&b&&c&&d) {...}писать такое:
if (a) {
    if (b) {
        if (c) {
            if (d) {
                ...
            }
        }
    }
}
Название: Re: Обработка "ошибок".
Отправлено: DIzer от Апрель 18, 2012, 04:02:47 pm
 ;)  Ага придуриваемся.... а что, мне тоже весело...
Название: Re: Обработка "ошибок".
Отправлено: valexey от Апрель 18, 2012, 04:07:14 pm
;)  Ага придуриваемся.... а что, мне тоже весело...
Ну, я не знаю какая у тебя цель участия в этой дискуссии, а у меня цель очень простая - мне нужно сделать свой код более читабельным. Причем не абстрактный код вообще, а вполне конкретный его кусок. Причем желательно это было сделать вчера. Как видишь, цель сугубо практическая.
Название: Re: Обработка "ошибок".
Отправлено: DIzer от Апрель 18, 2012, 04:12:46 pm
 :D Если прочитать ВСЕ ваши требования (... по этому топику)... целей у вас... как бы это выразится  помягче .. достаточно много (например, избежание "радостного смешивания") и не все они разумные в  контексте налагаемых вами ограничений.. впрочем, по этому поводу я уже высказался... все.
Название: Re: Обработка "ошибок".
Отправлено: vlad от Апрель 18, 2012, 04:30:40 pm
Ну, defer есть :-)

Тогда я бы точно склонился к варианту с досрочными ретурнами. Дейкстра (точнее его толкование труЪ оберощиками) идет лесом.
Название: Re: Обработка "ошибок".
Отправлено: Губанов Сергей Юрьевич от Апрель 18, 2012, 04:55:18 pm
делать тупо в лоб
Советую делать тупо в лоб с многократно вложенными if, но только диагностику ошибки делать сразу, а не где-то там в else через сто строчек.
err = f1();
if (err != nil)
{
logError("f1 failed", err);
}
else
{
//...
//...
//...
err = f2();
if (err != nil)
{
logError("f2 failed", err);
}
else
{
//...
//...
//...
err = f3();
if (err != nil)
{
logError("f3 failed", err);
}
else
{
//...
//...
//...
err = f4();
if (err != nil)
{
logError("f4 failed", err);
}
else
{
//...
//...
//...
err = f5();
if (err != nil)
{
logError("f5 failed", err);
}
else
{
//...
//...
//...
}
}
}
}
}
Название: Re: Обработка "ошибок".
Отправлено: DIzer от Апрель 18, 2012, 04:55:42 pm
Ну, defer есть :-)

Тогда я бы точно склонился к варианту с досрочными ретурнами. Дейкстра (точнее его толкование труЪ оберощиками) идет лесом.
Одна проблема в Обероне07(с его ЕДИНСТВЕННЫМ  RETURN -ом ) вам не дадут даже сделать этого... ;D
Название: Re: Обработка "ошибок".
Отправлено: DIzer от Апрель 18, 2012, 05:00:44 pm
делать тупо в лоб
Советую делать тупо в лоб с многократно вложенными if, но только диагностику ошибки делать сразу, а не где-то там в else через сто строчек.
err = f1();
if (err != nil)
{
logError("f1 failed", err);
}
else
{
//...
//...
//...
err = f2();
if (err != nil)
{
logError("f2 failed", err);
}
else
{
//...
//...
//...
err = f3();
if (err != nil)
{
logError("f3 failed", err);
}
else
{
//...
//...
//...
err = f4();
if (err != nil)
{
logError("f4 failed", err);
}
else
{
//...
//...
//...
err = f5();
if (err != nil)
{
logError("f5 failed", err);
}
else
{
//...
//...
//...
}
}
}
}
}
  :D ;D А вот по Алексею  это НИЗЗЯ ибо  здесь "радостно смешиваются" две различные логики  ;D
Название: Re: Обработка "ошибок".
Отправлено: vlad от Апрель 18, 2012, 05:03:31 pm
Советую делать тупо в лоб с многократно вложенными if, но только диагностику ошибки делать сразу, а не где-то там в else через сто строчек.

2valexey: я ж говорю, чисто вкусовые вариации - для меня, например, код Сергея абсолютно нечитаем :)
Название: Re: Обработка "ошибок".
Отправлено: vlad от Апрель 18, 2012, 05:06:00 pm
Одна проблема в Обероне07(с его ЕДИНСТВЕННЫМ  RETURN -ом ) вам не дадут даже сделать этого... ;D

А там и defer нету ;) Так что там, скорее всего, я бы выбрал вариант "с проверками до конца".
Название: Re: Обработка "ошибок".
Отправлено: DIzer от Апрель 18, 2012, 05:19:34 pm
Акаки там есть варианты акромя вашего (лестница)?  ;)
Название: Re: Обработка "ошибок".
Отправлено: DIzer от Апрель 18, 2012, 05:27:37 pm
Кто нибудь знает , есть ли в каком -нибудь Обероне - нечто на вроде  AnyProc -указателя на   произвольную процедуру?
Название: Re: Обработка "ошибок".
Отправлено: Valery Solovey от Апрель 18, 2012, 06:21:15 pm
Можно реализовать встроенную процедуру "приведение процедуры". : )
Название: Re: Обработка "ошибок".
Отправлено: Valery Solovey от Апрель 18, 2012, 06:23:30 pm
Раз радостное смешение логик не катит, то тогда прямая дорога к грустному конечному автомату.
Название: Re: Обработка "ошибок".
Отправлено: Valery Solovey от Апрель 18, 2012, 06:25:21 pm
Функции высшего порядка есть :-)
То есть, задача под какой-то конкретный язык, а не в общем случае? Тогда стоило добавить это в условие задачи.
Название: Re: Обработка "ошибок".
Отправлено: valexey от Апрель 18, 2012, 06:30:19 pm
Функции высшего порядка есть :-)
То есть, задача под какой-то конкретный язык, а не в общем случае? Тогда стоило добавить это в условие задачи.
Хотелось получить более-менее общий метод решения подобного на классе схожих императивных языков.

А так - язык Go. Но, по моему, это поможет мало, просто потому, что никто кроме меня тут на нем вроде бы не пишет.
Название: Re: Обработка "ошибок".
Отправлено: DIzer от Апрель 18, 2012, 06:41:07 pm
Раз радостное смешение логик не катит, то тогда прямая дорога к грустному конечному автомату.
Вот это грамотный ответ... :)  Правда здесь можно обсудить.. в какой степени можно эмулировать исключения средствами некоторого внешнего модуля (например, аккумуляция  ситуаций во внешнем хранилище с возможностью пост обработки)... и что это может дать
Название: Re: Обработка "ошибок".
Отправлено: valexey от Апрель 18, 2012, 06:52:48 pm
Раз радостное смешение логик не катит, то тогда прямая дорога к грустному конечному автомату.
Угу. Я думал об этом. Цикл, внутри case. Ну и поехали. По сути тут case играет роль goto с вычисляемой меткой.

В результате отказался - избыточно мощный и общий инструмент, следовательно больше шансов совершить ошибку. То есть если конечный автомат тут использовать, то нужно его специальным образом оформить. Как его оформить поприличнее я так и не придумал.
Название: Re: Обработка "ошибок".
Отправлено: Valery Solovey от Апрель 18, 2012, 07:07:27 pm
внутри case.
А зачем нам чемодан? Ведь есть же функции высшего порядка? Или это функции американского высшего порядка? Типа: "теперь вы равноправны, но на юге шерифу на глаза лучше не попадайтесь".
Название: Re: Обработка "ошибок".
Отправлено: valexey от Апрель 18, 2012, 07:37:11 pm
внутри case.
А зачем нам чемодан? Ведь есть же функции высшего порядка? Или это функции американского высшего порядка? Типа: "теперь вы равноправны, но на юге шерифу на глаза лучше не попадайтесь".
Я могу ошибаться, но по моему функции высших порядков не заменят кейс. Заменить кейс может паттерн матчинг (ака сопоставление с образцом).
Название: Re: Обработка "ошибок".
Отправлено: Valery Solovey от Апрель 18, 2012, 08:49:33 pm
В общем случае, навероное - да, не заменят. Но если рассматривать конечный автомат как последовательность "действие - переход", то переход-к-новому-действию можно заменить на вызов нужной функции. Функции, есс-но, нужно передать в параметрах (может, есть альтернативы, но я их пока не придумал). Думаю, получится упрощённый лиспо-подобный интерпретатор.
Название: Re: Обработка "ошибок".
Отправлено: DIzer от Апрель 18, 2012, 09:11:47 pm
А такой  способ не пройдет -пусть мы имеем
простейший обьект TWarder  с одним полем - ErrCode, конструктором устанавливающем его в nil, и методом WardProc(f:WardedProc) -который может менять ErrCode (в зависимости отего текущего значения вызывая f либо нет ), тогда работу фрагмент можно представить ввиде:
.......
MyWarder:=TWvarder.Create()
......
MyWarder.WardProc(f0());
MyWarder.WardProc(f1());
MyWarder.WardProc(f2());
.....
обработка ошибок...
Case  MyWarder.ErrCode of
err1:Log(err1,'f0()')
err2:Log(err2,'f1()')
.....
Название: Re: Обработка "ошибок".
Отправлено: DIzer от Апрель 18, 2012, 09:27:19 pm
Сама WardProc имеет простейший вид
Procedure TWarder.WardProc (f:WardedProc)
Begin
IF ErrCode=nil then ErrCode:=f()
End;
Название: Re: Обработка "ошибок".
Отправлено: DIzer от Апрель 18, 2012, 09:29:45 pm
В Паскале такая хрень проходит, в Обероне, даже простейшем.. тоже должна...
Название: Re: Обработка "ошибок".
Отправлено: DIzer от Апрель 19, 2012, 01:41:24 am
... так что я явно поторопился с "Одна проблема в Обероне07(с его ЕДИНСТВЕННЫМ  RETURN -ом ) вам не дадут даже сделать этого...  ;D". ;)
Название: Re: Обработка "ошибок".
Отправлено: DIzer от Апрель 19, 2012, 01:48:02 am
А с другой стороны, свел задачу к форме которую хотел Valexey?- но , как и  ожидалось, от if а избавиться не удалось...
Название: Re: Обработка "ошибок".
Отправлено: adva от Апрель 19, 2012, 03:54:04 am
А чё, мне понравилось, пожалуй попробую в будущем задейстововать :), правда тут без кейса можно (тем более в 1с его нет)