Изначально я хотел назвать статью как нибудь вызывающе, например, "Как наука может превращаться в религию", "В ловушке искажений смыслов структурного программирования" или "О чем вам забыли рассказать про структурное программирование", но в результате все же оставил текущее название и надеюсь, оно не вызывает раздражения у читателей. И хотя другие заголовки являются более кликбейтными, тем не менее они все же в больше степени отражают смысл статьи, чем нейтральные "размышления".


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


Все наверно помнят, что любой алгоритм можно представить в виде трех видов алгоритмических конструкций, следование, ветвление и повторения? А иногда еще добавляют, что эту теорему выдвинул и доказал Э. Дейкстра в 70-х гг. прошлого века, в том числе, включая широко распиаренный якобы запрет на использование операторов goto.


Структурное программирование


Структурное программирование – это концепция, появившаяся в конце 1960-х годов и повлиявшая на дальнейшее развитие императивного программирования. Основоположником структурного программирования считается Эдсгер Дейкстра. Его заслуга состоит не только в разработке этой концепции, но и в ее продвижении.


Основные принципы структурного программирования Эдсгер Дейкстра сформулировал главным образом в Dahl, O.-J., Dijkstra, E.W., Hoare, C.A.R. Structured Programming.


Однако разрабатывая лексику для своего языка программирования у меня неоднократно возникали некоторые сомнения в достоверности этих фактов. Ведь в данную концепцию (что любой алгоритм можно представить в виде трех видов алгоритмических конструкций), совсем не вписывается обработка исключений и некоторые другие элементы, которые являются практически обязательными для всех современных языков программирования.


В поисках правды


Поэтому я решил разобраться с доказательством Э. Дейкстра и найденные результаты меня очень удивили. Все вышло как про ученого, который изнасиловал журналиста или в более толерантное в анекдоте: "Не Кац, а Рабинович. Не в лотерею, а в карты. Не миллион, а сто рублей. И не выиграл, а проиграл".


Другими словами, все оказалось совсем не так. Отсутствует контекст, который необходим для правильного понимания этой информации, структурную теорему опубликовал и доказал вовсе не Э. Дейкстра и много чего еще, что кардинально меняет представления о некоторых вопросах, связанных со структурным программированием. А так как это фактически обязательная база, которая используется в школе при обучении основам программирования, то я думаю, что необходимо сорвать покровы рассказать про найденные факты.


Начал я с того, что попробовал найти первоисточник публикации в котором Э. Дейкстра выдвинул и доказал теорему о достаточности трех алгоритмических конструкций. И не нашел. Но в процессе поиска наткнулся на подробную статью с анализом интересующей меня информации и ссылками на первоисточники: Авачева Т. Г., Пруцков А. В. Современный взгляд на концепцию структурного программирования


Выводы


В результате получились вот таки итоги моего поиска:


  1. Структурная теорема о том, что любую блок-схему можно преобразовать в блок-схему, состоящую из блоков трех видов: следование, выбор и повторение доказали в 1966 году итальянские ученые К. Бём и Дж. Якопини (на итальянском языке статья была опубликована в 1965 году) Теорема Бёма — Якопини — Википедия. Данная теорема чисто теоретическая, доказана с учетом некоторых ограничений и была упомянута Э. Дейкстрой, в его работе "Go To Statement Considered Harmful".
  2. Принципы структурного программирования предложенные Э. Дейкстрой предназначены для улучшения стиля программного кода за счёт использования структур управления и отказа от других инструкций, управляющих ходом алгоритма, т.е. это не доказанная теорема, только предложение отказаться от использования, причем не только от оператора goto, но и от оператора присвоения значения: "Оператор goto позволяет нам посредством перехода назад повторить часть программы, тогда как оператор присвоения может создать необходимое различие в состоянии между последовательными повторениями."
  3. Э. Дейкстра в своей работе формулировал принципы структурного программирования в попытке автоматизировать доказательства правильности программ (программа – это последовательность вычислений. Вычисления можно записать математическими формулами. Следовательно, можно доказать теорему о правильности программы), но все же финальный вывод «Тестирование выявляет только наличие, но никак не отсутствие ошибок».
  4. Кроме трех видов алгоритмических конструкций (следования, ветвления и повторения) требуется еще механизм обработки ошибок (исключений), а иногда обработка прерываний и выполнение параллельных действий, без которых полноценная реализация отдельных алгоритмов будет невозможна.

З.Ы.


С наступающим Новым Годом!

Комментарии (59)


  1. rsashka Автор
    31.12.2023 15:58
    +2

    Затронутая проблема скорее всего не в перепутанных причине и следствии, а в некорректном обобщении.

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

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


  1. ultrinfaern
    31.12.2023 15:58
    +3

    Я думаю стоит различать алгоритм и его реализацию. В алгоритме указываются ограничения на входные параметры и все. Писать там что делать, если не открылся файл или в файле не те данные глупо (да и невозможно, так как ввод вывод специфичен для языка, операционки,...). А вот эти всякие исключения и остальные ошибки - это неидеальная реальность, не имеющая никакого отношения к алгоритму.


    1. rsashka Автор
      31.12.2023 15:58

      А проверки на "ограничения на водные параметры" это входит в алгоритм или постулируется?
      Если второе, тогда может получиться как в анекдоте "станьте ёжиками", когда есть требования к входным параметрам, но в реальности они не достижимы.


      1. RichardMerlock
        31.12.2023 15:58

        Алгоритм с кучей доп проверок и условий на входе, а также алгоритм с модульной структурой будет, скажем так, комплексным алгоритмом. У него есть основная идея, которую и надо изобразить "широкими мазками на первой странице". А далее раскрывать частности отдельными схемами, например, как стать ёжиками в 100500 шагов основной последовательности.


      1. yatanai
        31.12.2023 15:58

        Программисты старой школы всё ещё пишут условные if(ptr==nulltpr) return E_INVALID;

        Сейчас такая практика "устарела" и принято выкидывать исключения в рантайме, ибо обмазывать код if'ми на проверку корректности душно.


        1. lazy_val
          31.12.2023 15:58

          обмазывать код if'ми на проверку корректности душно

          Создатели Go не согласны

          Edit: Виноват, не дочитал тред до конца


    1. vabka
      31.12.2023 15:58
      +3

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


      1. GospodinKolhoznik
        31.12.2023 15:58
        +5

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


        1. Rive
          31.12.2023 15:58
          +1

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


        1. murkin-kot
          31.12.2023 15:58

          если появляется необходимость перехватывать ошибки, то это уже звоночек

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

          Исключения - это очень минималистичный способ в сравнении с предложением от ФП.


        1. mvv-rus
          31.12.2023 15:58
          +2

          что типы данных плохо описывают сущности с которыми работает программа.

          Ну да, типы данных в программах описывают сущности как-то метафизически, а не диалектически - без учета всеобщей связи и развития, без имманентных противоречий, свойственных сущностям объективной дествительности ( ;-) , даже самому удивительно, как это у меня загнуть получилось!). То есть, программы работают с сущностями, ограничивая тот набор абстракций, которыми в них описывается реальная сущность.

          Выражаясь фигурально...

          ...в качестве примера, возьмем программу для работы с сущностями типа "банан", который описывает некие абстрактные бананы. И не включает в этот тип, к примеру, мартышку, котрая может украсть банан - а ведь если программа работает со свежими бананами в джунглях с мартышками, то для полноты по логике предыдущего комментария надо описывать и такие казусы. И - не включает в тип "банан" сгнившие бананы, если программа работает на складе - где теперь мартышек нет, но зато бананы уже далеко не все свежие. Да, с одной стороны это ограничивает возможные ситуации, которые может обработать программа нарушения порядка своего выполнения - возбуждения исключений, которые требуется перехватывать. Но, с другой стороны, такая программа может работать с бананами одинаково, что в джунглях, что на складе.

          И в реальном программировании, ограничивая набор абстракций, заложенных в типе, используемом в программе,и реагируя на неподходящие случаи прерыванием нормального хода работы, разработчик делает программу более более универсальной и более пригодной для разнообразных применений.

          А вот где и как ограничивать - в этом-то и состоит ремесло разработчика. Которое, с одной стороны, опирается на науку, но с другой - граничит с искусством.


      1. eandr_67
        31.12.2023 15:58
        +1

        Именно так построена обработка ошибок в языке Go.


    1. LeninIvanov
      31.12.2023 15:58
      +1

      На кой чёрт нужен алгоритм, если он нежизнеспособен в реальности и его прямо надо допиливать?


      1. Pochemuk
        31.12.2023 15:58
        +1

        Алгоритм - это "костяк". Какое "мясо" на него налепят в реальности - не его проблемы.

        Алгоритм не привязан к конкретным программным или аппаратным решениям. Он - своеобразная абстрактная форма, которой всё равно, каким образом она будет реализовываться - в уме, на листике или с помощью камешков и палок.


        1. LeninIvanov
          31.12.2023 15:58

          Не путайте алгоритм с теорией. Последняя допускает ответвления и вольные трактовки, но не алгоритм.

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


  1. San_tit
    31.12.2023 15:58
    +4

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

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

    А исключения по сути -- это аналог goto (куда-то) вверх по стеку.


    1. CrazyOpossum
      31.12.2023 15:58

      Исключения ещё можно на континуациях сделать.


    1. rsashka Автор
      31.12.2023 15:58

      Я понимаю, что алгоритм и реализация, это совершенно разные вещи.
      Вот только выполнение даже идеально запрограммированного алгоритма происходит на реальном оборудования, в не идеальном окружении с различными входными данными.


  1. duke_alba
    31.12.2023 15:58

    Структурное программирование выстрелило в связи с большими сложностями IBM при создании первой большой ОС - они еле сумели её выпустить. Тогда и были продекларированы запреты на спагетти-код и, как следствие, на goto.

    Проблема давно ушла, а страхи всё ещё остались :-)


  1. kozlov_de
    31.12.2023 15:58
    +2

    Много математики потребовало функциональное программирование.

    А императивщина это так: тяп ляп


  1. Myclass
    31.12.2023 15:58

    Не совсем понял наезд на себя многими вещами зарекомендовавшее имя Э. Дейкстры. Мелочи, в которых такие как Э. Дейкстра не правы или недостаточно правы - это мелочи. В основном они создали или положили начало многим вещам, которые до сих пор используются или являются неотъемлемой частью программирования или .техники.


    1. rsashka Автор
      31.12.2023 15:58
      +12

      А никто не умаляет его достижения. Проблемы возникают когда полученные результаты начинают интерпретировать по собственному усмотрению не принимая во внимание ни контекст его работ, ни цели, ради которых эти работы велись.

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


  1. Orianti
    31.12.2023 15:58
    +4

    В выводах в п. 2 явно искажается смысл отрывка статьи Programming Considered as a Human Activity. Приведу чуть больший отрывок (в переводе Alf):

    «Давайте ограничимся рассмотрением языков программирования без операторов присваивания и перехода. При условии, что набор доступных функций достаточно широк и понятие условного выражения входит в число примитивов, можно описать вывод любой программы как значение большой (рекурсивной) функции. <…> Несмотря на элегантность подобного языка программирования, имеется серьезный довод против него. <…> Оператор goto позволяет нам посредством перехода назад повторить часть программы, тогда как оператор присвоения может создать необходимое различие в состоянии между последовательными повторениями.»

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


    1. rsashka Автор
      31.12.2023 15:58

      Так в статье и от goto не предлагается отказываться. Там говорится, что эти конструкции могут менять состояние программы, что вредит автоматическому выводу доказательства её правильности.


      1. Orianti
        31.12.2023 15:58
        +7

        Дело в том, что вы в статье пишете, что выдвигается «предложение отказаться от использования, причем не только от оператора goto, но и от оператора присвоения значения». Отношение Дейкстры к goto в целом известно, в двух словах его можно сформулировать следующим образом: он против. А вот критикой оператора присваивания он, кажется, не занимался. Поправьте меня, если что.


        1. rsashka Автор
          31.12.2023 15:58
          +1

          Ну хорошо, путь будет ваша формулировка т.е. не "отказаться", а "ограничимся рассмотрением языков программирования без операторов присваивания и перехода".

          Просто я пытаюсь обратить внимание не на критику тех или иных конструкций, а на причину этой критики. Ведь проблема не в том, что goto или оператор присвоения используется, а в том, что эти операторы мешают автоматическому выводу доказательства правильности программ.

          Согласитесь, было бы очень странно, если бы критиковались операторы присвоения. Как бы тогда вообще программы приходилось бы составлять? То ли дело goto, который легко заменить всякими break, continue и пр. (если что, это сарказм)

          А вот если обратится к первопричине (что эти управляющие конструкции меняют поведение линейного алгоритма), то мне кажется разумней было бы не гнобить goto,а продвигать принцип SSA (Static single assignment), который упрощает автоматизацию обработки и гереации кода с операторами присвоения. Жаль, что его разработали гораздо позже.


          1. Orianti
            31.12.2023 15:58
            +2

            Согласен, критиковать оператор присваивания действительно занятие довольно спорное. Именно поэтому и обратил внимание на эту формулировку. Но думаю, что мы пришли к общему знаменателю.

            Гнобить goto тоже считаю несправедливым, Кнут не даст соврать.


            1. RichardMerlock
              31.12.2023 15:58
              +3

              Если гнобить goto, то и if тоже надо гнобить. If - это условный goto под себя.


              1. vadimr
                31.12.2023 15:58
                +1

                Претензия к goto заключалась в том, что он передаёт управление далеко по тексту, то есть в каком-то смысле нарушает локальность.


                1. RichardMerlock
                  31.12.2023 15:58
                  +2

                  Я понимаю эти претензии, даже понимаю гугл с его собственным языком Go. Для разношерстной команды очень даже хорошо иметь язык со встроенным код-гайдом, когда особо нет варианта сделать уж совсем криво. Но как по мне, не стоит гнобить язык за возможности по отстреливанию ног. Лучше уж гнобить за низкую культуру кода.


              1. SadOcean
                31.12.2023 15:58

                Это очень странная логика)

                Понятно, что if под капотом и есть условный goto и в целом это сахар, но так за это его и любят)

                Так то и функция просто абстракция, можно использовать просто переменную для хранения обратного адреса и стек


                1. RichardMerlock
                  31.12.2023 15:58
                  +1

                  Странная, зато повышающая шанс открыть новые направления в обсуждении.


          1. Portnov
            31.12.2023 15:58
            +4

            Ну, если что, языков без оператора присваивания существует некоторое количество, и некоторые из них даже применяются на практике. И да, основное преимущество — как раз возможность (автоматического, автоматизированного или ручного) доказательства правильности программ.


  1. Pochemuk
    31.12.2023 15:58
    +3

    Структурное программирование - это декларируемый подход. Парадигма, т.е. Как эта парадигма будет реализована в конкретных ЯПВУ - отдельный вопрос. А как на этих языках будет написана конкретная программа - совсем уже третий.

    Ситуация напоминает ту, что сложилась с сетевыми протоколами. Есть декрарируемая семиуровневая модель OSI. А есть ее реализация - четырехуровневый стек протоколов TCP/IP. В нем одни уровни объединены, а другие - пересекаются. Но, тем не менее, стек TCP/IP не отрицает модель OSI, а базируется на ней и служит ее конкретной реализацией.

    Другой пример - язык Pascal. Не тот, который Object, а который просто. Создавался именно в соответствии с парадигмой СП, но дополняет её более сложными операторами ветвления, оператором выбора, различными формами операторов цикла, операторами break, continue и даже goto.

    И, кстати, все эти операторы (ну, кроме goto) прекрасно вписываются в понятие структурного программирования.


    1. vadimr
      31.12.2023 15:58
      +1

      Если занудствовать, то в “просто паскале” не было break и continue. Но goto был. Вирт тогда не решился сразу на радикальный шаг, но впоследствии убрал goto из Модулы.


      1. Pochemuk
        31.12.2023 15:58
        +1

        Таки, да. Сейчас поискал в Интернете, нашел, что операторы "break" и "continue" были введены в Turbo Pascal 7.0 в 1992 году.

        Давненько было. Хоть я начинал знакомство с Паскалем еще с третьей версии, но как там обстояло дело - не помню.


  1. feelamee
    31.12.2023 15:58
    +3

    Мне одному кажется, что цикл это и есть ветвление?


    1. rsashka Автор
      31.12.2023 15:58
      +5

      Нет, не одному. Но в этом случае пришлось бы использовать не кошеный goto, а он фууууу, бяка :-)


      1. lazy_val
        31.12.2023 15:58
        +1

        Разработчики на Fortran до версии IV включительно скорее всего с этим утверждением согласятся (по крайней мере те кто еще с нами)


  1. same_one
    31.12.2023 15:58
    +2

    Исключения это тот же GOTO, реализуемый простым переходом на блок кода по адресу в специальном регистре. Очень сомнительный механизм с точки зрения чистой алгоритмики.


    1. rsashka Автор
      31.12.2023 15:58
      +1

      Исключения это тот же GOTO

      Исключения, это не простой GOTO, а GOTO с раскруткой стека вызовов и освобождением ресурсов. И хотя исключения не являются линейными алгоритмами, но это все равно точно такой же алгоритм, не хуже и не лучше других, который решает поставленные перед ним задачи.


      1. GospodinKolhoznik
        31.12.2023 15:58
        +4

        Хуже - в той части, что логику работы программы с исключениями сложнее анализировать. Сложнее как человеку, так и автоматическим чекерам.


  1. Virviil
    31.12.2023 15:58
    +6

    Не надо путать причину и следствие. Наличие обработки исключений и некоторые другие элементы (например ключевое слово return) в большинстве современных языков программирования говорит лишь о том, что они нарушают принципы структурного программирования, а вовсе не о том, что без этих принципов нельзя писать программы. Можно!

    Вместо исключений - монады maybe|result как в Расте или просто err как в Го, вместо return - возвращаем последнее значение из функции как в том же Расте. Удобно ли так писать? Вопрос открытый. Но то что так можно делать реальный софт - это факт


    1. rsashka Автор
      31.12.2023 15:58
      +2

      Затронутая проблема скорее всего не в перепутанных причине и следствии, а в некорректном обобщении.

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

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


      1. rg_software
        31.12.2023 15:58
        +1

        Мне всегда казалось, что в "школьном" контексте фраза о том, что достаточно трёх видов конструкций приводится чтобы доказать, что без goto в принципе можно обойтись. Иными словами, исключая goto из арсенала, вы формально ничего не теряете. Опять же, формально тут всё справедливо: любое эффективное вычисление можно представить в виде машины Тьюринга, которая, очевидно, может быть реализована без goto. При этом, разумеется, можно придумать основанный на хитрых goto переходах алгоритм, который будет практически довольно сложно преобразовать в эквивалент без них.


        1. Pochemuk
          31.12.2023 15:58
          +1

          Если не ошибаюсь, в PL/1 были переменные типа "метка". Т.е., им можно было присвоить различные точки перехода goto динамически в процессе исполнения программы.

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


          1. mvv-rus
            31.12.2023 15:58
            +1

            Если не ошибаюсь, в PL/1 были переменные типа "метка".

            Такие переменные и assigned GOTO для их использования были и в Фортране - том самом, который использовали настоящие программисты.


        1. rsashka Автор
          31.12.2023 15:58

          Можно обойтись для тех алгоритмов, которые рассматриваются в школе.


          1. rg_software
            31.12.2023 15:58

            Не совсем понял комментария - вы можете привести пример алгоритма, который не реализуется на машине Тьюринга?


            1. rsashka Автор
              31.12.2023 15:58

              Не совсем понял комментария - вы можете привести пример алгоритма, который не реализуется на машине Тьюринга?
              "любое эффективное вычисление можно представить в виде машины Тьюринга, которая, очевидно, может быть реализована без goto."

              Но позвольте, мне совершенно не очевидно, да и в Вики написано, что Машина Тьюринга является расширением конечного автомата и, согласно тезису Чёрча — Тьюринга, способна имитировать всех исполнителей (с помощью задания правил перехода).

              Может быть вы приведите пример машины Тьюринга без goto?

              Но чтобы не углубляться в дебри софистики, можно просто привести примеры алгоритма, которому будет не достаточно упомянутых выше трех алгоритмических конструкций. Это любая обработка прерываний и параллельное выполнение.


              1. rg_software
                31.12.2023 15:58

                Машина Тьюринга тривиально реализуется без goto. Что-то в этом роде:

                rules = { (0, 0): (1, 2, 1), (1, 3): (5, 2, -1), ... }
                tape = [0, 6, 1, ...]
                state = 0
                pos = 0
                
                while tape[pos] != 'HALT':
                    state, tape[pos], move = rules[(state, tape[pos])]
                    pos += move
                

                "Правила перехода" -- это функция машины, а не эмулятора, который эту машину рализует.

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


  1. vassabi
    31.12.2023 15:58

    если принять что исключения - это "выключения питания", то

    1) не надо добавлять отдельные средства работы с ними

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


    1. rsashka Автор
      31.12.2023 15:58
      +1

      И все же исключения - это не "выключение питания". На них может быть завязан отдельная ветка алгоритма для обработки ошибок, да и программа не прекращает свою работу при при возникновении исключения, как безусловно было бы при реальном "выключении питания"


      1. vassabi
        31.12.2023 15:58

        ну, я понимаю, что это не настоящее выключение.

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

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


        1. rsashka Автор
          31.12.2023 15:58

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

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

          Поэтому "перестартовывает логику в ближайшем обработчике исключения" - это не что иное, как часть алгоритма хорошей программы.


          1. vassabi
            31.12.2023 15:58

            "учитывание обстоятельства" - это всего лишь надстройка над поведением, его конечно удобно вставлять рядом с кодом, который не выполнился.

            но это не "что там дальше делать с алгоритмом задачи?", это алгоритм восстановления "меня прервали, что это было - деление на 0 ? кончилась память? файла нет ? процесс убит ?" и т.д.


  1. Sdima1357
    31.12.2023 15:58
    +4

    Как я понимаю, речь шла не о присвоении значений переменным вообще , а о так называемом "side effect" ( недеклрируемое явно изменение состояния системы внутри фунции ) при вызове функций мешающему отладке и вызывающему неопределённое поведение.


  1. AcckiyGerman
    31.12.2023 15:58
    +1

    Как-то давно переводил статью на эту же тему в контексте паралельных вычислений: https://habr.com/ru/articles/479186/


  1. murkin-kot
    31.12.2023 15:58

    следование, выбор и повторение

    Не скажу в каком году и кто доказал, но для любой программы достаточно лишь выполнения одной инструкции по заданному адресу. Параметры "инструкция" и "адрес", разумеется, меняются динамически. Далее сужаем круг кандидатов на параметр "инструкция". Их всего две - "и+не" или "или+не". Обе должны читать и записывать значения по адресу. Итого параметров - данные (произвольные) и адреса.

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

    Более сложные операции, включая операции из авторского текста, нужны лишь для слабых мозгов, которые нас сильно ограничивают и требуют разжёвывания. Умным мозгам достаточно двух операций на машине с произвольным доступом к памяти.


  1. ALexKud
    31.12.2023 15:58
    +2

    В своей публикации на хабре я описал свою систему программирования тестов, в которой используется только линейный и циклический алгоритм. Xотя я и включил в систему команд оператор Go to, но использовать его в программе теста было неудобно, так как автоматический выход из цикла был не нужен, гораздо удобнее было привязать операцию с параметром к номеру цикла и использовать параметр- указатель пропустить команду в цикле или выполнить. Go ТО для выхода из цикла оказался не нужен. Тем более не нужен в линейной части алгоритма, так как if за ненадобностью не поддерживался. Только линейный и циклический алгоритм успешно решил все задачи. Для отладки программы был предусмотрен переход на любой оператор программы теста только в ручном режиме, примерно также как в IDE ЯП.