LINUX.ORG.RU

Правильный код


0

4

Алгоритм задачи написан так что следующий блок может выполняться только после успешного завершения предыдущего. Таких блоков от 20 до 100.
Можно написать в структуре со вложенными if else, а можно после каждого блока писать return при неудачном завершении. Вариант с GOTO просто не рассматривается. И тот и другой вариант мне не нравится. Вложенность ифоф реально доставляет, большое количество ретурнов нарушает концепцию один вход - один выход.

Кто что посоветует?

★★★★★

Концпеция про один выход в современном программировании не используется. Стандартное решение — return-ы или исключения.

Legioner ★★★★★
()

Кому нужна дурацкая концепция, если ты сам запутаешься и других запутаешь.

ilovewindows ★★★★★
()

Вариант с GOTO просто не рассматривается.

лечите gotoфобию

Bad_ptr ★★★★★
()

Если не гнаться за эффективностью, можно не делать вложенные if, а при неудаче формировать код ошибки, который проверять во всех if. Таким образом, после возникновения ошибки для всех последующих if будет ложное условие и блоки не будут выполнены.

amomymous ★★★
()

убрать вложенность if, ввести 'состояние', устанавливать его выполнении очередного блока, и анализировать перед входом в следующий?

anonymous
()

вариант с goto самый оптимальный и легко читаемый

Harald ★★★★★
()

Еще один вариант — соединить блоки через AND, можно прямо в коде, можно в цикле. Подзадачи оформляются отдельными функциями.

staseg ★★★★★
()

Таких блоков от 20 до 100.

может уже пора разделить алгоритм на функции?

anonymous
()

switch/case блоки и return?

iVS ★★★★★
()
Ответ на: комментарий от anonymous

do { ... } while(0); return -> break

О! Вот это мне нравится!
Ну-ка сейчас накачу! Посмотрю как это выглядит!

ВСЕМ СПАСИБО!!!!! Буду пробовать!

vada ★★★★★
() автор топика
Ответ на: комментарий от Harald

ресурсы освобождать нужно?

Нет.

vada ★★★★★
() автор топика

большое количество ретурнов нарушает концепцию один вход - один выход.

А если так?

#include <stdbool.h>

int main(int argc, char *argv[])
{
  bool OK = true;
  /* do something... */
  if (OK)
    {
      /* do something... */
    }
  if (OK)
    {
      /* do something... */
    }
  if (OK)
    {
      /* do something... */
    }
  return 0;
}

Deleted
()

Вариант с GOTO просто не рассматривается. И тот и другой вариант мне не нравится.

Давай уж по-чесноку: тебе не нравятся все три из возможных вариантов, причем самый неуё ты не стал рассматривать.

arturpub ★★
()
Ответ на: комментарий от staseg

Подзадачи оформляются отдельными функциями.

Вот это совсем не катит. Подзадачи размером от 5 до 10 строк, а их набежит несколько тысяч. В этом ворохе просто не разобраться будет :(

vada ★★★★★
() автор топика
Ответ на: комментарий от vada

do { ... } while(0); return -> break

О! Вот это мне нравится!

Убейте меня кто-нибудь :\

arturpub ★★
()
Ответ на: комментарий от Deleted

А если так?

Пробовал. Не понравилось. Пока бесполезные ифы обходит как-то все замирает...

vada ★★★★★
() автор топика

Тред императивного кукареканья. Проблема решена 20 лет назад - используйте монаду Maybe.

anonymous
()

следующий блок может выполняться только после успешного завершения предыдущего

Код пишется так, чтобы каждый шаг не знал об этой особенности алгоритма. Обычно бросаю исключение и задача подвисает в очереди. Самое простое и очевидное решение для многих мейнстримных ЯП.

Не знаю на каком ЯП реализуете этот «правильный код», это плохо.

outtaspace ★★★
()

можно ещё конечный автомат сделать, aka state machine

заводишь структуру, что-то вроде такого:

struct state
{
struct state *success; //куда переходим при успешном выполнении блока
struct state *fail;//куда переходим при неудаче
int (*action)(void *arg);//указатель на функцию, которая выполняет действия и возвращает результат - успех или неуспех
};

и инициализировать статически массив таких структур:

int block1(void *arg)
{
//действия, выполняемые первым блоком
}
int block2(void *arg)
{
//действия, выполняемые вторым блоком
}
//

struct state statemachine[]=
{
{&statemachine[1], &statemachine[2], block1},
{NULL, NULL, block2},
{NULL, NULL, block3}
};

и потом код, который всё это обрабатывает:

struct state *position = statemachine;

while (position)
{
   position -> action(arg) ? position = position -> success : position = position -> fail;
}

Harald ★★★★★
()
Ответ на: комментарий от buddhist

Самый разумный - монада Maybe, второй по разумности - return

unC0Rr ★★★★★
()

return'ы - просто и понятно.

Да, а если нужно освобождать много всяких разных ресурсов, то не вижу ничего плохого в goto. Полный отказ от его использования - не более, чем предрассудки...

solovey ★★
()
Последнее исправление: solovey (всего исправлений: 1)

Если речь идёт о коде, обрабатывающем входные данные пользователя (т. е. данные имеют право содержать ошибки), то правильнее использовать условные операторы. Для визуальной красоты можно ввести переменную кода ошибки и в каждом следующем блоке её проверять.

Если код обрабатывает данные и не предполагается, что в них могут быть ошибки (например данные поступили от других твоих же подпрограмм) - используй исключения.

return в середине кода - это тот же goto.

ksicom
()

использовать MaybeT или EitherT, очевидно же.

qnikst ★★★★★
()

Напиcал бы какой язык используешь и насколько ситуация с неуспешным завершением является исключительной.

maxcom ★★★★★
()
abrakadabra([]) ->
  ok;

abrakadabra([T|H]) ->
  case process_job(T) of
    ok ->
      abrakadabra(H);
    {error, ErrorCode} ->
      io:format("processing finished with error code ~w~n", [ErrorCode]),
      {error, ErrorCode}
  end.
nanoolinux ★★★★
()

Ты описал монаду Maybe. Впрочем исключение тоже подойдёт. Но язык-то какой? Не томи!

KblCb ★★★★★
()

Про исключения только ленивый не написал. ИМХО, самый простой и понятный вариант.

Вот это совсем не катит. Подзадачи размером от 5 до 10 строк, а их набежит несколько тысяч. В этом ворохе просто не разобраться будет :(

Религия не позволяет? Уж не собрался ли ты эти несколько ТЫСЯЧ подзадач одной функцией делать?

И да, ЯП в студию.

CaveRat ★★
()
Ответ на: комментарий от anonymous

Maybe как вариант. В Perl у меня happy case во все поля - код работает только пока все хорошо, он оборачивается в try {}.

outtaspace ★★★
()

Используй goto и не сношай себе мозг.

Absurd ★★★
()

нарушает концепцию один вход - один выход

Нет такой концепции. Используйте return и не слушайте идиотов которые предлагают такой бред.

slovazap ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.