Чем быстрее вы забудете ООП, тем лучше для вас и ваших программ

Автор оригинала: Dawid Ciężarkiewicz
  • Перевод

Объектно-ориентированное программирование — чрезвычайно плохая идея, которая могла возникнуть только в Калифорнии.

— Эдсгер Вибе Дейкстра

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

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

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

Данные важнее, чем код


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

Этот момент очень важен, так что я повторюсь: цель -> архитектура данных -> код. Здесь порядок менять ни в коем случае нельзя! При проектировании программы нужно всегда начинать с выяснения цели, которой нужно достичь, а затем хотя бы приблизительно представить архитектуру данных: структуры и инфраструктуру данных, необходимые для её эффективного достижения. И только после этого нужно писать код для работы с такой архитектурой. Если со временем цель меняется, то нужно сначала изменить архитектуру данных, а потом код.

По моему опыту, самая серьёзная проблема ООП заключается в том, что оно мотивирует игнорировать архитектуру модели данных и применять бестолковый паттерн сохранения всего в объекты, обещающие некие расплывчатые преимущества. Если это подходит для класса, то это отправляется в класс. У меня есть Customer? Он отправляется в class Customer. У меня есть контекст рендеринга? Он отправляется class RenderingContext.

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

Мотивирование к сложности


При проектировании архитектуры данных в явном виде результатом обычно является минимальный необходимый набор структур данных, обслуживающих цель нашего ПО. Если мыслить в категориях абстрактных классов и объектов, то грандиозность и сложность абстракций сверху ничем не ограничивается. Просто взгляните на FizzBuzz Enterprise Edition — такую простую задачу можно реализовать в столь большом количестве строк кода лишь потому, что в ООП всегда есть место для новых абстракций.

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

Повсюду графы


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

У вашего class Customer есть ссылка на class Order, и наоборот. class OrderManager содержит ссылки на все Order, а потому косвенно и на Customer. Всё стремится ссылаться на всё остальное, потому что постепенно в коде появляется всё больше мест, ссылающихся на связанный объект.

Вам нужен был банан, но вы получили гориллу, держащую банан, и целые джунгли.

ООП-проекты обычно выглядят не как качественно спроектированные хранилища данных, а как огромные спагетти-графы объектов, указывающих друг на друга, и методы, получающие огромные списки аргументов. Когда вы начинаете проектировать объекты Context просто для того, чтобы урезать количество передаваемых туда-сюда аргументов, то понимаете, что пишете настоящий ООП-код уровня Enterprise.

Задачи поперечных срезов


Подавляющее большинство существенного кода не работает всего с одним объектом, а на самом деле реализует задачи поперечных срезов. Пример: когда class Player ударяет при помощи метода hits() class Monster, где на самом деле нужно изменять данные? Величина hp объекта Monster должна уменьшиться на attackPower объекта Player; величина xp объекта Player должна увеличиться на уровень Monster в случае убийства Monster. Должно ли это происходить в Player.hits(Monster m) или в Monster.isHitBy(Player p)? Что если здесь нужно учитывать и class Weapon? Мы передаём аргумент в isHitBy или у Player есть геттер currentWeapon()?

Этот упрощённый пример со всего тремя взаимодействующими классами уже становится типичным кошмаром ООП. Простое преобразование данных превращается в кучу неуклюжих взаимопереплетённых методов, вызывающих друг друга, и причина этого только в догме ООП — инкапсуляции. Если добавить в эту смесь немного наследования, то мы получим хороший пример того, как выглядит стереотипное ПО уровня Enterprise.

Шизофреническая инкапсуляция объектов


Давайте взглянем на определение инкапсуляции:

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

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

Не поймите меня неверно — наложение ограничений, особенно в случае ADT, обычно является хорошей идеей. Но в ООП со всеми этими перекрёстными ссылками объектов инкапсуляция часто не достигает ничего полезного, а учитывать ограничения, разбросанные по множеству классов, довольно сложно.

По моему мнению, классы и объекты слишком дробные, и с точки зрения изоляции, API и т.д. лучше работать в пределах «модулей»/«компонентов»/«библиотек». И по моему опыту, именно в кодовых базах ООП (Java/Scala) модули/библиотеки не используются. Разработчики сосредоточены на том, чтобы соорудить ограждения вокруг каждого класса, не особо задумываясь над тем, какие группы классов в совокупности формируют отдельную, многократно используемую, целостную логическую единицу.

На одинаковые данные можно смотреть по-разному


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

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

Это ещё и является основной причиной объектно-реляционного разрыва. Хоть реляционная структура данных и не всегда бывает наилучшей, она обычно достаточно гибка, чтобы с ней можно было работать различными способами, пользуясь разными парадигмами. Однако жёсткость организации данных в ООП вызывает несовместимость с любой другой архитектурой данных.

Низкая производительность


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

Какой же подход использовать вместо ООП?


Я не думаю, что существует «серебряная пуля», поэтому просто опишу то, как это обычно сегодня работает в моём коде.

Первым делом я изучаю данные. Анализирую, что поступает на вход и на выходы, формат данных, их объём. Разбираюсь, как данные должны храниться во время выполнения и как они сохраняются: какие операции должны поддерживаться и с какой скоростью (скорость обработки, задержки) и т.д.

Обычно если данные имеют значительный объём, моя структура близка к базе данных. То есть у меня будет некий объект, например DataStore с API, обеспечивающим доступ ко всем необходимым операциям для выполнения запросов и сохранения данных. Сами данные будут содержаться в виде структур ADT/PoD, а любые ссылки между записями данных будут представлены в виде ID (число, uuid или детерминированный хеш). По внутреннему устройству это обычно сильно напоминает или на самом деле имеет поддержку реляционной базы данных: Vecторы или HashMap хранят основной объём данных по Index или ID, другие структуры используются как «индексы», необходимые для выполнения быстрого поиска, и так далее. Здесь же располагаются и другие структуры данных, например кеши LRU и тому подобное.

Основная часть логики программы получает ссылку на такие DataStore и выполняет с ними необходимые операции. Ради параллелизма и многопоточности я обычно соединяю разные логические компоненты через передачу сообщений наподобие акторов. Пример актора: считыватель stdin, обработчик входящих данных, trust manager, состояние игры и т.д. Такие «акторы» можно реализовать как пулы подпроцессов, элементы конвейеров и т.п. При необходимости у них могут может быть собственный или общий с другими «акторами» DataStore.

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

Основная идея такова: только потому, что моё ПО работает в области, где есть концепции, например, клиентов и заказов, в нём не обязательно будет класс Customer и связанные с ним методы. Всё наоборот: концепция Customer — это всего лишь набор данных в табличной форме в одном или нескольких DataStore, а код «бизнес-логики» непосредственно манипулирует этими данными.

Дополнительное чтение


Как и многое в проектировании программного обеспечения, критика ООП — непростая тема. Возможно, мне не удалось чётко донести свою точку зрения и/или убедить вас. Но если вы заинтересовались, то вот ещё несколько ссылок:

Поддержать автора
Поделиться публикацией

Комментарии 1266

    +51

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

      –12
      те языки и подходы, которые в итоге оказывались самыми практичными и популярными

      Популярность — продукт рекламы и продвижения крупными компаниями. Качество при этом и рядом не валялось. Только финансовые интересы.

      А с учетом такой популярности про практичность говорить бессмысленно.

      Всё-таки между академическим программированием и прикладным есть большая разница.

      Прикладное программирование — это когда школота лепит быдлокод? Для них и придуман был ООП.
      Один мой знакомый в давние времена сказал такую умную вещь: объектное программирование должно быть в голове, а не в языке.

      А большинству современных программистов до Дейкстры, как до Шанхая…
        +24
        Прикладное программирование — это когда школота лепит быдлокод?

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

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

        Хотим мы с вами или нет, но мы решаем задачи бизнеса. А пользователь на бизнес стороне, как правило, понятия не имее про ООП или BDD или синглтон. Ему наплевать что там в кишках! Он просто тыкает кнопку и если она не решает его задачу он не платит денег. И хоть вы там идеальную архитектуру наколбасите ему будет пофиг, лишь бы кнопка делала то что надо!
          +19
          Проблема быдлокода лежит в другой плоскости. Ну набросал ты по быстрому и оно у тебя даже работает, продал… и тут клиент хочет ещё рюшечку добавить, ну так мелочь и с точки зрения клиента это решается просто «ну оно же тут вот… сюда сюда и всё» а вы смотрите в код и понимаете что нужны изменения которые будут стоить так же как исходный продукт, а то и дороже. И с каждым очередным внедрением этих рюшечек будет всё сложнее, дольше и дороже. В конечном итоге получается программа-мотылёк, поработала один день и дешевле написать новую чем модифицировать эту.
            +1
            Собственно всё упирается в том, что мы не умеем делать хорошие программы. Не в том смысле, что технологий нет. Нет культуры. Как в 90е, когда «новые русские» ринулись строить свои безумные котеджи.

            Когда вас просят «добавить рюшечку» и вы это делаете — без плана и дизайна, то получается пресловутый Дом Винчестеров.
            Как-то примерно так
            Пользоваться этим неудобно, но зато можно постоянно перестраивать.

            Автор же, совершенно справедливо, отмечает, что нормальные, удобные дома — так не строят. Но до этого индустрия разработки ПО — пока не доросла.
              +4

              На самом деле методы написания хороших программ были придуманы и стандартизованы ещё во времена первых Space Shuttle. Просто до сих пор мало кто в это умеет: из-за холиварщиков типа Дейкстры программисты уже три десятка лет занимаются поиском самого "правильного" языка программирования и обсиранием "неправильных" языков: это как если бы электронщики каждые 5-10 лет придумывали новый набор обозначений на схемах для отображения всё тех же резисторов, транзисторов и конденсаторов.


              А решение проблемы находится на более высоком уровне: на уровне организации, методик и подходов.

                +1
                А решение проблемы находится на более высоком уровне: на уровне организации, методик и подходов.
                … которые не позволяют даже NASA избежать ошибок…

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

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

                      0
                      Есть 2 обозначения резисторов, «советский» прямоугольником и «западный» пилой. Диоды следовало бы пересмотреть — когда рисовали их значок, думали что ток течёт в другую сторону, а дальше «так исторически сложилось».
                      Навскидку.
                        +1

                        Всё в порядке с диодами, просто не надо путать направление тока и направление движения электронов!


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

                          0
                          Есть 2 обозначения резисторов, «советский» прямоугольником и «западный» пилой.

                          Есть примеры и в математике: tg и tan, скажем. Или десятичная запятая/точка.


                          Диоды следовало бы пересмотреть — когда рисовали их значок, думали что ток течёт в другую сторону, а дальше «так исторически сложилось».

                          А вот тут никакой проблемы нет. Направление тока (туда же, куда электроны, или в противоположную сторону) вообще не имеет особого значения на практике для расчёта цепей. Надо просто один раз договориться. И договорились: от плюса к минусу.

                      0
                      На самом деле методы написания хороших программ были придуманы и стандартизованы ещё во времена первых Space Shuttle.
                      И сколько такие методы будут стоить компаниям? В том-то и проблема что хорошесть программ может определяться очень разными способами, не существует универсального параметра качества. И стоимость разработки решения практически всегда вносит определенный вклад в то, насколько программа хороша для ее заказчика.
                    +1

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

                      0
                      Нужно исходить из ситуации. Какие могут вообще ситуации?
                      1. Пользователь решил проблему. Больше не пришел
                      2. Кроме одного пользователя эту сделанную фичу больше никто не использовал
                      3. Пользователь решил проблему. Пришел с багой\предложением

                      и еще 100500 вариантов развития будущего.

                      Вы уверены, что в написанном коде вам действительно придется ковыряться и что-то переделывать? Да, можно вспомнить закон Мерфи про то что худшее по-любому случится, если оно может случиться. Но на практике вариаций развития будущего масса! Как надо будет переписывать так и не надо, а иногда и оказалось не надо и лучше удалить код, нет кода — нет багов!

                      Мы же когда пишем код мы же обычно так поступаем:
                      Встретилась задача просто пишем код. Встретилась второй раз тупо копи-пастим. Встретилась в третий — выносим в отдельную функцию. Втретилась в четвертый — выносим в библиотеку.

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

                      Другими словами: Если значимость и ценность кода еще не доказана требованиями бизнеса, то тратить на него слишком много времени и усилий не следует. Исходить нужно из математической фразы «необходимо и достаточно»
                        0
                        Исходить нужно из математической фразы «необходимо и достаточно»

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

                      –1
                      Все так. Вот в чистом виде конфликт между экономикой для результата и экономикой для прибыли.

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

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

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

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

                      И еще, популярность Java Scrip обусловлена саботажем разработчиков браузеров. Почему нельзя сделать нормальный вменяемый язык для фронтенда с контролем типов? Вот и выросло поколение горе-программистов, не понимающих, зачем нужен статический контроль типов, проверка используемости процедур (или, как сейчас модно говорить, методов). Объяснять таким полезность контроля равносильно попытке объяснять глухому от рождения величие классической музыки. И это не их вина, это их беда.
                        0
                        Почему нельзя сделать нормальный вменяемый язык для фронтенда с контролем типов

                        А разве таковым не был Dart который не взлетел?

                          0
                          Не знаю, не знаком. А вот то, что взлетело, это как птица в том анекдоте — летит и гадит.
                            +1

                            Сейчас уже есть typescript который потихонечку взлетает и webassembly

                          0
                          Думаю, что Джон МакКарти (отец LISP, 50-е годы) и многие другие великие и умные люди сказали бы вам много причин, по которым статический контроль типов не нужен.
                            +2
                            Не нужен — да, обходился же LISP без него. Полезен? Ну я думаю Джон МакКарти не стал бы заниматься LISP 2 с поддержкой статической типизации, если бы он считал эту идею бессмысленной.

                            Другое дело, что оказалось не так-то просто добавить статическую типизацию в LISP и не потерять его выразительности…
                              +3

                              Думаю, что многие другие великие и умные люди вроде Пирса, Барендрегта, Мартина-Лёфа или Жирарда с ним бы с интересом побеседовали о нужности типов.

                                –1
                                И Алан Кей и Рич Хики говорят, что ещё не видели системы типов, которая бы помогала, а не мешала, и не причиняла бы боль. Очень возможно, что из Haskell/Rust/F# сообщества появится такая система типов. А до тех пор у нас будут void *, interface {} и пр. в языках, которые имеют статическую типизацию.

                                Самая лучшая апологетика динамической типизации (не с ура-пофигистских позиций типа «а нафига типы?»), которую я видел, здесь:
                                youtu.be/YR5WdGrpoug
                                youtu.be/2V1FtfBDsLU?t=1143 (можно даже отсюда начать: youtu.be/2V1FtfBDsLU?t=1639)
                                  +1
                                  И Алан Кей и Рич Хики говорят, что ещё не видели системы типов, которая бы помогала, а не мешала, и не причиняла бы боль. Очень возможно, что из Haskell/Rust/F# сообщества появится такая система типов.

                                  Она, ну, именно что уже есть. Пишу на хаскеле, система типов очень помогает, ни на что её не променяю.


                                  А до тех пор у нас будут void *, interface {} и пр. в языках, которые имеют статическую типизацию.

                                  Ни разу не использовал void* даже в C++, ЧЯДНТ?


                                  Самая лучшая апологетика динамической типизации (не с ура-пофигистских позиций типа «а нафига типы?»), которую я видел, здесь

                                  Расшифровка есть?

                                    0
                                    Расшифровка есть?

                                    Текст выступления? Или перевод на русский?
                                    Насколько я знаю, ни того, ни другого нет.
                                      +1

                                      Текст, лучше в оригинале.


                                      Жалко, смотреть видео — ну такое.

                                      –2
                                      Ни разу не использовал void* даже в C++, ЧЯДНТ?

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

                                        А void* — да, с ним авторы библиотек пусть возятся. Это их работа.
                                          –4
                                          Ну да, Вы же весь в белом! Зачем Вам руки пачкать? Так?
                                          +1

                                          Какие авторы?


                                          Я, если что, писал свой any и свой variant. Даже там как-то удалось обойтись без void*.


                                          Единственная библиотека, которую я могу вспомнить и которая использует void* достаточно активно — Qt, да и то потому, что они так реализуют сигналы/слоты для совместимости со старыми компиляторами.

                                            –1
                                            Я, если что, писал свой any и свой variant. Даже там как-то удалось обойтись без void*.

                                            Было бы занятно взглянуть. Это возможно?
                                              +1

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


                                              Но, если в общем говорить, any делается через type erasure, variant — на самом деле даже проще, через вариадики.

                                                –1
                                                Никогда толком не вникал, что такое type erasure, но интуитивно тот же void*, вид сбоку. А в Вашем variant на вариадики (шаблоны, я верно понял?) можно менять содержимое на другой тип после объявления?
                                                Если Вы используете такой срез C++, где не нужно явно использовать просто машинный адрес и/или взаимодействовать с C — почему нет. Но я бы не стал этим гордится)))
                                                  0
                                                  Никогда толком не вникал, что такое type erasure, но интуитивно тот же void*, вид сбоку.

                                                  Не, ну если под определённым углом...


                                                  А так — указатель на базовый класс, от которого наследуется шаблонный производный класс. Всё. Никаких void*, всё очень типобезопасно.


                                                  А в Вашем variant на вариадики (шаблоны, я верно понял?) можно менять содержимое на другой тип после объявления?

                                                  Вы имеете в виду такое?


                                                  variant<int, std::string> v { 42 };
                                                  v = "42";

                                                  Если такое, то да, можно. Там внутри тоже в каком-то смысле type erasure вылезет, но за счёт того, что список типов известен статически, можно даже в RTTI не лазать.


                                                  Если Вы используете такой срез C++, где не нужно явно использовать просто машинный адрес и/или взаимодействовать с C — почему нет. Но я бы не стал этим гордится)))

                                                  Ну, под атмеги я тоже когда-то писал, ещё когда школотроном был. Кстати, тоже void* особо не нужно было, всё очень быстро обмазалось темплейтами, но не суть.


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

                                                    –1
                                                    А так — указатель на базовый класс, от которого наследуется шаблонный производный класс. Всё. Никаких void*, всё очень типобезопасно.

                                                    И указатель на этот самый базовый класс и оказывается нижней гранью выбранной «подсистемы» типов. Но C++ не ограничивается только этой «подсистемой», поэтому void* в нем необходим.
                                                    Я понял, что Вы имеете в виду. Согласен, для каждого конкретного случая можно обойтись без void*, зафиксировав нужные типы в параметрах шаблонов.
                                                    Но не согласен, что void* не является полноценным элементом системы типов. Как и просто void, в шаблонах он тоже вылазит и, по слухам, там без него не обойтись. То, что void* можно использовать для обхода типизации — следствие наличия в языке низкоуровневых средств и особенностей типа «указатель на» (преобразование T*->void*->T* безопасно). Именно это средство C++ делает возможным «бескомпромиссную совместимость» с миром C и с аппаратурой, например.
                                                    Так что гордится тем, что ни разу не использовал void* не стоит: просто повезло запереть себя в «чистой комнате». Как-то так)
                                                      +1
                                                      Но не согласен, что void* не является полноценным элементом системы типов.

                                                      Является, конечно, обратного никто и не говорил. Наоборот, там выше было утверждение (на которое я и отвечал), что void* прям нужен в C++, иначе никуда.


                                                      То, что void можно использовать для обхода типизации — следствие наличия в языке низкоуровневых средств и особенностей типа «указатель на» (преобразование T->void->T безопасно). Именно это средство C++ делает возможным «бескомпромиссную совместимость» с миром C и с аппаратурой, например.

                                                      T* -> char* -> T* тоже безопасно, кстати. Или через std::byte теперь.


                                                      Впрочем, давайте с другой стороны. Почему при работе с железом нельзя обойтись без void*?

                                                        0
                                                        Впрочем, давайте с другой стороны. Почему при работе с железом нельзя обойтись без void*?

                                                        Возможно, это просто историсеское наследие, но думаю, что преобразование беззнаковых целых в указатели так или иначе включает «создание» void* из целого. Указатель ведь, по сути, структура с битовыми полями и кучей атрибутов, и на низком уровне на него накладываются ограничения, которые, ну, скажем, невыразимы в языке, по крайней мере в текущем виде. Нужен какой-то тип данных, который позволит все это делать. Я так думаю. Это может быть и не видно явно, для C и даже C++ такая спрятанная в компилятор неявность — дело обычное.
                                                        И да, указатель на байт может заменить указатель на void. Но что это даст в плане типобезопасности? Те же яйца, вид сбоку, в gnuc void* ведет себя, как byte*.
                                                        Вон сколько уже ISO/IEC TR 18037 все не примут, так и нужда пройдет.
                                                          +1
                                                          Возможно, это просто историсеское наследие, но думаю, что преобразование беззнаковых целых в указатели так или иначе включает «создание» void* из целого.

                                                          Зачем? reinterpret_cast<Foo*>(0xd34df00d). Снова никаких void*.

                                                            0
                                                            Если честно, то не задумывался, что можно через reinterpret_cast, пребывал в заблуждении, что все-таки нужен указатель. Не сказал бы, что это чем-то лучше.
                                                            Остался в языке для совместимости с C, видимо.
                                                            Сколько безобразного кода люди готовы написать только для того, чтобы гордо заявлять «мне void* не нужен!»… )))
                                                              0

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


                                                              Да и как вы в C++ из void* получите более типизированный указатель, кроме как кастом? Это в C он сам ко всему приводился.

                                                                0
                                                                В молодости я тоже так думал.)))
                                                                А сейчас и (void*) кажется годным, да и пишу больше на C…
                                                                Хотя согласен, если уж плюсы, то лучше если все по взрослому, чтобы без слез на код не взглянуть. Более строгая типизация, чего уж там.
                                                                  0

                                                                  Ну это уж совсем субъективный вопрос. Я бы не сказал, что код на плюсах стрёмнее потому, что там reinterpret_cast вместо того, чтобы всё заметать под ковёр void*.

                                          +3
                                          И Алан Кей и Рич Хики говорят, что ещё не видели системы типов, которая бы помогала, а не мешала, и не причиняла бы боль.

                                          Ну вы не ровняйте всех программистов с Кеем и Хикки. Им, может, и не помогает, а программистам ниже уровня — помогает вполне.
                                          Я вот дурачок, самому думать трудно, по-этому мне часто проще, когда за меня думает тайпчекер.


                                          Самая лучшая апологетика динамической типизации

                                          Рассуждать о динамике вс статике сейчас имеет смысл исключительно в контексте тайскрипта. С-но, значительную часть проблем тс решает, из оставшейся части значительную часть — не решает, но оно в принципе решаемо.

                                            0

                                            Так я с вами полностью согласен, и я тоже дурачок. Только, кажется, отвечали вы на самом деле не мне, ну да ладно.

                                              0
                                              Только, кажется, отвечали вы на самом деле не мне, ну да ладно.

                                              Да, сорри. Запутался в ветках :)
                                              Это был ответ на пост evocatus, конечно же.

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

                                    Потому что предпочтительнее считается смотреть не только на один день вперед, но ещё и на два, а иногда и ещё больше, например?

                                    Если вы конечно не фрилансер, или не аутсорс контора которая не заботиться о своей репутации и стремиться выжать из заказчика денег любым способом и распрощаться
                                      0
                                      Потому что предпочтительнее считается смотреть не только на один день вперед, но ещё и на два, а иногда и ещё больше, например?
                                      Далеко не всегда. Стандартная ситуация с начинающей компанией — есть предположение что наше решение решит чью-то проблему. Можно долго создавать крутое решение, потратить кучу денег на него, а можно быстро накидать МВП и выкатить его. В случае если решение действительно нужное — да, первый вариант, скорее всего, в итоге окажется выгоднее. Если не совсем и нужно допиливать — возможно и так, и так. Если совсем нет, то, очевидно что второй вариант потратит заметно меньше ресурсов. И даже в первом случае выкатить что-то на говнокоде и допиливать потом имеет смысл. Потому что оно принесет денег вот сейчас — тех самых денег, которые нужны чтобы таки сделать хороший продукт. Совсем не факт что такие деньги на старте вообще есть.
                                      Я что пытаюсь сказать на самом деле — заглядывать в будущее конечно хорошо и правильно, вот только никто не умеет это делать надежно. И в условиях ограниченных ресурсов вариант делать сейчас как кажется правильным, а что будет потом — будет потом, вполне может оказаться выгоднее.
                                        0
                                        Стандартная ситуация с начинающей компанией — есть предположение что наше решение решит чью-то проблему. Можно долго создавать крутое решение, потратить кучу денег на него, а можно быстро накидать МВП и выкатить его.

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

                                        очевидно что второй вариант потратит заметно меньше ресурсов

                                        martinfowler.com/bliki/DesignStaminaHypothesis.html

                                        И даже в первом случае выкатить что-то на говнокоде и допиливать потом имеет смысл

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

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

                                        А может совсем и не оказаться. Вопрос в том, происходит ли оценка рисков, или higest payed person/product owner считает что «так выгоднее», потому что ни капли не программист и далёк от критериев качества ПО.
                                          0

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

                                            0
                                            Может конечно такой вариант развития событий имеет место быть, но я ни разу не слышал о ситуациях когда люди просто взяли и выкинули своё MVP, скинув пальму первенства. Как можно бизнесу/юзерам/инвесторам продать остановку новых фич, поиск хороших работников, потому что низкое качество MVP часто обусловлено ещё и наймом самых дешевых программистов с рынка, и переписывание проекта с нуля я слабо представляю.
                                              0

                                              Легко можно продать:


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

                                              :)

                                                0
                                                Это на словах легко )
                                                Может, как я и писал, можно, но я не слышал о таких success story, возможно потому что объяснять уже нужно будет не только бизнесу, а ещё и юзерам/инвесторам как-то сознаться что в продукте все не так радужно.
                                                Возможно потому, что, опять же, дорого, конкурентов надо как-то обгонять.
                                                  0

                                                  Я понимаю, потому и смайлик поставил. На самом деле при разработке чего-то вроде MVP и его дальнейшем развитии я стараюсь искать баланс между скоростью и поддерживаемостью/расширяемостью/… Благо веб-разработка позволяет относительно малой кровью совмещать старый и новый код даже на разных фреймворках, языках, ОС и прочих платформах, часто всего лишь изменением конфига реверс-прокси.

                                            0
                                            За ссылку на Фаулера спасибо (хотя я подозреваю что конкретно это я уже читал), но речь не о том, чтобы меньше тратить на дизайн. Речь о том, что есть множество неизвестных. Можно попробовать долго и упорно уменьшать их количество на стадии дизайна — организовывать опросы, разбирать детально предметную область, может быть заказать парочку исследований даже. И только после этого закончить дизайн. А можно — разработать дизайн с кучей неизвестных, выкатить демо версию и посмотреть на реакцию. Я понимаю что аналогия будет выглядить не очень уместной, но мне кажется она подходит: это как с тестовым запуском ракеты — есть масса неизвестных, которые можно промоделировать за большие деньги и долго, а можно быстрее и дешевле (не всегда конечно) сделать прототип, запустить его и просто все что нужно измерить.
                                            конкуренты будут делать качественный и стабильный продукт, выкатывая новые фичи в срок и не ломая старый фукционал.
                                            Чтобы получилось как вы говорите нужно чтобы конкуренты умели сделать быстро и качественно то, что мы умеем либо быстро, либо качественно. В рельности же скорее всего конкуренты после нашего MVP будут все же на шаг позади. И если они начнут долго и упорно пилить идеальный продукт, то о них можно вообще не думать, к тому моменту как они закончат рынок уже будет поделен среди тех кто выкатывал быстро но не очень качественно.
                                            Вопрос в том, происходит ли оценка рисков, или higest payed person/product owner считает что «так выгоднее», потому что ни капли не программист и далёк от критериев качества ПО.
                                            А этот вопрос вообще за рамками текущего обсуждения. То же самое может произойти в любом случае.
                                              0
                                              Дело в том что проект и с кучей неизвестных можно сделать более менее качественным и расширяемым, и не иметь необходимости его переписывать. А можно наклепать и за несколько месяцев такого, что расширять не проще чем с нуля переписывать.

                                              Ну и обычно MVP всё же часть будущего продукта, а не вещь которую скоро выкинут
                                                0
                                                Дело в том что проект и с кучей неизвестных можно сделать более менее качественным и расширяемым, и не иметь необходимости его переписывать.
                                                Я в этом не уверен. В каких-то частных случаях — наверняка. Но мне не сложно представить случай когда расширяемость будет сделана не для того и не туда для чего и куда она будет нужна. Можно попробовать запланировать расширяемость во все возможные направления, но результат будет так себе выглядеть и работать будет, скорее всего, совсем не просто. И даже так для меня не очевидно что это в принципе всегда возможно.
                                                  0
                                                  Невозможность архитектуры приспособиться к каким-либо изменениям говорит об ошибках в проектировании, и чем менее качественная у программы архитектура, тем сложнее вносить в неё изменения, вот и всё.
                                                  Анализ потока изменений имеет место быть, но при грамотном проектировании не должно происходить ситуаций требующих переписывания значительной части приложения, а в «написанном школниками на коленке» MVP — вполне себе.
                                                    0

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

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

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

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

                                                        Между случаем когда опытные разработчики хоть немного задумываются об архитектуре на MVP, и случаем, когда проект делают, как выше было сказано, «школьники на коленке», разница огромна.

                                                        Ну и время на создание MVP все же оптимизируется сокращением и упрощением фич, а не выкидыванием этапа проектирования/рефакторинга.
                                                          0
                                                          Предполагать будущее — так себе затея.
                                                          Конечно. Именно об этом я и говорю. Но не предполагая будущего вы не сможете построить расширяемую систему. Потому что вам необходимо знать куда она должна уметь расширяться.
                                                          не выкидыванием этапа проектирования/рефакторинга.
                                                          Никто не говорит про выкидывание. Но очевидно что на этот этап можно потратить разное количество времени. И достаточно очевидно что с какого-то момента дополнительное затраченное на него время будет приносить все меньше и меньше пользы, а потом даже начнет работать во вред. Вы про overengeneering когда-нибудь слышали? Термин не на пустом месте появился, его не маркетологи придумали.
                                                            0
                                                            Но не предполагая будущего вы не сможете построить расширяемую систему. Потому что вам необходимо знать куда она должна уметь расширяться.

                                                            Так ведь суть проектирования в том чтобы при появлении новых / изменении требований менять как можно меньше кода, для этого ведь нужны всякие DI, OCP, ISP. Подготовить почту для каки-то определыннх вариантов развития, и совершенно не учитывать другие сродни игры в русскую рулетку в которой при удаче проигрыш лишь отложиться на некоторое время.

                                                            Вы про overengeneering когда-нибудь слышали? Термин не на пустом месте появился, его не маркетологи придумали.

                                                            Да, но я не считаю что посадить на проект разработчиков, а не «школьников на коленке» — оверинжиниринг.
                                                              0
                                                              Так ведь суть проектирования в том чтобы при появлении новых / изменении требований менять как можно меньше кода, для этого ведь нужны всякие DI, OCP, ISP.
                                                              Я не очень понимаю — вы пытаетесь сказать что всегда можно спроектировать так чтобы потом не было проблем с расширением? Или с чем именно вы спорите?
                                              0
                                              > есть предположение что наше решение решит чью-то проблему.

                                              Быстро сделав прототип «тяп-ляп», мы получаем:
                                              — возможность рекламировать что-то относительно реальное, а не «вот через 10 лет будет вау»
                                              — Инвесторы гораздо легче одобрят что-то прототипное прямо сейчас, чем графики-картинки и сказки как будет круто
                                              — можно набирать пользователей, получать реальную обратную связь, действительно полезные замечания внедрять сразу
                                              — В конце концов, это даст возможность оценивать реальную нужность идеи.

                                              Потом, когда будет первая версия, есть дизайн, некий костяк пользователей, понятно что на самом деле нужно а что шелуха, тогда нужно будет заново провести оценку решения, если надо — сменить язык, и написать нормально. Но пока нет «нормально» — придётся поддерживать прототип.
                                          +1
                                          Один мой знакомый в давние времена сказал такую умную вещь: объектное программирование должно быть в голове, а не в языке.
                                          Можно ли мыслить не на языке, тем более измысливать программы и структуры данных? Просто обычно мыслят на языках программирования более высокого уровня, чем пишут код.
                                            0
                                            Мыслить можно. Но оперативное пространство мозга слишком мало, приходится записывать все идеи на внешний носитель и в форме удобной для обработки по кускам…
                                            –1

                                            Много используете программ, написанных Дейкстрой? Я — ни одной.

                                              +24
                                              почти как сказать «много ли вы используете компьютеров, сделанных Тьюрингом?»
                                                +7

                                                Это примерно как если бы Тьюринг давал советы по пайке и разводке инженерам, делавшим ENIAC.

                                                  +8

                                                  Учитывая, что Тьюринг занимался проектированием компьютера ACE, возможно, он смог бы что-то дельное посоветовать и разработчикам ENIAC.

                                                0

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


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

                                              +2
                                              те языки и подходы, которые в итоге оказывались самыми практичными и популярными

                                              А, например, COBOL вы в ту же категорию относите?
                                                +1

                                                На COBOL крутится очень много бизнес-логики, на нём до сих пор пишут ПО. Раз его используют спецы в этой области — значит для своих задач он хорош. Мнение человека вроде Дейкстры, не имеющего опыта в энтерпрайзе, годится лишь для холиваров. Для меня вообще удивительно, что он допускал такие резкие высказывания — видимо в академической среде какая-то своя атмосфера: не шарящим студентам, лижущим тебе задницу ради оценки, всегда можно навешать на уши х*ету.

                                                  +13
                                                  Раз его используют спецы в этой области — значит для своих задач он хорош.

                                                  Нет, не значит. Скорее это значит что так 'исторически сложилось'

                                                    0

                                                    Во всяком случае это решать спецам, а не холиварщикам со стороны.

                                                      +2
                                                      Насчёт «исторически» возможно отчасти и так, я Кобол не знаю, но я знаю Фортран, ещё более древний язык. По большому счёту, это первый высокоуровневый язык программирования вообще. И я знаю, что в науке и технике он до сих пор широко применяется. Просто потому, что он на самом деле самый удобный и быстрый язык для численных расчётов. Причём даже в новых проектах с нуля, без наследия 60-х годов. И сейчас нет проблемы конвертировать Фортран в другие языки. Первые трансляторы, например на Си, появились как минимум 30 лет назад.
                                                        +2
                                                        Просто потому, что он на самом деле самый удобный и быстрый язык для численных расчётов.

                                                        Как там с аналогом плюсовых expression templates?


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

                                                          0
                                                          Последние исследования по expression templates, которые видел, утверждают что они уступают вручную оптимизированному коду. Года 4-5 назад, но уже не помню подробностей.
                                                          Мне кажется, что ET все-таки скорее средство «быстрой разработки» численных расчетов, дающий вполне достойную, но не пиковую производительность. Может быть, требования к срокам и стоимости разработки стали жестче и теперь нельзя шлифовать код до идеала?
                                                            0

                                                            Там же не зря ещё «удобный» упоминается. А так-то понятно, что любой результат, полученный с использованием хоть плюсов, хоть фортрана, можно написать на ассемблере.

                                                            +1
                                                            Аналогов в самом языке ещё нет. Кое-что делается оптимизирующим компилятором, также есть внешние инструменты типа Parametric Fortran и Fypp.
                                                            Я не зря написал «удобный и быстрый». Expression templates в C++ это просто кошмар какой то. Чтобы их использовать в реальных задачах нужен настоящий эксперт в С++, который потратил годы на обучение и изучение всех тонкостей языка. Это реально эзотерическое программирование. А отладка? Сообщения об ошибках в шаблонах способны заставить рыдать даже закалённого бородатого кодера. Нет, это не подходит для программирования научного кода, который обычно пишется учёными, а не профессиональными программистами. Конечно, можно нанять и их. Например у нас в организации на каждый десяток physical scientists есть один или пара computer scientists. Но оказалось, что их усилия гораздо эффективнее направить на другие методы оптимизации, например переписать под многопоточность или векторные операции, ручную оптимизацию кода наконец.
                                                              0
                                                              Expression templates в C++ это просто кошмар

                                                              А это вообще в реальности кто-то использует? В чем проблема использовать внешний кодогенератор?

                                                                +1

                                                                Я использую.


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


                                                                auto GetRecentRSSNews(FeedID feedId)
                                                                {
                                                                    return m_myOrm->Select(field<Feed::id> == feedId &&
                                                                            field<Channel::feedId> == field<Feed::Id> &&
                                                                            field<Item::channelId> == field<Channel::id> &&
                                                                            field<Item::date> >= yesterday());
                                                                }

                                                                без того, чтобы туда как-то ещё кодогенерацию вкорячивать.


                                                                А как-то построить дерево выражения, протайпчекать его и, возможно, соптимизировать позволяют именно expression templates.

                                                                  0

                                                                  А есть какие-то фундаментальные причины, по которым в язык не могут прикрутить нормальные макросы, с которыми это все было бы ez? Как я понимаю, востребованность есть, в чем затык? Просто ретроградство тех, кто пишет стандарт, или что-то более серьезное?

                                                                    +1

                                                                    Это сложно сделать правильно сразу, а у тех, кто пишет стандарт, есть большое желание делать правильно сразу.


                                                                    Впрочем, метаклассы отчасти помогают, компилтайм-рефлексия поможет, на CppNow вот какой-то чувак аналог гигиенических макросов предлагал.

                                                                  0
                                                                  Внешний кодогенератор, конечно же, намного лучше, но только если он уже есть. Скажем, мы используем кодогенератор, который из химического механизма, написанного в человеческом виде, делает очень быстрый код решения дифференциальных уравнений. Это очень хороший кодогенератор, но он создавался, расширялся и оптимизировался годами, причём разными группами.
                                                                  +1

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


                                                                  Ну и да, я не считаю себя топовым спецом по C++, но в expression templates нет ничего сложного. И, спасибо clang, сообщения об ошибках уже давно весьма хороши.

                                                                    +1
                                                                    И, спасибо clang, сообщения об ошибках уже давно весьма хороши.
                                                                    Они, кстати, вполне неплохи и в последних версиях gcc… но это потому что их clang заставил…
                                                                      0

                                                                      Я ченджлог gcc 9 читал не так давно и поймал себя на том, что там как-то прям даже вкусно сделали.


                                                                      Да, спасибо clang'у за то, что возродил конкуренцию среди компиляторов.

                                                                      0
                                                                      Да, я смотрел эти библиотеки, а именно Eigen и Blaze. Увы, они не быстрее давно известных библиотек, написанных на обычном Фортране типа Intel MKL.
                                                                  –8
                                                                  Фортран дожил до наших дней только потому, что на нем на заре программирования было написано много расчетных программ, и никто сейчас не хочет их заново переписывать. По современным понятиям Фортран — такое же уродство, как и JavaScript. Но не надо в него кидать камни, он был первым языком высокого уровня. А вот зачем сейчас плодят уродов? Но это риторический вопрос.
                                                                    +2
                                                                    Всегда поражаюсь людям, стремящимся обосрать js на основе одного лишь предвзятого отношения к языку, который да, не без странностей, но при этом позволяет использовать любую парадигму программирования, а в современных реалиях показывает буквально торжество принципов функционального программирования в противовес тяжелому ООП подходу. Самый яркий пример — React: До 15 версии всё плясало вокруг классов, затем народ, прям удивительно, но всё больше и больше начал отдавать предпочтение функциональным pure компонентам и в итоге в 16 реакте мы наблюдаем феерический разворот от классов к функциональному стилю )
                                                                      +3
                                                                      в 16 реакте мы наблюдаем феерический разворот от классов к функциональному стилю )
                                                                      Вы хотели сказать «к процедурному»? Тот феерический ужас, который они реализовали с useState не имеет ничего общего с фп, а просто какая-то хрень от современных ооп-хейтеров, чтобы не писать гадкое слово class
                                                                        +2
                                                                        Вы хотели сказать «к процедурному»? Тот феерический ужас, который они реализовали с useState не имеет ничего общего с фп, а просто какая-то хрень от современных ооп-хейтеров, чтобы не писать гадкое слово class

                                                                        Самое смешно в данной ситуации то, что useState — это, по факту, бедная реализация методов классов на замыканиях из SICP :)
                                                                        То есть, вместо того, чтобы использовать нативные классы, ребята просто сделали свою параллельную костыльную ООП-подсистему.

                                                                          0
                                                                          Вы хотели сказать «к процедурному»?

                                                                          на заре эпохи, в начале 90-х, мы функции от процедур отличали только тем, что функции возвращают что то, а процедуры нет )) Правда я тогда и сам был ещё не волшебником, я только учился )
                                                                            +4

                                                                            Так вот сложилось, что функция от процедуры и правда не сильно отличается. А вот функциональное программирование и процедурное — два разных мира.

                                                                              –1
                                                                              Ну, сейчас то да и я с TheShock не спорю, он прав, чистый React действительно больше процедурный подход + декларативный (jsx + например sass типа потому что) но в общем смысле если это же js и раз такой подрубаешь к нему redux + redux-observable и у тебя rxjs в купе с редьюсерами в корне меняют картинку, дабавляя море функционального кода ) а потом такой раз, решил абстракций каких то с данными поналепить, особенно там при работе с canvas, а то и вообще что то вроде three.js заюзать и снова здрасьте OOP ) и как то уже эту дикую смесь парадигм язык не поворачивается назвать процедурным стилем ) А самое прикольное, что всё такое при этом модульное, организованное, под командную работу заточено, с линтами там, с пайплайнами под CI/CD контроль версий, с мерджреквестами через кодревью и на удивление ниче друг другу в коде не мешает, всё тестируемо, и рефакторить вообще песня :)
                                                                              А вообще, вся эта холиварщина, а давайте вот теперь будем только такой стиль юзать, а такой перестанем, больше похожа на какую то бредогенерацию принципиальных теоретиков, потому что программисты практики должны уметь в любой парадигме работать и с другой стороны, в любой парадигме полно и говнокода и шедевров. В современных реалиях это часто вопрос грамотного подбора правильных инструментов, от которых требуется что бы они поставленную задачу выполняли. Мне например приятно юзать и ООП и функциональный стиль и императивный код, если они написаны людьми, которые реально умеют их готовить и используя эти инструменты, я буду учиться у гениев, следуя их рекомендациям по работе с этими инструментами, не зависимо от предпочитаемого ими подхода — мне всё интересно :)
                                                                          +1
                                                                          но при этом позволяет использовать любую парадигму программирования

                                                                          Как там с type-driven development в стиле Idris, например?

                                                                            0
                                                                            Не трогайте их. А то они сейчас компилятор Idris в js напишут и скажут, что его возможности — это возможности js.

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

                                                                              Поздняк.

                                                                    +3
                                                                    Как уже написали, аргумент «раз на нем пишут, значит он хорош» очень спорный. Дейкстра может быть прав или нет по поводу COBOL, ваше право с ним не соглашаться, но для критики языка программирования не обязательно иметь какой-то особый «опыт в энтерпрайзе». Скорее, теоретические знания и опыт разработки других языков программирования более релевантны. И, критика, вообще, вещь полезная для индустрии.
                                                                      –4

                                                                      В энтерпрайзе одни подходы, в академии — другие. А ещё вспоминается поговорка про плохого танцора.

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

                                                                          На коболе просто написанно много плохого кода, который переписывать очень страшно и чревато большими простоями и рисками. Одновременно с этим на этом не лучшем языке люди не хотят писать, поэтому их заманивают большими деньгами. Ну примерно как кроссовер платит 50 баксов в час за проекты в стиле Delphi + .Net 1.1. Знаю из первых рук.


                                                                          Вот так и складывается "стоимость специалистов необходимого уровня".

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

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

                                                                                0
                                                                                Я с этим и не спорю. Я только говорил что для действительно адекватной и предметной критики языка для энтерпрайза нужно все-таки понимать реалии энтерпрайза. Чисто академические знания здесь не подходят.
                                                                            0
                                                                            Много занимался корпоративным ПО на Java и все никак не могу понять о каком таком особом энтерпрайзе идет речь. Зато видел тонны плохо кода, подходов и инструментов, которые можно смело критиковать после одного взгляда ни них. К слову, иногда неадекватность какого-то решения легче заметить человеку «со стороны», чем уже привыкшему к нему. ИМХО, энтерпройзу нужен универсальный язык программирования и адеквантные инструменты, по большей части тоже довольно универсальные. То есть, определенные отличия в мире корпоративной разработки, конечно, есть — вспоминается статья Джоэла Спольски «Пять миров» — но все это не существенно для написанного выше. Если я не прав, то тогда что имеется ввиду под словом энтерпрайз и какие там особые задачи, которые не подчиняются общим принципам и для них нужен особый язык?
                                                                              0
                                                                              Много занимался корпоративным ПО на Java и все никак не могу понять о каком таком особом энтерпрайзе идет речь. Зато видел тонны плохо кода, подходов и инструментов, которые можно смело критиковать после одного взгляда ни них.
                                                                              Суть в том, что бизнес не очень волнует качество кода само по себе. Его волнует стоимость получения результата и, иногда, стоимость последующей поддержки и развития. И если нужен сайт визитка, который будет таким и оставаться, а при необходимости чего-то более крутого просто перепишется, то совершенно неважно какой там отстойный код напишет нанятый джун. И нанятый джун на «плохом» JS, например, будет гораздо дешевле чем нанятый джун с плюсами. Хотя бы потому что первый получит результат куда быстрее. При этом его код может быть максимально отвратителен — но кого это волнует? То есть приоритеты другие, академичность и правильность by the book могут легко быть неприменимы в бизнесе. Это не значит что обязательно будут, просто нужно понимать когда и почему они все-таки применимы. А это очень сложно сделать без опыта работы на собственно бизнес.
                                                                                +1

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

                                                                                  +1
                                                                                  Это нюансы уже. Я всего лишь пытался показать как энтерпрайз может не беспокоиться о качестве кода, я не пытаюсь сказать что так происходит всегда. Суть моего комментария в том, что у бизнеса есть другие параметры кроме красивости кода. И из-за этого лучшим может оказаться дурно пахнущий код про который любой специалист скажет что так писать нельзя.
                                                                                    0

                                                                                    Это да. Всегда когда речь идёт о красивости и идиоматичности кода вспоминаю про WordPress :)

                                                                                  +1
                                                                                  бизнес не очень волнует качество кода само по себе. Его волнует стоимость получения результата и, иногда, стоимость последующей поддержки и развития.
                                                                                  Согласен.
                                                                                  То есть приоритеты другие, академичность и правильность by the book могут легко быть неприменимы в бизнесе.
                                                                                  В некотором смысле да, но в то же время, в бизнесе используются инструменты и подходы рожденные в академической среде. То есть, если кто-то для простой разовой задачи начнет использовать некий академический подход требующий избыточного количества времени, то это конечно ошибка. Но вроде бы подобной массовой проблемы и нет, когда академики ломают бизнес. Зато, например, тот же джун может с пользой для себя и своей продуктивности потратить время на изучение какой-то «академической» литературы.
                                                                                    0
                                                                                    В некотором смысле да, но в то же время, в бизнесе используются инструменты и подходы рожденные в академической среде. То есть, если кто-то для простой разовой задачи начнет использовать некий академический подход требующий избыточного количества времени, то это конечно ошибка.
                                                                                    Вот мой комментарий именно о том, что вот этот вот подход, на мой взгляд, и подразумевается когда говорится про отличие энтерпрайза от академических рассуждений и решений. При этом задача необязательно разовая или простая (хотя вероятнее всего именно так, но бывают разные ситуации все же). Просто иногда могут случаться всякие обстоятельства когда академический подход не сработает из-за недостатка ресурсов — времени и всего из него вытекающего (наывыка, количества рук) или денег. Например если в компании кризис и нужно срочно что-то выкатывать максимально быстро или закрываться. В таком случае выкатить что-то что внутри будет выглядеть отвратительно и будет очень тяжело поддерживать и расширять, но вот прямо сегодня, а не через месяц — вполне может оказаться лучше.
                                                                                      0
                                                                                      Теорию пишут практики. Если применение «академического подхода» приводит к неудачным результатам, скорее всего он был применен неправильно, и скорее всего из-за плохого понимания подхода тем, кто решил его использовать, например кто-то в очередной раз решил что нашел серебрянную пулю, и решил срочно внести в проект какой-то подход даже не проанализировав, какие проблемы он решает, и существуют ли они в проекте на текущий момент.
                                                                        +7
                                                                        Ну, его крестовый поход против goto увенчался успехом…

                                                                        А с учётом того, что он внёс значительный вклад в разработку Алгола, который является предком подавляющего большинства современных ЯП…
                                                                          +1

                                                                          Самое смешное, что goto так никуда и не делся, поскольку выходить из вложенного цикла без него ещё не научились.

                                                                            +2
                                                                            Можно выйти из вложенного цикла на любой уровень и без goto.
                                                                            Для этого перед break нужно присвоить переменную указывающую куда нужно выйти, а во внешних циклах ловить значение этой переменной, и делать break в зависимости от её значения.
                                                                              +9
                                                                              А еще можно сравнить итоговый код в машинных командах и офигеть, насколько короче и быстрее тот некошерный goto, чем Ъ и обобренный брейк… )))
                                                                              А потом посчитать, насколько уродливее и тяжелее та кажущаяся «красота» на уровне human-readable абстракций…
                                                                              )))
                                                                                +4
                                                                                А еще можно сравнить итоговый код в машинных командах и офигеть, насколько короче и быстрее тот некошерный goto, чем Ъ и обобренный брейк… )))

                                                                                Борьба с goto велась всегда с оговоркой «не используйте его без надобности». Выход из вложенных циклов — это один из немногих осмысленных кейсов goto.
                                                                                  +3

                                                                                  Не всегда. Видел я кандидата наук, которая считала break разновидностью goto и снижала за него баллы на ЕГЭ...


                                                                                  Да и тут на Хабре похожие кадры попадаются.

                                                                                    0
                                                                                    Видел я кандидата наук, которая считала break разновидностью goto и снижала за него баллы на ЕГЭ...

                                                                                    Это — клиника и не лечится. Я тоже таких к.т.н. видел.
                                                                                    Препод зачем-то вела уравнения мат. физики. При этом ни хрена в этом не соображала. Было забавно, когда студенты исправляли косяки в ее лекциях, потому что она не втыкала где у нее ошибка.
                                                                                      0
                                                                                      Это — клиника и не лечится.

                                                                                      Может, какие светила медицины попробуют? Готов стать подопытным.

                                                                                      Чем break не разновидность goto?
                                                                                        +3
                                                                                        Думаю, фундаментом для этого вывода стало «снижала за него баллы на ЕГЭ».
                                                                                          0
                                                                                          Тем, что не continue? ;)
                                                                                            0
                                                                                            Чем break не разновидность goto?

                                                                                            Тем, что бездумное использование goto — резко снижает читаемость кода. Использование break — зачастую необходимость.
                                                                                            Но исходно речь шла про то, что занижать оценки за использование break — глупость. Хотя остается вариант, что это интерпретация студента, и оценка была занижена за что-то осмысленное, а не за break.
                                                                                              0

                                                                                              Оценка была занижена потому что использование break нарушает теорему Дейкстры. Это не интерпретация, это точная цитата с апелляции.

                                                                                                –1
                                                                                                Оценка была занижена потому что использование break нарушает теорему Дейкстры. Это не интерпретация, это точная цитата с апелляции.

                                                                                                Ну так вы текст программы приведите — посмотрим. Судя по всему, break как таковой ни при чем.
                                                                                                  0

                                                                                                  Там был обычный цикл с выходом по-середине:


                                                                                                  repeat
                                                                                                      {foo}
                                                                                                      if {some_condition} then break;
                                                                                                      {bar}
                                                                                                  until false; 

                                                                                                  Написать его по-другому без дублирования кода невозможно (а за дублирование кода тоже штрафуют).

                                                                                                    0

                                                                                                    Чтобы не быть голословным пример из моего солидити кода


                                                                                                    for (uint64 i = uint64(dates.length - 1); ; i--) {
                                                                                                        if ((!latestStatusIndex.hasValue || dates[i] > dates[latestStatusIndex.value]) && isDistributionStatus(statusCodes[i])) {
                                                                                                            latestStatusIndex = Types.OptionU64(true, i);
                                                                                                        }
                                                                                                        if (i == 0) {
                                                                                                            break;
                                                                                                        }
                                                                                                    }

                                                                                                    переменная i — unsigned, поэтому проверять на i < 0 в условии цикла нельзя.

                                                                                                      0
                                                                                                      Можно так:
                                                                                                      uint64 i = uint64(dates.length);
                                                                                                      do
                                                                                                      {
                                                                                                          --i;
                                                                                                          if ((!latestStatusIndex.hasValue || dates[i] > dates[latestStatusIndex.value]) && isDistributionStatus(statusCodes[i])) {
                                                                                                              latestStatusIndex = Types.OptionU64(true, i);
                                                                                                          }
                                                                                                      }
                                                                                                      while (i > 0);
                                                                                                      

                                                                                                      Если что, я не против break (и не против goto, честно говоря).
                                                                                                        0

                                                                                                        Во-первых в солидити (как и многих других языках) нет do циклов.
                                                                                                        Во-вторых этот код сломается если dates пустой массив.

                                                                                                          +2
                                                                                                          Ваш вариант вроде тоже ломается, разве нет?
                                                                                                            0

                                                                                                            Вот так мы и нашли баг :)


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


                                                                                                            Правда, про do момент остается.

                                                                                                              0
                                                                                                              Про do — OK, для меня просто слово «солидити» ничего не означало тогда — принял его за название проекта, а код за плюсовый. Так то согласен, без цикла с пост-уловием — или дублирование, или break.
                                                                                                      0
                                                                                                      Я что-то не догоняю, паскаль не помню, наверное. until false — это do {...} while(1); или do {...} while(0);?
                                                                                                        0

                                                                                                        until — это противоположность while. Так что until false — это while(1).

                                                                                                          +2
                                                                                                          Ну, если заданием было написать код, иллюстрирующий теорему Дейкстры, то отметка снижена заслуженно и, я бы сказал, недостаточно.
                                                                                                            0

                                                                                                            Заданием на ЕГЭ в части С всегда является написание работающего кода, без перерасхода памяти, времени и строчек программы.

                                                                                                              0
                                                                                                              А борьба с «перерасходом» строчек программы не может ли вести к перерасходу памяти и замедлению программы? Подсказка: цена абстракций)))
                                                                                                                0

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


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


                                                                                                                А на самом деле на апелляции сидит "кандидат наук", сравнивающая текст программы посимвольно.

                                                                                                                  0
                                                                                                                  Понял Вас, ЕГЭ оно такое ЕГЭ… Что тут скажешь, сочувствую…
                                                                                                        –1
                                                                                                        Вы так и не привели текст программы.
                                                                                                        Вот это:
                                                                                                        использование break нарушает теорему Дейкстры.

                                                                                                        я могу трактовать как «преждевременный выход из цикла нарушает теорему Дейкстры». Т.е. претензия не к break'у, а к алгоритму. Чтобы это проверить — нужен текст программы, а вы его не привели.
                                                                                                          +1

                                                                                                          Вы издеваетесь или как? Как я вам вспомню какую задачу я решал на экзамене 12 лет назад и какой код при этом написал?


                                                                                                          И ладно бы это был самый сложный экзамен всей моей жизни, так ведь нет, это был очередной экзамен на внимательность при заполнении бланка...


                                                                                                          я могу трактовать как «преждевременный выход из цикла нарушает теорему Дейкстры». Т.е. претензия не к break'у, а к алгоритму.

                                                                                                          Во-первых, теорема Дейкстры на самом деле называется теоремой Бёма — Якопини.


                                                                                                          Во-вторых, эта теорема говорит лишь о возможности приведения программы к некоторому виду, но никак не запрещает иной вид программы. Теорему невозможно "нарушить".


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

                                                                                                            –1
                                                                                                            Вы издеваетесь или как? Как я вам вспомню какую задачу я решал на экзамене 12 лет назад и какой код при этом написал?

                                                                                                            Почему издеваюсь?
                                                                                                            1) Да, тупые преподы бывают.
                                                                                                            2) Да, бывают студенты, которые считают, что их незаслуженно обидели.
                                                                                                            3) При этом бывает, что обидели студента заслуженно.
                                                                                                            4) Как я могу определить, что имело место быть на самом деле без текста программы?
                                                                                                            5) Поскольку название алгоритма непонятное, непонятно и к чему придрался препод.
                                                                                                            6) break используется повсеместно.
                                                                                                            7) Наезда на языковую конструкцию в вашей цитате я не увидел.
                                                                                                            8) Иногда преждевременный выход из цикла покрывает не все кейсы алгоритма и поэтому некорректен.
                                                                                                              +1
                                                                                                              Как я могу определить, что имело место быть на самом деле без текста программы?

                                                                                                              А слов разработчика с 8-летним стажем олимпиад и 10-летним стажем разработки вам недостаточно? Почему вы вообще взялись проводить какое-то расследование в комментариях на Хабре?


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

                                                                                                              А где вы вообще увидели название алгоритма?


                                                                                                              Наезда на языковую конструкцию в вашей цитате я не увидел.

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


                                                                                                              Иногда преждевременный выход из цикла покрывает не все кейсы алгоритма и поэтому некорректен.

                                                                                                              В таком случае мне бы сказали "алгоритм некорректно работает в таком-то случае", а не то что я цитировал выше.

                                                                                                                –1
                                                                                                                А слов разработчика с 8-летним стажем олимпиад и 10-летним стажем разработки вам недостаточно?

                                                                                                                Конечно, нет. Во первых, ошибаться / преднамеренно вводить в заблуждение может кто угодно. Во вторых, у вас на лице ваш стаж / квалификация не написаны. В третьих, на просьбу показать код последовало гениальное «begin… end», что в середине — не помню.
                                                                                                                В четвертых, мне непонятно, чего вас колбасить начинает. Я высказал свое мнение. Не устраивает — пройдите дальше. Чего кипятиться-то?

                                                                                                                Почему вы вообще взялись проводить какое-то расследование в комментариях на Хабре?

                                                                                                                С того, что после моей фразы (безобидной вполне):
                                                                                                                Хотя остается вариант, что это интерпретация студента, и оценка была занижена за что-то осмысленное, а не за break.

                                                                                                                последовала какая-то бурная деятельность с вашей стороны.

                                                                                                                А где вы вообще увидели название алгоритма?

                                                                                                                «теорема Дейкстры». До букв докапываться не будем, ок? :)

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

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

                                                                                                                В таком случае мне бы сказали «алгоритм некорректно работает в таком-то случае», а не то что я цитировал выше.

                                                                                                                Ну это ВАШЕ понимание, что нужно говорить. У других людей оно может несколько отличаться. И еще раз повторю: да, я видел тупых преподов. Море. Равно как видел нормальных преподов и тупых студентов, которые считают препода тупым.
                                                                                                                  0
                                                                                                                  «теорема Дейкстры». До букв докапываться не будем, ок? :)

                                                                                                                  Не ок. Четвертый раз вам говорю: это не название алгоритма!

                                                                                                            +2

                                                                                                            Типичный пример полезного брейка:


                                                                                                            let user_input: u32 = loop {
                                                                                                               if let Ok(user_input) = read_line().parse() {
                                                                                                                  break user_input;
                                                                                                               }
                                                                                                               println!("Неверный ввод: ожидалось беззнаковое число");
                                                                                                            }
                                                                                                              0
                                                                                                              Даже Дейкстра без break/return/goto не смог бы покинуть вечный цикл)
                                                                                                                –1

                                                                                                                Эксепшены забыли. :) Ну и всякие штуки вроде setjmp, отправка сигнала самому себе, прерывания и т.д.

                                                                                                                  0
                                                                                                                  Ну да :)
                                                                                                                    –1

                                                                                                                    А еще можно у компьютера шнур питания выдернуть!

                                                                                                                    0

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

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

                                                                                                                      Вечный цикл покинуть нельзя. Если используется break это значит цикл не вечный, но условие выхода находится где-то унутре

                                                                                                            0
                                                                                                            Бездумное использование break снижает читаемость, goto (jmp) — зачастую необходимость. Но это никак не говорит о том, является ли что-то из этого разновидностью другого.

                                                                                                            Goto — безусловный переход.
                                                                                                            Break — безусловный переход к любому оператору после определённого цикла.
                                                                                                              0
                                                                                                              Бездумное использование break снижает читаемость

                                                                                                              Бездумное программирование снижает читаемость.

                                                                                                              goto (jmp) — зачастую необходимость.

                                                                                                              Примеры, конечно можно привести. Но, «зачастую»… В своей практике, вообще ни разу не применял goto. Кейсов таких не возникало. А вот break — постоянно.

                                                                                                              Break — безусловный переход к любому оператору после определённого цикла.

                                                                                                              Что значит к любому? К следующему оператору за циклом. Что обычно и требуется.
                                                                                                                –1
                                                                                                                Бездумное программирование снижает читаемость.

                                                                                                                Именно!

                                                                                                                Опять же, в своей практике я и в break не нуждался.

                                                                                                                Что значит к любому? К следующему оператору за циклом.

                                                                                                                Ну… К любому, всякому, какой бы ни оказался за этим циклом.

                                                                                                                Таки безусловный переход.
                                                                                                    0
                                                                                                    А еще можно сравнить итоговый код в машинных командах и офигеть, насколько короче и быстрее тот некошерный goto, чем Ъ и обобренный брейк… )))
                                                                                                    Даже более. В машинных командах в любом случае будет аналог JMP операнда, который тот же Goto.

                                                                                                    По сути, дело в абстракциях и удобстве.
                                                                                                      0
                                                                                                      Нет, дело не в удобстве. Дело в последствиях непредвиденного выхода. Очень сложно контролировать все точки выхода из процедуры или какого-то участка кода и на одном из них забыть освободить память или закрыть файл. А так-то вещь весьма удобная — вжик и вышел. А тут оказывается что надо не просто выйти а ещё и ресурсы освободить, файлы закрыть и т.д. Хорошо когда это делается в одном месте, и даже если туда переходить по goto но тогда сам оператор перехода становится ненужным — достаточно уже существующих конструкций.
                                                                                                      Break — он не просто вызывает выход из цикла, попутно под капотом он может ещё и переменную/коллекцию освобождать.
                                                                                                        0
                                                                                                        А так-то вещь весьма удобная — вжик и вышел. А тут оказывается что надо не просто выйти а ещё и ресурсы освободить, файлы закрыть и т.д.

                                                                                                        RAII?


                                                                                                        Break — он не просто вызывает выход из цикла, попутно под капотом он может ещё и переменную/коллекцию освобождать.

                                                                                                        Как он это сделает и почему в той же ситуации goto этого сделать не сможет?

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

                                                                                                            Странное какое-то определение, учитывая что компилятор C++ таки вставляет вызовы деструкторов перед goto...

                                                                                                              –1
                                                                                                              Ага, прикрутили костыль. Очередной.
                                                                                                  +3
                                                                                                  Без него и освобождение ресурсов в C затруднительно))
                                                                                                    +4

                                                                                                    Да и эксепшены по-сути эмулируют goto.

                                                                                                      +1
                                                                                                      Не совсем. Исключения еще дают гарантии выполнения деструкторов, там где релевантно.
                                                                                                  +2
                                                                                                  PHP умеет, просто после него ставится число, из скольких циклов выходить. А все его ругают.
                                                                                                    +8

                                                                                                    Да запросто:


                                                                                                    for(...) {
                                                                                                       for(...) {
                                                                                                          if (condition) return;
                                                                                                       }
                                                                                                    }

                                                                                                    Да-да, цикломатическая сложность >= 2 — повод выделить этот код в отдельную функцию

                                                                                                      –3

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

                                                                                                        +12

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

                                                                                                          0
                                                                                                          Еще и Duff's device есть)
                                                                                                        0
                                                                                                        break и continue поддерживают параметры
                                                                                                        В вашем примере достаточно написать break 2;
                                                                                                        Редко нужно, но порой выручает. Бывает цикл+switch, тоже можно делать break 2;
                                                                                                          0

                                                                                                          1) Не во всех языках, 2) отдельная функция всё равно чище, 3) если вы скопипастите кусок с break 2 и он попадёт в цикл другой глубины, то будет ошибка.


                                                                                                          Так что лучше не делать так.

                                                                                                            +2

                                                                                                            С тем же успехом можно случайно скопипастить кусок с return по-середине...

                                                                                                        +2
                                                                                                        Я бы в таком случае засунул вложенный цикл в функцию и вместо goto использовал return
                                                                                                      +6
                                                                                                      Если язык популярный, это не всегда значит, что он — практичный, то есть оптимальный для решения практических задач. Как по мне так Дейкстра видел перспективу на десятилетия вперёд, а любители «практического программирования» иногда не видят и на десятилетия назад)
                                                                                                        –4

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


                                                                                                        Методики и подходы написания надёжных программ были выработаны ещё в 80х при создании софта для SpaceShuttle и к данному моменту стандартизованы. И ключ совсем не в выборе самого лучшего языка программирования, а в организации процесса.

                                                                                                          +1
                                                                                                          Я написал коммент про языки программирования. И про то, что оценивать уровень Дейкстры не каждому из нас под силу. Скажите, пожалуйста, при чём тут красивый и некрасивый код, шаттлы и надёжность?) У меня просто жестокий разрыв контекста сейчас.
                                                                                                            0

                                                                                                            Основная идея в том, что если Дейкстра или кто-либо другой профессионально не писал программы для энтерпрайза и сложных систем, то не ему критиковать подходы, практикуемые там. Вроде бы очевидно, нет? Дальновидность его в области промышленного ПО можно оценить по тому, что он критиковал как раз те подходы, которые до сих пор является широко используемыми (хоть и критикуемыми), и, думаю, здесь дело не в повальной умственной отсталости тех, кто их использует. Проблема же написания качественного софта, которую Дейкстра пытался решать критикой (уровня обычного обсирания) отдельных технических подходов и языков, лежит не в плоскости языка, а в плоскости организационных подходов и методик — например таких, какие были выработаны при разработке ПО для Space Shuttle, а надёжное ПО, используемое десятки лет, можно писать хоть на ассемблере — например тот же MVS.

                                                                                                              +4
                                                                                                              Википедия про Дейкстру:
                                                                                                              В 2002 году получил ежегодную премию, вручаемую Симпозиумом по принципам распределённых вычислений (англ. Symposium on Principles of Distributed Computing) Ассоциации вычислительной техники «за публикацию, оказавшую наибольшее влияние на область распределённых вычислений»; в знак признания заслуг учёного с 2003 года эта премия носит название премии Дейкстры.

                                                                                                              Действительно, откуда ему что-то знать?)))
                                                                                                                0


                                                                                                                Какую, говорите, премию он там получил?:)

                                                                                                                  –1
                                                                                                                  Много — не значит хорошо. Ещё есть аргументы?)
                                                                                                                    –1

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

                                                                                                                      0
                                                                                                                      Ооо, вот оно как вы развернули. К сожалению, на этом я вынужден оставить Вас наедине с самим собой. Удачи в измерениях!
                                                                                                                    +2
                                                                                                                    Я абсолютно осгласен с оратором в начале ветки, и повторю его мысль — пополуярность это лишь продукт хорошей маркетинговой компании а не показатель качества продука.