Как стать автором
Обновить

Бьёрн Страуструп: Проблема с программированием

Время на прочтение8 мин
Количество просмотров51K
Всего голосов 46: ↑40 и ↓6+34
Комментарии118

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

Это он сейчас так говорит, чтобы поддержать своё реноме. Но мы-то помним всю правду :)

Очевидно, он это говорит не сейчас. Например, по его фразе о 15 годах и «Геноме человека» видно, что это очень старое интервью, ведь 15 лет назад проект «Геном человека» уже не только был 13 лет как начат, но и практически закончен. Это интервью 2006 года.

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

Вот что было сказано на самом деле:
who am I to second-guess, say, 1984 vintage Bjarne? He may have been less experienced than I, but he was no less smart, probably smarter, and he had a better understanding of the word of 1984 than I have.

НЛО прилетело и опубликовало эту надпись здесь
Почти наверняка там опечатка, и он имел в виду ...of the world of 1984.

Это не похоже на отсылку к роману. Выглядит как опечатка — world. Мол, старый Бьёрн явно лучше понимал мир 84-го года, чем он сейчас.

«Кто я такой, чтобы задним числом критиковать Бьёрна времён 84-го года? Пускай у него было меньше опыта, чем у нынешнего меня. Но он был ничуть не глупее, и, вероятно, даже умнее меня, и лучше меня понимал реалии 84-го года.»

Здесь vintage не имеет значения «винтажный или ламповый». Vintage — это дословно процесс сбора урожая винограда и изготовления вина. 1984 vintage Bjarne означает что-то вроде «Бьерн 1984-го года розлива»
Перевод просто ужасен.

Уши гуглопереводчика торчат отовсюду.
That works, but often that support comes at the cost of specialization.
Это работает, но часто эта поддержка стоит за счет специализации.

А должно быть «поддежка достигается ценой специализации».
Но мы-то помним всю правду :)
Вы пропустили тэг «ирония», или действительно считаете эту шутку за реальное «интервью» Струструпа? ;)
AFAIK, вот реальное интервью.
В те времена на ЛОРе не было тега «ирония», все всегда были предельно серьёзны.
Я не про те времена, а про первый комментарий в обсуждении: некоторые ведь могут и всерьез эту шутку принять.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
SQL гораздо ближе к человеческому языку, чем С++

Попробуйте Ruby, вот где красота.
НЛО прилетело и опубликовало эту надпись здесь
«C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off». Yes, I said something like that (in 1986 or so). What people tend to miss, is that what I said there about C++ is to a varying extent true for all powerful languages. As you protect people from simple dangers, they get themselves into new and less obvious problems. Someone who avoids the simple problems may simply be heading for a not-so-simple one. One problem with very supporting and protective environments is that the hard problems may be discovered too late or be too hard to remedy once discovered. Also, a rare problem is harder to find than a frequent one because you don't suspect it.
Начинаем цитировать Библию? Это было сказано 32 года назад! Вас ничего не смущает?

Идём в Вики SQL first appearance 1974, первый стандарт 1986 как раз 32 года назад. Теперь можно спорить?

О чём спорить-то? «Отстрелить себе ногу» можно и на JS, и на C# — долго ли «умеючи»! Проблема ведь не в тулзах, а в головах. В real life люди работают с очень опасными, сложными и капризными устройствами — и ничего, выжившие становятся высокооплачиваемыми профессионалами.
Ruby чарующе элегантен, но он в другой категории — скриптовых языков.
Вот если когда-нибудь по-настоящему взлетят Crystal и Elixir — вот будет красотища…
а для более сложных лучше подошло бы декларативное описание желаемых целей.
— Давайте построим коммунизм, удвоим ВВП, войдем в пятерку экономически развитых стран

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


А вообще скорее наоборот — фп лучше подходит для простых задач обработки данных, маленьких кирпичиков, которые соединяются императивным раствором

Как, например, LINQ в C#.
НЛО прилетело и опубликовало эту надпись здесь
Это какими, к примеру, монадами?
НЛО прилетело и опубликовало эту надпись здесь
Мне кажется, что основная проблема C++ в том, что Бьярн — очень мягкий и хороший человек и старался никогда никому не говорить «нет»…
НЛО прилетело и опубликовало эту надпись здесь

Гвидо загнал сообщество в проблему 2vs3, поэтому тут тоже не все хорошо.


P.S. Ну или при его попустительстве загнали. Не знаю эту историю полностью.

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

По моим ощущениям это сильно ударило по позициям Python в целом. Пока PHP усиленно работал над производительностью и актуализацией, а Golang надо многопоточностью, Python просто ушел в болото на несколько лет.

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

Ну, например, в этом году я впервые начал новый проект на Python 3. До этого вопросы обратной совместимости по библиотекам всегда останавливали.

какая библиотека мигрировала только в этом году?

Так сказать не получится: проект-то новый, поэтому просто посмотрели и поняли, что все есть. А до этого я работал над OpenStack, а там все исторически на 2.7 c редкими вкраплениями Ruby и Python 3.


Проблема-то ещё и в том, что работает — не трожь. Т.е. резона переписывать, например, объвязку GPDB на 2.7 просто нет пока. И таких проектов море, а следовательно инсталяционная база у Python 3 меньше и качество обратной связи ниже. По крайне мере так было где-то до 3.4-3.5. Сейчас за полгода проекта на 3.6-3.7 ничего не словили критичного.

> работает — не трожь. Т.е. резона переписывать, например, объвязку GPDB на 2.7 просто нет пока

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

Дьявол в деталях. Все же PHP 5.x и PHP 7.x это очень разные языки. Да что там говорить: даже между 5.1 и 5.6 изменили много (наконец грохнули globals, сменили ссылочную логику). Я участвовал в таком переходе как зритель. В целом не сложно, но сумарно с месяц человеко часов это съело: надо же не только изменить (что не много заняло), но протестировать, изменить поставку (а софт почти коробочный), написать документацию и т.д.


На мой взгляд действительно хорошая совместимость только у C, потом C++, потом Java, а все остальное в целом проблемно. Беда в том, что Python 3 не предлагал существенных плюшек по сравнению с Python 2. Вот зачем переходить с PHP 5 на PHP 7 всем было понятно, а Python — нет.

НЛО прилетело и опубликовало эту надпись здесь

Потому что по скорости в вебе его обгоняет только Go lang (компилируемый:-) )
Потому что одна из самых больших комьюнити
Потому что невероятно огромный выбор хороших и не очень хороших пакетов\фреймворков
Потому что огромное количество вакансий (среди веба, только у JS больше)
Потому что 80% веба до сих пор PHP
Потому что язык жив и активно развивается

НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Все же PHP 5.x и PHP 7.x это очень разные языки.

А аргументация будет какая-нибудь? Всё же PHP 5.x от 7.x отличаются так же, как питон 3.4 от 3.5, наличием тайпхинтинга и пачкой других мелочей, и ничего фатального, что перевело бы PHP 7.х в разряд «очень разный язык» нет.

Вся аргументация есть в документации на php.net.

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

Учитывая вышеизложенные тезисы, то вся логика последующего комментария, которая отталкивается от этого замечания лишь плод вашего воображения, либо неудачное стечение обстоятельств. На практике же переход с 5.х на 7.х, если в проекте участвовали компетентные специалисты, не использующие функционал, который устарел лет на *дцать, требует ровно два телодвижения — установка 7.х-fpm и рестарт сервера.
НЛО прилетело и опубликовало эту надпись здесь
Невероятно, задепрекейтили конструкторы из 2000х годов и вместо Warning ошибки начали кидать Deprecated. Как же я могу об этом забыть, ну всё, теперь точно другой язык :D
Ну питон 3 активно развивается как язык, плюшек там много появляется, я питон только почуток смотрю, поэтому много перечислить не готов, однако например type hints вполне крутая штука для больших проектов.
Мы выполняем много маленьких чудес посредством проб и ошибок, чрезмерного использования грубой силы и многих испытаний, но зачастую этого недостаточно.

Оригинал:
We perform many minor miracles through trial and error, excessive use of brute force, and lots and lots of testing, but–so often–it’s not enough.


К сожалению, мой английский далеко не так силён, но мне кажется, что не стоило переводить «brute force» — так здесь имелся в виду метод полного перебора (то есть не чрезмерное использование грубой силы, а использование неэффективных решений «в лоб»).
Кроме того, «and lots and lots of testing» хочется перевести как «и проведения огромного количества тестов».
Поправьте меня, пожалуйста, если я ошибаюсь

Тут именно "метод грубой силы", потому что речь идёт о надёжности программ и сложности их проектирования. Но судя по всему, у автора это получилось случайно, потому что "lots of testing — многих испытаний" — былинный отказ.

А что есть полный перебор (или же, как Вы сказали, «неэффективные решения в лоб»), как не применение грубой силы?
Несомненно, перевод соответствует действительности. Но на практике я встречал варианты «полный перебор» и варваризм — брутфорс. «Грубая сила» даже не припомню.
Я изначально понимал, что всё это сильно субъективно, поэтому мне было интересно мнение сообщества (кроме того mbait сказал, что мой вариант перевода неверен). Считайте, что это отсылка к спору по поводу использования интерсептор(интерцептор)/перехватчик, синглтон/одиночка, прокси/заместитель. Честно говоря, мне сильно претят варваризмы, но первые варианты даже в контексте мною воспринимаются четче, чем вторые.
Дело в том что в данном случае Страуструп говорит о «brute force» не как о полном переборе(это значение у этой фразы не основное), а именно как о грубой силе, то есть брать мощностью железа, а не крутостью алгоритма или эффективностью реализации, а уж алгоритм ли там полного перебора или, например, использование веб-приложений вместо нативных — не важно.

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

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

Я к тому что с++ писался так буд-то вокруг одни гении и специалисты. Возможно когда-то это было так но явно не сейчас

НЛО прилетело и опубликовало эту надпись здесь
так в этом и проблема, что человек должен знать и помнить, что можно, а что нельзя, на си тоже можно писать крутой код если всё знать и ничего не забывать, но человек так не умеет
НЛО прилетело и опубликовало эту надпись здесь
таланты бывают, но на них отрасль не построишь, тем более речь не про крутой и быстрый, а про надёжный, Дональд Кнут и тот попал на бабки за свои баги.
НЛО прилетело и опубликовало эту надпись здесь
ну вот что-то не получается учить, гугл вроде не самых худших разработчиков нанимает, но приходится изобретать всякие огороженные Go чтобы они себе ноги не отстреливали.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
C++ Core Guidelines, в соответствии с концепцией, включает в себя статический анализатор как неотъемлемую часть.
Да статические анализаторы изобрели давно, но чуда что-то не случилось.
НЛО прилетело и опубликовало эту надпись здесь
Конкретно в случае Core C++ Guidelines существующие анализаторы умеют проверять достаточно много, чтобы ваше утверждение «так в этом и проблема, что человек должен знать и помнить, что можно, а что нельзя, на си тоже можно писать крутой код если всё знать и ничего не забывать, но человек так не умеет» было неверным. Большая часть вполне проверяется.
Да, надо признаться себе, что человек это самое ненадёжное звено и не рассчитывать на его идеальную работу при проектировании инструментов вроде языка программирования.
Ну, не совсем так. Защитный чехол и предохранитель можно поставить, после того как отпилишь себе 3-4 ноги, конечно. Зато на собственном опыте осознаешь, для чего они нужны и когда необходимо их снимать, для того чтобы реализовать низкоуровневые вещи.
Ну а как иначе? Если выдумывать какие-то безопасные инструменты, то вы рано или поздно упрётесь в необходимость подвигать биты туда-сюда.
Системного программирования всё меньше и там интересным вариантом, не отягощённым обратной совместимостью, выглядит Rust
Для того чтобы своять свою, допустим, хэш таблицу, вам придется повертеть в руках raw поинтеры.
Rust, конечно не имеет наследия в виде доисторического Си, но для меня этого недостаточно, тем более с++ со временем всё лучше и лучше, вон в версии от 17 года подсыпали сахарку ещё.
Само появление rust'a это следствие периода застоя в комитете с++, я сам когда знакомился с плюсами, был удивлён что вот это и есть то на чём написано всё в мире.
у C++ вроде до сих пор проблемы с зависимостями?

ИМХО. С++ как один из инициаторов ООП 'эры' это беда.
Ещё студентом ощущал что c ооп что-то не так — на нем не удается красиво написать код увязав бизнес логику и ООП парадигму.
Сейчас по прошествии лет работы с разными языками это понимание только укрепилось.
Для котиков и окошек ООП отлично подходит, для бизнес логики где нет четкого наследования и нет необходимости в объектах, т.к. в основном код это данные и функции работы над данными(но не вместе) — не подходит.

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

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


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

НЛО прилетело и опубликовало эту надпись здесь
Если есть класс, ответственность которого — только хранить данные, то логично его избавить от всего, что к этому не относится, получив POD. А класс (или скорее классы, но не важно), который отвечает за действия, с одной стороны, имеет большой риск оказаться -er классом, а с другой, может без особых проблем быть заменен на набор функций.
Вот и получается, что такой подход отличается от процедурного программирования по форме, но не отличается по сути: у нас те же данные, функции, а классы здесь особенно-то и не нужны. Поэтому я и говорю, что он, на мой взгляд, противоречит духу ООП.
PS: Я не великий эксперт, вполне могу ошибаться. Да и не факт, что верно понял ваше предложение.
НЛО прилетело и опубликовало эту надпись здесь
До тех пор, пока нам не нужно их получать в разных видах, валидировать, и т.д.
Как раз здесь я вас неправильно понял. Когда вы писали о «классах, представляющих данные», я думал, вы имеете в виду POD.
Разве это плохо?
Вроде это более или менее известный антипаттерн. www.yegor256.com/2015/03/09/objects-end-with-er.html
Если в языке есть механизм неймспейсов, чтобы не захламлять глобальную область
Полностью согласен, что если в языке нет неймспейсов, то можно использовать классы для их замены. Но у нас же вроде C++.

Насчет Di согласен.
«Данные и методы их обработки» — это определение понятия «класс» в ООП. Определение класса противоречит духу ООП?
Всегда думал, что «данные и методы их обработки» — это определение абстрактных типов данных. А ООП — это инкапсуляция, наследование, полиморфизм. Я ошибаюсь?
ООП — это (согласно рус. Вики):
методология программирования, основанная на представлении программы в виде совокупности объектов, каждый из которых является экземпляром определённого класса, а классы образуют иерархию наследования
Инкапсуляция, наследование, полиморфизм — это принципы ООП, которые, ИМХО, не есть сама суть ООП. А так называемый «дух», ИМХО, присущ не самому ООП, а программисту, который его использует. И если для кого то «дух» ООП — это использование наследования везде, где только можно, я советую обратиться к Саттеру и Александреску — они доходчиво объясняют, когда стоит использовать наследование, а когда рак на горе таки не свистит.
Отсылка к википедии — сильный аргумент, но все-таки не истина в последней инстанции. Что-то Вы меня задели, хочется ответить. Хотя я и не силен в призывании духов, в том числе и «духа ООП», но позволю изложить свой «голос с белтА» (или, если угодно, из программистских окопов).
Суть ООП предельно проста: представление программы, как совокупности «линейно независимых» сущностей, скрывающих свое внутреннее состояние и доступных для взаимодействующих исключительно в соответствии со строго определенными протоколами. Такие сущности и «экспортируемые» ими протоколы в ООП и называются объектами. Как это делается средствами языка — вопрос десятый. В C++ — это класс и совокупность его публичных методов, в JS — это (как пример) сигнатура функции, возвращенной из другой функции и «закложурившей» в качестве «полей класса» экземпляры локальных переменных, в Rust — это (опять же, пример) структура + совокупность ее собственной реализации и реализуемых для нее трейтов, для C это может быть WinProc со switch-ом на десяток экранов. Варианты можно добавлять. Главное — есть инкапсулированное состояние и определение допустимых способов взаимодействия. По сложившейся традиции, если нет иерархии наследования и виртуальных методов, то такой подход называется «абстрактные типы данных», а если добавляется наследование и позднее связывание — то, почему-то, ООП.
Ну, а что касается Александреску и Сеттера, то они замечательные эксперты, но мне ближе Шон Пэрент, особенно его «Inheritance is the root cause of all evil».
Как-то так, что-то тема меня забрала, мог бы еще долго распространятся и аргументировать, но затыкаюсь ибо и так слишком длинно.
Прошу прощения, если обидел лично Вас, мои замечания на счет «духа» ООП относятся к предыдущим комментаторам, которые обвиняли С++ в том, что их личная бизнес логика не совместима с их личным пониманием ООП.
В моем понимании ООП — это то, что написано на Вики, только без последней фразы про иерархию наследования. Просто объединяем данные и методы их обработки в классы — вот и ООП. Если у меня четко одно поведение — не будет полиморфизма, ничего страшного. Если у меня простая структура, содержащая данные, к которым много где нужен прямой доступ — долой инкапсуляцию. А наследование всегда пытаюсь использовать по минимуму, ибо, несмотря на его удобство в правильных ситуациях, в остальных оно всегда вызывает проблемы. Принципы принципами, но пусть все же ООП работает на меня, а не наоборот. Это лишь мое понимание, которое, очевидно, не совсем совпадает с мнением большинства, но пока что как то так.
Единственное же, что я хотел сказать оскорбившим Вас комментарием — это то, что не стоит обвинять ООП в своих проблемах, а С++ — в проблемах ООП, ибо ООП — не единственная парадигма поддерживаемая в С++, а решение проблем — это не задача ООП.
Нет проблем, какие претензии, да меня особо не обидишь:) Мне не нравятся очень распространенные в последнее время «возвышенное» отношение к ООП и расширенная его трактовка. Где-то в 90-х прошлого века это можно было понять, не не в наше время.
Еще раз повторю основную свою мысль: ООП это это метод проектирования и реализации, позволяющий лучше справиться с управлением состоянием программы путем разделения этого состояния на меньшие части и ограничения на способы взаимодействия этих частей. Нет нетривиального и необходимого состояния — ООП не особо нужно. Например, когда программа есть функция, перемалывающая одни данные в другие — много «OOP inside» скорее вредит.
Есть более узкое понимание ООП: инкапсуляция, наследование, полиморфизм. Такое понимание «взлетело», потому что очень упростило программирование оконного интерфейса, вот его и стали всюду пихать, где надо и не надо. А классы тут просто деталь реализации. Сам Страуструп, кстати, про классы писал (цитирую по памяти): "… классы — это модули, но такие, что можно одновременно создавать много экземпляров ...".
Так я именно это и хочу сказать. «Данные и методы их обработки» — это класс. А когда данные отдельно, методы отдельно — это уже фигня какая-то, а не ООП.
Ах да, прошу прощения, неправильно прочитал. Но мне все же не кажется, что это противоречит какому-то духу. Если данные какой то сущности должна особым образом обрабатывать другая сущность, это не повод все мешать в один класс. Другое дело, если это происходит постоянно — тогда стоит задуматься над архитектурой проекта. Если все становится слишком уж сложным — никто не мешает пересесть на процедурщину. Но само ООП ни в чем не виновато.
Мне кажется, Вы путаете синтаксический сахар (ну, и некоторые возможности оптимизации) с логической сутью. Например:
class Cpp {
  int a;
  int b;
public:
 void  f() { ... }
};

эквивалентен:
struct PureC {
  int a;
  int b;
};
void f(struct PureC * this) {...}

Когда-то, во времена CFront, это так и было, я еще помню) Есть концептуальные моменты, например, конструкторы и деструкторы (как средства поддержания инвариантов и в меньшей степени управления жизненным циклом), но основная разница в удобстве программирования, а не в сути. А «дух ООП» пускай носится над бездной, в программировании ему мало места.
Да, дело здесь не в сахаре. Я полностью согласен, что оба варианта кода выше — это ООП. В свое время писал проект на C89 с полноценным ООП, с наследованием, полиморфизмом, всеми делами, это был очень интересный опыт.
Я подумал, что, возможно, ситуация у комментатора выше похожа на ту, что была в одном из моих проектов, где не получалось нормально скрыть поля объектов (для любого чиха приходилось использовать много полей разных объектов), а функции работали с несколькими равноправными объектами и не очень-то собирались в логически связанные группы. И в этом случае, вместо того, чтобы писать
class C1 {
public:
  int a, b;
};
class C2 {
public:
  int a, b;
};
...
class Methods {
  public:
  static C1 f1(C1, C2, C3);
  static C2 f2(C5, C6, C7);
...
};
лучше написать что-то вроде
struct C1 {
  int a, b;
};
struct C2 {
  int a, b;
};
...
C1 f1(C1, C2, C3);
C2 f2(C5, C6, C7);
...
Потому что эти два варианта — оба следуют процедурной парадигме, а не объектно-ориентированной (и именно в этом смысле в этом коде нет «духа ООП»). Первый от второго отличается лишь сахаром.
PS: сейчас я уже как-то не очень уверен, что изначально автор имел в виду именно это, но сначала я понял его именно так.
А можете прояснить свою мысль более развернуто? И предложить парадигму, более подходящую для вашей бизнес-логики?

Я не хотел тут развиваться холивары по этому альтернативы специально не писал. А сделал акцент на недостатках ООП, которые на мой взгляд ставят эту парадигму под сомнения.


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

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


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

Тогда мне так же, непонятно зачем нужен ООП. Если вы игнорируете идею объекта — как вещи в себе.
Какой нибудь JSON или HTTP запрос в своей сути является сочетанием 2-х коллекций ассоциативного массива и списка. Для манипуляции этими двумя типами (ассоциативный массив и список) есть отличные функции в любой стандартной библиотеке, для чего нужна обертка в виде класса?


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

Думаю что в вашем случае представление о FP извращено представителями вида Haskell, языки поддерживающие основные концепции FP не обязательно должны иметь сложную систему типов. Erlang, Clojure простые, но реализуют самые важные, С ПРАКТИЧЕСКОЙ, точки зрения концепции из FP.

НЛО прилетело и опубликовало эту надпись здесь
Встряну чуть чуть.
Тогда мне так же, непонятно зачем нужен ООП. Если вы игнорируете идею объекта — как вещи в себе.

Обычно такие вопросы возникают у тех кто не смирился с мыслью, что объект в ООП не равен объекту реального мира. Это есть абстракция. А все абстракции кастрированы по определению — они реальность показывают далеко не со всех сторон. Об этом прямо говорит Single Responsability Principle — объект отвечает за что то одно и от этого зависит какой он — инкапсулирует что либо или наследуется или просто делает что то. За что должен отвечать класс/объект? — а вот это уже вопрос проектирования. А проектирование архитектуры программного кода как и любое проектирование есть не только инженерия, но и в не малой степени искусство. Поэтому нельзя просто понимать или не понимать ООП, принять его или не принять — это есть подход. Возможны другие подходы, но только те что позволяют проектировать. Иначе с их помощью не построить сложную систему. ФП в целом проектировать позволяет, но при этом свойства ФП и ООП различаются и выходит что и свойства спроектированных систем различны. Т е там где буксует ФП — отлично растет ООП и наоборот.
Обычно такие вопросы возникают у тех кто не смирился с мыслью, что объект в ООП не равен объекту реального мира.

Причем тут реальный мир, я писал что-то о реальном мире? А вот во всех книгах про ООП обычно и моделируются объекты из реального мира — животные и иерархия в компании и подобное.
В реальности 99% кода это не реальный мир — кэш, HTTP, ответ от БД, обход коллекции, и т.д. На них как раз ооп и не ложится в отличии от вымышленных примеров.


ФП в целом проектировать позволяет

Что именно из деталей ФП мешает проектированию?)


Т е там где буксует ФП — отлично растет ООП и наоборот.

Можно привести примеры и теоретические выкладки где ФП буксует а ООП нет и наоборот. Без них вы как бы просто пустословите, ИМХО.


P.S.
Хотелось бы в проектировании/программировании обойтись без искусства иначе спорить можно до бесконечности.)
Что бы самому не быть голословным, приведу примеры того как предметная область не ложится на ООП из-за чего вылазит геморой.
ORM исключительно продукт ООП, попытка натянуть эту парадигму на реляционную. Из-за чего для достаточно простой задачи извлечь данные из БД нужно городить кучу классов и хитрых связей между ними. Как итог вам нужно знать SQL + ORM, две системы вместо одной. Я уже не говорю о том что ORM библиотеки между собой могут существенно отличаться.
Во пример отличного применения ООП:)
https://github.com/spring-projects/spring-framework/tree/master/spring-web/src/main/java/org/springframework/http
90% кода просто перегоняют данные из одного типа(класса) в другой.
И все это чтобы представить такую простую штуку как HTTP запрос/ответ:


GET /wiki/страница HTTP/1.1
Host: ru.wikipedia.org
User-Agent: Mozilla/5.0 (X11; U; Linux i686; ru; rv:1.9b5) Gecko/2008050509 Firefox/3.0b5
Accept: text/html
Connection: close
(пустая строка)

Которую в любом ЯП можно представить как ассоциативный массив.


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

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

Я бы не обобщал это на прямо все книги. Не вы не я не читали всех книг по ооп.
Можно привести примеры и теоретические выкладки где ФП буксует а ООП нет и наоборот. Без них вы как бы просто пустословите, ИМХО.

Давайте не будем бросаться колкостями если вы реально хотите диалога а не драки, хорошо? Как вам пример с оконными интерфейсами?
В реальности 99% кода это не реальный мир — кэш, HTTP, ответ от БД, обход коллекции, и т.д. На них как раз ооп и не ложится в отличии от вымышленных примеров.

Впервые слышу что на кэш или http ооп «не ложиться»
Которую в любом ЯП можно представить как ассоциативный массив

Вот как раз этого ООП старается избежать. Это называется «выхолащивание» абстракций. Т е в любой момент можно добавить/удалить из этого массива поле что приведет к неработоспособности кода, но с первого взгляда эта проблема будет скрыта и не то что компилятор не определит, но и программисту придется отслеживать все места в коде где идут операции с этими ассоциативными списками. Тогда как в ооп это либо вообще не скомпилируется, либо можно будет легко найти где идут операции с этим полем. Если уж хотите корректное сравнение с ФП тогда в пример нужно приводить записи(record) ну или алгебраические типы. Но записи мало чем отличаются от объектов с оторванными методами и в принципе их легко имитировать на ООП. Алгебраические типы конечно уникальны для ФП, но и они имеют свою нишу. Если уж на то пошло, то самое сильное отличие ФП от ООП — это использование ридонли-структур. Именно из этого вытекает большинство плюсов ФП и одновременно его же минусов.
НЛО прилетело и опубликовало эту надпись здесь
Мне кажется, что разговоры о нужности/полезности/оптимальности (ненужное зачеркнуть) ООП оправданы только по отношениям к языкам, в которых все есть ссылка на класс, а любое действие — вызов метода, обычно виртуальный. У C++ могут быть проблемы с «истинным функциональным программировании», но и только. А так — есть место ООП и есть место, где лучше без ООП.
Правда, и туда пробрались глобальный функции… )
НЛО прилетело и опубликовало эту надпись здесь
Для котиков и окошек ООП отлично подходит, для бизнес логики где нет четкого наследования и нет необходимости в объектах

А почему нет необходимости в объектах? Объекты обладают свойствами: состояние, идентичность, поведение. Я думаю бизнес-объекты этим тоже обладают.


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


Что такое "четкое наследование" и почему в бизнес логике его нет?

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

Из Мейера помнится, что при многопоточности в C++ f(g(x),y(z)); — это не то же самое, что auto a = g(x); auto b = y(z); f(a,b);. А так язык неплохой, и Кьеркегор, как оказалось, в деле...

Вроде то же самое, что и
if (some_random() % 2 == 0)
{
  auto a = g(x);
  auto b = y(x);
  f(a, b);
}
else
{
  auto b = y(x);
  auto a = g(x);
  f(a, b);
}

, но по новому стандарту, вроде всегда должен выполняться if, или только будет должен…
Начиная с C++17 всегда только if: [intro.execution.16]
Every value computation and side effect associated with a full-expression is sequenced before every value
computation and side effect associated with the next full-expression to be evaluated

По-моему, здесь говорится о законченных выражениях ("full expression"), аргументы функции являются подвыражениями (subexpressions), поэтому к ним это не относится. То есть ваша цитата фактически гарантирует, что statement1(); statement2(); выполнится в порядке 1-2.


Насколько мне известно, до C++17 в стандарте ничего не было про порядок в аргументах функции, поэтому это было UB, а теперь официально закреплено, что порядок произвольный. Я не знаю, где выдержку прямо из стандарта взять, но на cppreference вот так написано:


15) In a function call, value computations and side effects of the initialization of every parameter are indeterminately sequenced with respect to value computations and side effects of any other parameter.
Все верно, я говорил про вторую часть первого комментария: auto a = g(x); auto b = y(z); f(a,b);А параметры функции, насколько я понимаю, описываются [intro.execution.17]:
Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced. [ Note: In an expression that is evaluated more than once during the execution of a program, unsequenced and indeterminately sequenced evaluations of its subexpressions need not be performed consistently in different evaluations. — end note ] The value computations of the operands of an operator are sequenced before the value computation of the result of the operator. If a side effect on a memory location (4.4) is unsequenced relative to either another side effect on the same memory location or a value computation using the value of any object in the same memory location, and they are not potentially concurrent (4.7), the behavior is undefined. [ Note: The next section imposes similar, but more complex restrictions on potentially concurrent computations. — end note ]
Получается, они должны быть unsequenced. Странно, что cppreference говорит о другом. Возможно, я где-то запутался.
Нет, все нормально с cppreference, это я читать не умею. [expr.call.5]:
The postfix-expression is sequenced before each expression in the expression-list and any default argument. The initialization of a parameter, including every associated value computation and side effect, is indeterminately sequenced with respect to that of any other parameter.

Ну тут дело вроде даже не в многопоточности, а в том, что в C++ не гарантируется порядок вычисления аргументов функции и даже то, что они будут вычислены последовательно. Это, например, приводит к опасным и трудно-находимым багам. Например,
f(unique_ptr<int>(new int(100)), g()) может привести к утечке памяти, если g() выбрасывает исключение.

вот вы привели пример из книги Майерса на тему «зачем нужен make_unique», но в угоду аргументу забыли про make_unique. Вас совесть после этого не мучает?
НЛО прилетело и опубликовало эту надпись здесь

Вот мне приходится писать код с условием, что он будет компилироваться на g++-4.7, в нем даже C++11 не весь, а make_unique лишь в 14м стандарте появился. Может я не один такой с устаревшими компиляторами, там эта проблема может быть актуальной.

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

А ведь если тренды пойдут так, как сейчас — эти слова, которые надо выбить в граните, могут, увы, стать "Говорил я вам — не прислушались". Достаточно взглянуть, скажем, на Atom (который редактор)…
C++ сейчас учу и он начинает мне нравиться. Но: во-первых, сочинял его человек, не учившийся математике или ненавидящий её. Глядя на выражение вида A(b), математик никогда не угадает, что это инициализация. Кроме того, с дизайном очень плохо
public static virtual *** &&
Не должны половину программы занимать служебные слова, не должны быть знаки * и & там, где они предполагаются по умолчанию.
Ну, не нравится математику A(b) — может и A{b} написать. А что касается * и &. то всей Одессе они нравятся, только математик недоволен:) Не трогайте священное наследие C, которое, по словам Страуструпа же, одновременно обожают и ненавидят;)
А вот где математик нашел 'public static virtual'…
НЛО прилетело и опубликовало эту надпись здесь
а где знаки *, & && и пр. предполагаются по умолчанию?
Зарегистрируйтесь на Хабре, чтобы оставить комментарий