Pull to refresh

Comments 253

Статья в стиле: я не понимаю ООП и не могу на нем нормально программировать, поэтому ООП — плохой. Интересно, автор про SOLID что нибудь слышал?
Т.е. Вы считаете, что человек, постоянно работающей в области ЯП, при этом имеющий тонну публикаций и исследований ничего не понимает в ООП?

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

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

И люди с ООП головного мозга пишут всякое такое:

class ClassA {};
class ClassB: private ClassA
{
public:
ClassA& AsClassA()
{
return *this;
}
};

А самое страшное — народ со скамьи разучился думать и писать ПРОСТО и это очень грустно :(
Ну, конечно, хотелось бы предметного диалога с автором. Несмотря на это, постараюсь прокомментировать статью и некоторые моменты, чтобы не быть голословным:

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

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

В процедурных программах процедуры вызывают другие процедуры. Процедурный код показывает… процедуры, вызывающие другие процедуры. Все хорошо и просто, так ведь?

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

С тем же успехом можно утверждать, что параметры — вот они были объявлены my_param, а теперь вдруг при исполнении опа, и нет my_param, а есть лишь 0 в ячейке памяти. Неожиданно, правда? Так и с объектами, есть класс, который объявляет, что будет внутри, т.е. сосуд, а наполнение может быть самым разным. Это, на минутку, присуще всем языкам, ООП тут вообще ни при чем.

Честно говоря, методы я тоже терпеть не могу.

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

Примем во внимание то, что на чтение объектно-ориентированного кода мы тратим больше времени, чем на его написание.

Для того, чтобы использовать, нет необходимости читать код. Для этого есть доки. Это же можно отнести к любой парадигме, ООП тут не исключение. А абзац можно понять так: предположим, что читать код ООП очень тяжело. Вот видите, т.к. читать очень тяжело, то мы столько времени на это тратим, таким образом производительность падает. Хочется спросить: откуда первоначальное утверждение?

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

Наверно, в функциональных языках нет типов? Или, может, в процедурных? Очевидно, там нет, поэтому положим минус в копилку ООП, говорит нам автор.

Можно еще долго комментировать это послание про ООП. Но, думаю, для начала достаточно.
Вы реально все это восприняли только в прямом смысле?

Я сомневаюсь, что он не знает всех плюсов ООП, которых тоже весьма и весьма прилично.

ИМХО Автор имел ввиду показать что существует множество заблуждений по поводу ООП:
Что ООП ИДЕАЛЬНО описывает окружающий мир, что он ПРОЩЕ и УДОБНЕЙ, что ПОВТОРНОЕ ИСПОЛЬЗОВАНИЕ кода всегда нужно, что ПОСТОЯННЫЙ КАСТИНГ ТИПОВ это хорошо и т.д.

Я так понял, что он просто попытался показать его под другим углом.
Это отлично, что он хочет сказать, что ООП — не панацея, что существуют другие парадигмы. Но только то, КАК он это сказал и какие аргументы привел, вызывает ряд вопросов.

Вы реально все это восприняли только в прямом смысле?

Хм, а можно все это как-то воспринять в переносном смысле? Какой тогда смысл в статье, если я должен додумывать, что же на самом деле хотел сказать автор? Если автор, как говорилось выше, такой профессионал, то он должен четко формулировать свою мысль, чтобы невозможно было понять мысль двояко. Или я ничего не смыслю в профессионализме?
Я думаю, дело в том, что это не послание публике, а послание таким же спецам на конференции, а они «смысл прохавают»
Единственное, что я вынес из статьи, это, что автор попытался объяснить: «нет ничего идеального и совершенного, ООП не панацея». Зачем только он это сделал непонятно: умные люди и так это знали, а для глупых, по-моему, ничего принципиально не изменилось.
Я где-то 6-8 (не помню уже) лет занимался профессионально фехтованием.

У нас тоже была такая шутка:
" — Петров, ты почему халтуришь \ не занимаешься разминкой
— Тренер, так давно известно: профессионалам она не нужна, а остальным и так не поможет" )
Забавно. Тоже вспомнилось: «Книга оказала влияние, обычное для хороших книг: глупые стали глупее, умные умнее, а тысячи прочих ни в чем не изменились».
> ИМХО Автор имел ввиду показать

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

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

Писать свой список вопросов не будут, т.к. по большому счету согласен с gridem habrahabr.ru/post/169601/#comment_5880081"
А от «дайте IDE с объектами вообще похихикал» :D Это как?
См. любую Smalltalk-среду с образом и GUI, а еще лучше сразу Self с изначальным Morphic-ом.
Хм… Напоминает Object Browser и Watch (при запущенной отладке) в Visual Studio. Возникает вопрос чем тогда не доволен автор статьи (он утверждает что таких инструментов вообще нет с ООП). Я кстати, подумал что он вообще хочет видеть реальные объекты в IDE. Поэтому и улыбнуло. А если так — то такое, как я уже сказал, есть.
Выше я показал два вида инспекторов объектов, доступных в Pharo (одной из реализаций Smalltalk). Да, они являются родственниками (а то и родителями) упомянутых инструментов в VS (или практически любой другой мейнстримовой среде). Только помощнее и поудобнее в некоторых аспектах. Но главное, позволяют работать с объектами напрямую в любой момент — но это не их личная заслуга. Просто в Smalltalk-ах нет разделения на время «редактирования», «выполнения» и «выполнения с отладкой» — любая программа выполняется в единой среде, в которой (если не отключены) живут все объекты, представляющие средства разработки, отладки, сами классы, методы… и вообще почти все, что есть в программной системе. Очень удобно и эффективно (с точки зрения разработчика, как миминимум).

Тем не менее, несмотря на свою относительную развитость, объектность и даже авангардность (да, я про систему, созданную более 30 лет назад!), среда Smalltalk все равно несет в себе, как очень точно подмечено, следы кодо-ориентированности. Программист даже в Smalltalk-е все равно значительную часть времени вынужден проводить, работая с кодом, а не с живыми объектами. Что уж говорить о «современных» «продвинутых» текстовых редакторах, которые по недоразумению кем-то были названы IDE :)

В принципе, это мое личное мнение, но автор, как мне кажется, говорил именно об этом. Так что, да: думаю, он хочет видеть реальные объекты в IDE… и как можно чаще. Тем, что это не удается делать чаще, он и недоволен. А про полное отсутствие он не говорит… даже упоминает кое-что (тот же Seaside).
Просто в Smalltalk-ах нет разделения на время «редактирования», «выполнения» и «выполнения с отладкой» — любая программа выполняется в единой среде, в которой (если не отключены) живут все объекты, представляющие средства разработки, отладки, сами классы, методы… и вообще почти все, что есть в программной системе. Очень удобно и эффективно (с точки зрения разработчика, как миминимум).

Если это так, то как оно сохраняется? И есть ли там понятие «перезапустить программу», например (да и есть ли понятие программы вообще)?
Если это так, то как оно сохраняется?

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

И есть ли там понятие «перезапустить программу», например (да и есть ли понятие программы вообще)?

А что такое программа? Вычисления запускаются передачей сообщения некоторому объекту, который для его обработки передает сообщения другим объектам и т.д. Соответственно «перезапуск» программы выполняется остановкой процесса, выполняющего такие вычисления, и запуск нового аналогичным способом.
Соответственно «перезапуск» программы выполняется остановкой процесса, выполняющего такие вычисления, и запуск нового аналогичным способом.

А есть ли способ при этом определить, какие объекты, созданные на предыдущем запуске, надо убить, а какие оставить? И как-нибудь привести объекты в «первоначальное состояние»? Или всё это — просто загрузка сохранённого образа?
Интересная модель. Надо будет поиграться.
Сборка мусора.

Если есть глобальные объекты (что плохо), разумеется надо самому заботится об правильной переинициализации. Перезапуск образа в «начальное состояние» ничего не сбрасывает — разве что почистит внешние ресурсы (что тоже не всегда удобно, но как иначе?). Можно создать новый образ (из чистого) и загрузить туда нужный код. В общем, работа с образами удобна, но требует определенной дисциплины управления образами.

Да, я в прошлом комментарии не упомямнул, что объекты из образа можно различными способами выгружать и загружать обратно. И, естественно, существует целый ряд инструментов для управления исходным кодом.
В Visual Studio они норовят исчезнуть при любой попытке убрать с них курсор.
Посмотреть код делегата, лежащего в поле какого-то объекта, мне не удалось. Кое-как добрался до Target объекта, но какая функция к нему привязана, осталось загадкой.
Есть ли возможность, например, поставить break point на изменение или на чтение поля конкретного экземпляра? Найти все ссылки на объект? А как-нибудь отфильтровать их?
Про ручное добавление метода к объекту в VS, речи, конечно, не идёт — C# и в коде сделать такого не позволит. Но интересно, возможно ли это в среде Smalltalk.
> В Visual Studio они норовят исчезнуть при любой попытке убрать с них курсор.

Вы с значениями по месту в коде не путаете. Окна Watch и Object Browser прекрасно живут как в отдельных вкладках, так и на втором мониторе.

> Есть ли возможность, например, поставить break point на изменение или на чтение поля конкретного экземпляра?

Поля кажется нет, а проперти да (перейдя кликом из Object Browser в исходник).

> Найти все ссылки на объект?

Shift + F12?

> Про ручное добавление метода к объекту в VS

Не понял что требуется.
Поля кажется нет, а проперти да

Это будет breakpoint на конкретный экземпляр объекта или на класс в целом?

Окна Watch и Object Browser прекрасно живут как в отдельных вкладках, так и на втором мониторе.

У меня Object Browser почему-то показывает только классы, а не объекты. И даже перейти на класс в этом окне из объекта в Watch пока не получается.

Shift + F12?

В окне Watch? Тоже не работает.

Не понял что требуется.

Добавить к объекту новый метод. С именем, сигнатурой и реализацией (например, как лямбда-выражение). Чтобы потом вызвать его, например, через dynamic.
Написать метод расширения…
Он будет у конкретного экземпляра или у класса в целом?
У класса в целом. Все пространство имен System.Linq; состоит из них, у коллекций нету методов ToArray, ToList, ToDictionary и прочих стандартнейших и привычных.
Да — все перечисленное не только возможно, но в том или ином виде уже реализовано.
Только методы добавляются не к индивидуальным объектам, а к классам — просто поведение объекта полностью определяется классом, к которому он принадлежит. Но при необходимости можно «на лету» создать новый класс с нужным методом и сделать объект его экземпляром. Это, конечно, не так уж и просто. Хотя не так уж часто такое требуется, но все равно особо не радует. И речь о желательности иметь бессклассовый объектный язык заходит в том числе и поэтому (среди прочих соображений).
Тогда автор и функции тогда должен не любить. Потому что метод — это функция, где дополнительным параметром будет объект, т.е. экземпляр класса.

У метода есть неприятное свойство — требовать наличия дополнительного параметра, да ещё предварительно порождённого от конструктора.
У методов есть более неприятное свойство — они разделены друг от друга слоями Священной Инкапсуляции, и поэтому в типичных ООП-системах существенная часть методов просто передаёт вызов дальше, в какой-нибудь следующий класс.
Т.е. сидишь отслеживаешь граф вызовов всё дальше и дальше, и никак не можешь найти место — а где же, собственно, метод реализован?
Это уж как у автора фантазия работатает. Если москзг так устроен, то тут язык не причем. Языки с меньшим количеством ограничений вообще позволяют творить всякий ужос-ужос-ужос. И ничего, одни как-то пишут, другие это как-то разбирают. Это как любой инструмент: чем проще, тем больше можно сделать, но очень сложно. Сложным специальным инструментом можно сделать меньше, но проще и качественнее. Так что, имхо, все упирается в человека, вцепившегося рученками в этот самый инсрумент.
Вот когда граф вызовов отслеживаешь (если я правильно понял, вы говорите о call stack во время выполнения в дебаге?), реализация как раз таки и показывается.

Ну а если каша из реализаций и делегирований? Такой же код можно и в функциональном пихнуть ( {int, int, function {int, int -> int} -> int} ) — отгадай, что за функцию передали параметром в другую функцию.
Тут автор явно передергивает. Понятно, что классы существуют только в нашем сознании, но, о ужас, не только классы, но и функции, переменные и проч

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

Естественно, использование чисто абстрактной идеи в языке программирования — это не смертельно. Но ведь одной из фишек ООП обычно называют как раз отражение реального мира, не так ли? Т.е., например, функциональное программирование часто сопоставляется с математикой, а не с реальным миром. Соответственно, в ФП принято оперировать понятиями из математики — чистые функции, отсутствие состояния, алгебраические типы данных и т.д. ООП само по себе, у него нет «родительской парадигмы» — оно не отражает ни реальный мир, ни какую-то другую науку. Это, опять же, не смертельно, но вполне достаточно, чтобы записать в минусы.

Для того, чтобы использовать, нет необходимости читать код.

Если вы — автор этого кода, то читать вам его придётся. А читать код нам приходится гораздо чаще, чем писать. И да, это не специфично для ООП, ООП просто делает отслеживание потока контроля сложней из-за постоянного делегирования обязанностей, заставляя прыгать по всей системе. Поэтому автор и упоминает синдром «затерянных в космосе».
класс в ООП — это, по сути, протокол создания объектов, описатель будущих экземпляров. Что в природе ведёт себя так же, как классы в ООП? Мне в голову ничего не приходит.

Фабричный конвейер.

Т.е. метафора ООП хоть и не для любых моделируемых сущностей адекватна, но всё же осязаемее, чем «чистые функции» и т.п.
Фабричный конвеер соответвует фабричному методу в ООП — одна сущность порождает другую. Класс не соответствует конвееру ни по названию, ни по семантике (если, конечно, речь идёт о таких языках как Java и C++, в других языках, таких как Ruby, Delphi, Common Lisp и т.д. конструкторы сами по себе являются фабричными методами).

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


В том то и дело, что не обязательно опираться на что-то реальное — главное, чтобы «родительская парадигма» была хорошо известна. Тогда ответ на вопрос, как именно реализовать ту или иную фичу, становится очевидным. Если же хорошей аналогии нет, то каждый разработчик будет строить свои собственные абстракции со своими собственными правилами. А когда речь дойдёт до интеграции, то окажется, что одна половина дома построена из панелей, а вторая — из кирпичей (с)
Класс соответствует спецификации, которой нет в природе (по каналу Дискавери что ли?), по чертежи и ТЗ вполне привычная вещь на производстве.
Главное, в классах то, что они очень хорошо бюрократизируется, а бюрократия такая штука, что во всех случаях выбирается наименее эффективный способ реализации; однако, по-другому не умеют.
Хм, а чем концептуально отличается «фабричный метод в ООП» от класса?
И то и другое — способ превращать указания «создай мне X» в экземпляры X.

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

В общем и целом моя позиция в том, что для классов нет красивой аналогии ни в реальном мире, ни в живой природе (откуда явно пришли некоторые понятия), ни где-то ещё. Даже если взять конструкторы в виде статических фабричных методов (e.g. MyClass.new), то они всё равно не особо похожи на фабричное производство: на производстве есть отдельно схема и отдельно машина, создающая предметы по этой схеме; в ООП класс представляет из себя сразу и схему, и машину. Лично мне довольно сложно представить себе такую машину. А если ещё попробовать привизать к ней такие понятия как наследование или полиморфизм… Дэвид Линч отдыхает.

И да, кстати, обратите внимание на терминологию: класс практически во всех ООЯП называется именно классом, а не фабрикой или чем-то таким. А это, опять же, ведёт к разной интерпретации разными людьми и вытекающими из этого проблемами.
К понятию класса приходишь постепенно, если много пишешь на процедурном языке, например на Си.
В какой-то момент просто задалбываешься писать функции, которые принимают аргументом указатель на структуру.
К понятию private приходишь, когда понимаешь, что все поля данной структуры предназначены для внутреннего пользования и объявляешь структуру уже в .c файле, в имплементации.
Могу рассказать, как приходишь к понятию конструктор и деструктор.
В общем-то, если много пишешь, сам придёшь к ООП от процедурного программирования.
Но после ООП переходить на ФП — здесь уже нужна не практика, а стремление «сделать не как все». Подобное стремление особо развито у программистов не могущих проявить себя на фоне более умелых коллег.
Вы знаете, я вполне уверен, что у вас очень стройное представление о теме разговора, но не могли бы вы пояснить, к чему относится ваш комментарий?
Извините, он относится к комментарию megalol чуть выше.
Но после ООП переходить на ФП — здесь уже нужна не практика, а стремление «сделать не как все». Подобное стремление особо развито у программистов не могущих проявить себя на фоне более умелых коллег.

Дело не в ФП.
У умелых коллег есть фатальный недостаток — они ничего, кроме ООП не видели и видеть не хотят, и то, что есть везде (даже в pure c, типа приватности) считают достоинствами именно ООП. Запущенный случай синдрома утенка. Т.е. если «они» прочитали в книжке об ООП о том, что private — это хорошо, они не узнают о том, что в любой сишной либе сокрытие обеспечивается. В сишных книгах не пишут о таких специфических вещах. Сахарок неявного this считается чем-то фундаментальным. Полиморфизм на VMT — по-другому не бывает. Бывает.
Есть лямбды в объектно-ориентированном руби, есть деструкторы в обобщенной STL. Парадигму составляют не фичи, а совокупность фич. Какие вещи являются специфичными именно для ООП? Да хреновые. У ООП, особенно статического и мейнстримного, есть несколько фатальных недостатков.

1. Непринятие ФВП. Вместо этого — тонна паттернов вида «конструктор+метод exec», половина GoF в этих паттернах.
2. Отсутствие или неэффективность двойной диспетчеризации. Лечится визитором и тонной мелких методов для эмуляции двойной диспетчеризации.
3. Нельзя указать на то, что X — является одновременно чем-то и чем-то. Типа foo(x: IFooable, IBarable). Вместо этого нужно делать интерфейс IFooableAndBarable.
4. И многое другое.

Вот эти три пункта лечат тьмой однострочных методов. Они неэффективны. А «достоинства ООП» (не важно, появились они первый раз в ООП языке или нет) умные люди догадались оставить в пост-ООП языках, не дураки же.
Пост-ООП языки это какие, например?
Clay, Rust, Julia. Go тоже можно сюда вписать, но он меня никогда не интересовал. Но в целом он вписывается в тот тренд, что в один момент появилось много языков, в которых отсутствие ООП упоминается как фича. Вполне обыкновенных языков, не ортодоксальной функциональщины. Они, конечно, вряд ли взлетят, потому что языку не достаточно быть просто лучше другого языка.

Clay — шаблоны С++ на стероидах (выводом типов, встроенным в язык предикатами а-ля boost:enable_if, мощная compile time рефлексия). На порядок лаконичнее С++ (код может выглядеть как питон с фигурными скобками), но с теми же минусами в виде выпадения ошибки компилятора в неочевидном месте, которые слегка лечатся предикатами. Множественная диспетчеризация есть.

В Rust используются тайпклассы. Вместо передачи в функцию объекта, который в свою очередь содержит указатель на VMT, используется пара указателей — один на таблицу методов, другой на сам объект. Отсюда, например, x: IFooable, IBarable реализуется легко: нужно передать 3 указателя: на x, и на 2 таблицы методов. Соответственно не нужно городить N*M искусственных классов или, что делается чаще, даункастить, получая проблемы уже в рантайме. На тайпклассах делать частичную специализацию подобно шаблонам С++, но без минусов шаблонов и их избыточной сложности. А вот с двойной диспетчеризацией в Rust проблемы, насколько я знаю.
Что мешает сделать класс FooBarable с полем type?
Т.е. по вашему, тысячи программистов пишущих на функциональных языках (иногда — крупные и сложные проекты) так ничего в своей жизни и не поняли?
Причём здесь поняли или нет, они сделали — работает — молодцы. Проблема ФП в том, что на каждую тысячу таких программистов приходится миллион пишущих на ООП Языках и тысяч десять пишущих по-старинке на процедурных. И они тоже делают крупные и сложные проекты, и даже не иногда, а почти постоянно. Для разработки на ООП языках это норма, для ФП языков — это скорее исключение. Мало кто берётся за тот же хаскель, чтобы разработать новый движок для сайта или написать полезное приложение, в 99% случаев возьмут более понятный и привычный подход.
Как раз-таки конвейер без схемы мне представить проще: у меня в соседнем доме пекарня, и в машину с одной стороны засыпают муку, с другой выезжают по ленте лепёшки. Даже если у неё есть какой-то «отсек для схемы лепёшек», вряд ли её оператор им когда-либо пользуется. И пирожки с яблоками эта машина не начнёт печь ну ни по какой схеме.

А устоявшаяся терминология — вопрос исключительно исторический. Одно и то же понятие называется по-английски «нитками», по-русски «потоками» — и что, его по-разному из-за этого интерпретируют? «Сокращённый путь» и «ярлык», который до компьютеров означал этикетку, и так далее.
Так в том то и дело, что класс — это «конвеер + схема». Представить эти предметы по отдельности легко, а вот вместе, в одном неделимом предмете они мне как-то не встречались.

Одно и то же понятие называется по-английски «нитками», по-русски «потоками» — и что, его по-разному из-за этого интерпретируют?

Но и английский, и русский варианты отражают связанную последовательность (в данном случае — последовательность команд). А вот к чему относится слово «класс» я так и не понял. Но более важно то, что слова «нить» и «поток» описывают абсолютно чёткое понятие, а вот «класс» в разных языках программирования может означать очень разные вещи.
> Что в природе ведёт себя так же, как классы в ООП?

ДНК
ДНК описывает ровно одну особь — даже родители этой особи имеют другие цепочки ДНК, и даже при бесполом размножении и отсутствии мутаций дочерние особи не будут идентичными хотя бы из-за разных условий развития. ДНК как раз показывает всю абстрактность понятия класса — в природе сущесвтуют объекты, взаимодействующие друг с другом, но в виды/классы/царства их объединяем уже мы. Природа, по сути, придерживается утиной типизации — если объект умеет крякать, то мы мы можем объединить его по этому признаку с другими подобными объектами и назвать их всех утками. Но нет никакой метасущности DuckClass, из которой были порождены все утки.
ДНК описывает миллиарды клеток особи
ДНК задаёт миллионы разных клеток организма. Из класса всегда пораждаются одинаковые объекты.
Если объекты одинаковые, нафиг они нужны? У клеток стейт разный. Объекты как раз и интересны состоянием. Хреновая архитектура с блобом, да.
Можно еще взять концепцию «ген как класс». Спецификация, по которой генерируется белок. Это поинтереснее, потому что и наследование можно найти — подтипы 5HT рецепторов, например, интерфейс один, суть разная. Это если очень надо, чтобы классы были по каналу Дискавери.
Но зачем оно надо, не понятно. Чертежей в природе, тоже не бывает, например, но это не значит, что чертежи не существуют. В общем и целом — в быту да, любят дактайпинг, но на производстве попытка засунуть в ЧПУ станок ежа вместо ужа может быть плачевной, и дактайпинг там не к месту, чем больше модель соответствует спеке, тем лучше.
Слово «чертёж» гораздо лучше отражало бы классы как схемы для объектов, но даже чертежи и схемы плохо соотносятся с такими понятиями ООП как полиморфизм или наследование. А без более или менее чёткой аналогии, как я уже говорил, теряется преимущество единой модели. Не смертельно, но и приятного мало.
Наследование интерфейсов есть. Полиморфизм, соответственно тоже. Принятого в ООП единичного наследования реализации, скорее нет, но это специфичная именно для программирования вещь. Множественного наследования полно.
Эээ, наследование интерфейсов чего? Это что ли я взял у Васи его чертёж и перерисовал под свою задачу? Тут максимум прототипирование, с наследованием ничего общего. То же самое касается полиморфизма, пояснитесь, пожалуйста.
У деталей тоже есть интерфейсы — например, поверхности, которые позволяют их соединять. Соответственно, два предмета с общим механическим интерфейсом являются полиморфными.
Тут максимум прототипирование, с наследованием ничего общего.

Как это ничего общего. В прототипном ООП нет классов, а тут есть класс — чертеж детали, и экземпляр — конкретная деталь, которая обладает своими интерфейсами, определяемыми классом, и состоянием.
У деталей тоже есть интерфейсы — например, поверхности, которые позволяют их соединять. Соответственно, два предмета с общим механическим интерфейсом являются полиморфными.

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

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

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

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

> Из класса всегда пораждаются одинаковые объекты.

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

> Особи, созданные по одной ДНК — это как? Клонирование что ли?

Да. Классы точно такие же клоны, разве нет?

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

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

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

Человек одев крылья, хвост и клюв своеобразной формы становится птицей?

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

> Найдёте для них «метасущность», порадившую оба предмета?

Табурет :)
ДНК — декларация, а не исполняемый файл. Это вполне себе файл данных.
И точно так же одна и та же последовательность нуклеотидов (=код класса) всегда порождает одинаковые объекты

Это не так
А как? Может быть где-то можно по подробнее про это почитать? (лучше не слишком научно)
ДНК — код на языке, который конвертируется в другой язык (условно — РНК) который интерпретируется в рибосомах (результат интерпретации — белок). Интерпретатор обладает собственным состоянием и может из одного и того же кода создавать разные белки (читать, например, elementy.ru/news/431959)
> Особи, созданные по одной ДНК — это как? Клонирование что ли?
Да. Классы точно такие же клоны, разве нет?

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

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

Вы пытаетесь моделировать, я же говорю про аналогии. Реально в программе у вас будут объекты типа Person с 3-4мя свойствами, и реагировать на сообщения они будут вполне определённо. И наследоваться Person будет от какого-нибудь GenericUser (или вообще от Object), но никак не от Monkey.

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

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

> Найдёте для них «метасущность», порадившую оба предмета?

Табурет :)

И каков же был механизм порождения?
> Это как бы был намёк, что в природе клонирования не существует.

Это не так ru.wikipedia.org/wiki/Клонирование_(биология)

> Реально в программе у вас будут объекты типа Person с 3-4мя свойствами, и реагировать на сообщения они будут вполне определённо.

Вы наверное хотели сказать в простой программе?

> Вообще отличный вариант — при изучении и работе с ООП в качестве аналогии использовать слабоизученные понятия из совершенно другой области

Я так и не увидел аргументов против того что ДНК это программа, что кстати и написано в её определении: «Дезоксирибонуклеи́новая кислота́ (ДНК) — макромолекула (одна из трех основных, две другие — РНК и белки), обеспечивающая хранение, передачу из поколения в поколение и реализацию генетической программы развития и функционирования живых организмов. Основная роль ДНК в клетках — долговременное хранение информации о структуре РНК и белков.».

Кроме этого есть еще РНК: «РНК состоит из длинной цепи, в которой каждое звено называется нуклеотидом. Последовательность нуклеотидов позволяет РНК кодировать генетическую информацию. Все клеточные организмы используют РНК (мРНК) для программирования синтеза белков.». Эта программа выполняется в рибосомах и на выходе имеем новые экземпляры белков. Аналогия, ИМХО, полная (и даже проще чем с ДНК).

> И каков же был механизм порождения?

Без спинки сидеть неудобно :)

ЗЫ: цитаты из википедии.
Это не так ru.wikipedia.org/wiki/Клонирование_(биология)

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

Вы наверное хотели сказать в простой программе?

В любой программе, не пытающейся моделировать конкретно человека как билогический вид. Если Person у вас играет более или менее важную роль, то будет 10-12 полей. Если вы пишете очередной фейсбук, может быть будет 30-40 полей. Но никак не тысячи полей и методы, зависящие от внешних рандомных факторов.

Я так и не увидел аргументов против того что ДНК это программа, что кстати и написано в её определении:

Так я не понял, мы сравниваем ДНК с классами или с программой? Или и с тем, и с другим? И вы всё ещё считаете это интуитивной аналогией, на которой стоило бы строить модель? Ну ок, каждому своё.

«Без спинки сидеть неудобно :)» — это вы и называете «наследованием»?
> В любой программе

Я бы не стал обобщать, ИМХО, это все впереди :)

> Так я не понял, мы сравниваем ДНК с классами или с программой?

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

Охренеть
> ДНК описывает ровно одну особь — даже родители этой особи имеют другие цепочки ДНК

Все особи созданные по одной ДНК (= классу) одинаковы, изменения же в ДНК подобны рефакторингу (случайные изменения => ошибки допущенные программистом).

> Но нет никакой метасущности DuckClass, из которой были порождены все утки.

Определенная последовательность нуклеотидов, отвечающая за определенные признаки, как раз ей и будет (можно назвать её интерфейсом). И только по этой последовательности можно точно отнести создаваемые особи (объекты) к какому либо типу, одинаковых признаков у разных особей для этого недостаточно (умение крякать не делает человека уткой).
Особи, созданные по одной ДНК — это как? Клонирование что ли? Даже если так, то отличия между особями всё равно будут. Даже если Вася и Петя — близнецы и обладают абсолютно одинаковой ДНК, то на разные раздрожители они всё равно будут реагировать по разному. А вот инстансы класса Person, даже имея разные имена, будут реагировать на раздрожители (сообщения) одинаково, потому что это прописано в их методах. Если вам всё ещё нравится такая аналогия, и вас не смущает разница ни в терминологии, ни во внутренних механизмах классов в ООП и ДНК в живых организмах, то ради бога, пользуйтесь ей. Но, как я уже говорил выше, перечисленных отличий достаточно для недовольства автора изначальной статьи.

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

Если отойти от живой природы, то можно найти ещё более яркие примеры: офисное кресло и железный трон не имеют ничего общего, кроме того, что на них принято сидеть; тем не менее, и то, и другое вполне попадает под определение стула. Найдёте для них «метасущность», порадившую оба предмета?
Нет, не ДНК. Единственное, что действительно похоже на классы — виды живых существ. Хоть и не для всех случаев, но можно сказать, что вид является в природе не просто абстрактным понятием, т.е. это реально существующий пример ООП класса в реальной жизни.
ведь одной из фишек ООП обычно называют как раз отражение реального мира, не так ли?
Есть несколько абстракций, которые иногда используются на начальных этапах обучения ООП. Признаться — они меня всегда бесили. По-моему, также, как есть гуманитарный и технический склад ума, тамже существует и «тип мышления, легче обучающегося через аналогии» и «тип мышления, не требующего аналогий при обучении». Мне нафиг не нужны отображения вроде «class Car — это как машина в реальном мире, у неё есть разные характеристики (properties), она всякое умеет (methods)» и т.п. Мне достаточно понимания того, КАК работает та или иная конструкция. Тем не менее, выделение сущностей — чертовски хорошая идея, позволяющая четко отразить взаимосвязи между компонентами, модулями, классами и т.п.
Аналогии дают одно хорошее преимущество — они явно задают контекст. Если вы видите объект типа «Car», то вы уже заранее можете ожидать, что у него есть метод «drive». Если же вы видите абсолютно новое понятие, то вам именно что придётся сначала изучить, как с ним работать. Т.е. в первом случае у вас в голове уже есть некая модель объекта, во втором — вам сначала придётся её построить. И ладно бы на изучении объекта дело и заканчивалось, но если каждый программист использует свой собственный набор моделей, то где гарантия, что при интеграции эти модели совпадут, а не приведут к куче несовместимостей в коде? Если я в коде на C++ привык помечать все переменные в своих функциях как const, то мне будет довольно неприятно работать с библиотекой, постоянно использующей references и поэтому требующей изменяемых переменных. Единая парадигма или единая аналогия, которой приедживаются все разработчики, значительно снижает количество таких проблем несовместимости. Программы пишутся людьми для людей, и только потом — для компьютеров (с) Сассман.
Соответственно, в ФП принято оперировать понятиями из математики — чистые функции, отсутствие состояния, алгебраические типы данных и т.д. ООП само по себе, у него нет «родительской парадигмы» — оно не отражает ни реальный мир, ни какую-то другую науку.

Ну здрасьте. ООП – в чистом виде платоновские эйдосы, прямо вместе с иерархиями. Ничем не более и не менее абстрактное понятие, чем математика. И «не наука» в той же степени, что математика.
Интересно, сколько из присутствующих здесь разработчиков ассоциирует ООП с Платоном.
>Что в природе ведёт себя так же, как классы в ООП?

ИДЕИ.
Есть мир реальный, который мы осязаем, есть мир идей — т.е. работа нашего мозга, мышление (в том числе абстрактное). Эту тему хорошо развил Платон. Объекты в ООП соответствуют предметам реального мира, а классы — идеям реального мира (т.е. объектам идеального мира Платона). Вот машина (объект), вот еще одна машина (объект), и все это — машина как идея (класс), частный случай транспортного средства (абстрактный класс).
Почему-то на мой комментарий о классах целая куча людей сразу стала искать, что же в природе похоже на классы в ООП — ДНК, чертежи, идеи. И почему-то все пропустили основную мысль: у ООП нет очевидного аналога, с которым можно было бы сравнивать, на примере которого можно было бы объяснять парадигму новым разработчикам, и основываясь на котором можно было принимать архитектурные решения. Ни ДНК, ни чертежи, ни философия Платона не входят в ряд всем известных знаний; ООП не проводит явных аналогий с ними ни по терминологии, ни по свойствам. При желании можно найти общие черты между ООП и чем угодно. Но вопрос не в том, что в реальном мире сопоставить парадигме, вопрос в том, чему сама парадигма изначально была сопоставлена.
Вы слегка противоречите сами себе)

у ООП нет очевидного аналога,

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

— т.е. все-таки аналог есть?

Я согласен со второй цитатой. НЕВОЗМОЖНО создать нечто, не имеющее аналогов в реальном мире. И реальный, и техногенный мир построен на одних и тех же фундаментальных понятиях.
И в чём же противоречие? Вопрос: на основе каких идей из реально мира было создано ООП? Ответ не очевиден. По-моему, всё очень логично.

Я согласен со второй цитатой. НЕВОЗМОЖНО создать нечто, не имеющее аналогов в реальном мире.

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

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

Бесконечная последовательность.

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

Бла-бла-бла. Вы не представляете, сколько раз я вёл подобный диалог, и каждый раз безрезультатно. ООП отражает реальный мир ни чуть не больше, чем процедурное, функциональное или какое либо ещё программирование. То, что ООП прихватизировало понятие «объект» ещё не значит, что оно отражает мир лучше. Я бы сказал, что оно отражает реальность гораздо хуже того же процедурного подхода, потому что когда мы пишем программу, мы описываем, что мы делаем над объектами (процедуры над структурами), а не что сами объекты делают. point.add(another_point) — мы прибавляем одну точку к другой, а не одна точка берёт и прибавляет к себе другую. connection.open() — мы открываем соединение, а не само соединение берёт и ни с того, ни с сего решает открыться. Переставьте this с места перед точкой в список аргументов и вы получите чистый процедурный подход. И именно этот подход будет отражать наши действия в реальности. feed(cat) — покормить кота, а не cat.feed() — кот кормит.

Обобщение понятий по общим признакам — это интерфейсы. Классы задают строгую иерархию, которой объекты реального мира не обладают. Камень и автомат калашникова не имеют ничего общего в своём происхождении (читай, не имеют общего класса-предка), но оба могут быть использованы как оружие (реализуют интерфейс «оружие»). Отношения между объектами реального мира гораздо сложней, чем это описывает ООП. Если не верите, попробуйте составить мало-мальски серьёзную онтологию на основе иерархии классов. А потом сравните, например, с логическим программированием и подумайте, так ли хорошо ООП описывает мир.
feed(cat) — покормить кота, а не cat.feed()

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

Cat cat;
cat.eat(); — мы сказали коту «иди поешь!»

или
Human human;
Cat cat;
human.feed(cat); — мы сказали человеку «покорми кота»

Обобщение понятий по общим признакам — это интерфейсы

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

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

Бесконечная последовательность.

Вселенная по-вашему конечна? Есть граница?
Вселенная по-вашему конечна? Есть граница?

Я вам специально написал «бесконечная последовательность», а не «бесконечная вселенная». Рассуждать о бесконечности вселенной бессмысленно — мы не видели её границ, так что не знаем точно. А вот бесконечные последовательности одназначно существуют в математике. Не нравятся бесконечные последовательности, ок, найдите в природе аналог любого ненатурального числа, например, минус единицы. Можете нарисовать мне минус одно яблоко? А как насчёт мнимой единицы яблока? На самом деле в природе нет ни сложения, ни вычитания (есть перенос яблок из одного места в другое), ни дробных чисел, ни корней квадратных и т.д. Математика — это формальная система, удобная абстракция, которая позволяет проще оперировать объектами реальности. Но далеко не все элементы абстракции имеют хотя бы один аналог в реальности.

Cat cat;
cat.eat(); — мы сказали коту «иди поешь!»

И часто вы разговариваете с котами? Нет, серьёзно. Говорить коту «иди поешь» — это либо вы — Куклачёв, либо просто не соответсвует реальности. И именно такое передёргивание понятий и ведёт к плохому дизайну, оторванному от реальности.

Пример с человеком уже лучше, но если это человек изменяет состояние кота, то в чём отличие класса Cat от одноимённой структуры? Мы модифицируем структуру извне, а значит кот теряет свои объектные свойства.

Ну и да, как там с точками? Точке вы тоже говорите «сложись с вон той другой точкой»? А соединение с сервером тоже превращается в живое существо, которое может открывать и закрывать себя?

Так что хреновенько ООП отражает наш способ описания мира.

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

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

У вас какие то неправильные коты похоже, т.к. все мои кошки прекрасно понимают когда им говоришь «иди ешь» :) (и по сути это единственный случай когда они добровольно слушаются)

> Так что хреновенько ООП отражает наш способ описания мира.

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

> А соединение с сервером тоже превращается в живое существо, которое может открывать и закрывать себя?

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

Вы говорите про абстракцию, к ООП она ортогональна.

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

И получить, опять же, процедурный код.
> Вы говорите про абстракцию, к ООП она ортогональна.

ООП это и есть абстракция реального мира («реальный мир» здесь далеко не в буквальном смысле).

> И получить, опять же, процедурный код.

O_O, правда? Может быть объясните почему?
O_O, правда? Может быть объясните почему?

Ну вот, пошли по кругу. Если над соединением оперируют внешние к нему методы, чем оно, как объект, отличается от структуры в процедурном программировании?

ООП это и есть абстракция реального мира («реальный мир» здесь далеко не в буквальном смысле).

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

Так оперирование идет не напрямую. Как с тем же котом, говорим человеку «корми кота», передавая ему объект «кот». В методе человек:: кормить идет не просто cat.сытость += 10 (т.е. работа с объектом как со структурой, в процедурном стиле), там естественно дергаются какие-то методы объекта «кот». И таких уровней вложенности может быть хоть сколько: каждый объект умеет что-то делать по внешней «просьбе», отсылая для этого «просьбы» другим объектам (инкапсулированным в него, или переданным как параметры).

Напомню, что изначальная идея ООП даже не в классах и вызове методов, а «программа состоит из объектов, объекты обмениваются сообщениями». Посмотрите на мир вокруг: разве он не состоит из объектов (предметов, систем), обменивающихся сообщениями (поля, излучения)?
В методе человек:: кормить идет не просто cat.сытость += 10 (т.е. работа с объектом как со структурой, в процедурном стиле)

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

Посмотрите на мир вокруг: разве он не состоит из объектов (предметов, систем), обменивающихся сообщениями (поля, излучения)?

А вы посмотрите на тред и удивитесь, сколько есть разных мнений о том, что же такое ООП и как оно отражает мир. И при этом вы первый, кто заговорил о полях и излучениях как о сообщениях.
Статье уже более двух лет, и там же, в коментах, автору давно объяснили моменты, где он «ошибается».
Я всегда знал, что с этим ООП что то не так, оказывается я был прав ))) хорошо в свое время я его не понел
Непонимание никогда не бывает благом.
думаю что тебе написать, но глаза закрываются, ибо устал я сегодня… можно я тебе завтра отвечу на свежую голову ))
После «не понел» можно даже ничего не отвечать =)
UFO just landed and posted this here
Нет, была стандартная головоломка — выделять привычные шаблоны, давно замылившие глаз. И ломать. Думаю, что профессионал бы сделал на порядок красивее.
Гениальные и простые слова — абсолютная истина.
Думаю, большинство программистов, которые застали до ООП период, сейчас в глубине души считают именно так, как сказано в статье, слово в слово. Но вслух сказать все боятся, ибо — тренд, ибо «мы же так этого хотели!, мы же так к этому стремились, сжигая все мосты и занимая все фонарные столбы по дороге!»…
На мой взгляд, слишком радикальные мнения в статье высказаны.
Да, есть плюсы в ООП: возможность группирования данных по смыслу и добавить в языки тонны синтаксического сахара (например, перегрузка операторов и приведение типов).
Но есть и минус — разрекламированные расширенные возможности по повторному использованию кода в ООП на практике редки. Например, если есть проект «хлебопечка» — классы «хлебопечки» и «муки», а мы захотим сделать новый проект «мельница» и использовать класс «мука» из прошлого проекта, скорее всего окажется, что тот класс совсем не то, что нам нужно для этого проекта. Иные свойства, иные методы.

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

Но что придет на смену? Я ожидаю нечто типа «Knowledge Oriented Programming». Работа программиста должна быть сходна с работой скульптура, когда формируем результат, беря заготовку и шлифуя ее добавлением новых знаний о продукте — определений, ограничений, реакций. Я верю, что скоро программирование как таковое будет идти на вполне обычном литературном языке без какого-либо строгого синтаксиса. И несмотря на это, с типизацией рано прощаться — может быть произойдет переход от типизации данных к их классификации, но суть от этого резко не поменяется.
Knowledge oriented — это декларативное. Компьютеру нужны четкие процедуры, возможно с ростом AI и будет так. А по поводу литературных слов, так есть всякие DSL. Он на той же Scala можно DSL писать.
Никто не говорит, что ООП идеальная парадигма, но лучше пока не придумали.

>>Можете ли вы привести хоть один пример из реального мира, что класс — это реальная, физическая сущность? Нет, не думаю.
А кто сказал, что в ООП класс является «физической сущностью»?
но лучше пока не придумали

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

Знать ООП он знает, но видимо не было проектов, где ему он реально бы пригодился. А говоря вот так открыто и категорично, что ООП фигня (самому ведь не приходилось) показывает человека не с хорошей стороны.
Поясните пожалуйста, где автор, видный деятель ООП-сообщества и профессор CS, заявляет, что ООП – фигня?
Мне плевать на ООП, мне плевать на патерны и прочую требуху. Я пишу код так что бы он работал, был понятен и легко модифицировался. А отвечает ли он каким то правилам или нет меня мало волнует.
Когда я учился на мехмате одни студенты пытались выучить все что им давали, а другие ничего не учили но сторались понять суть. Так вот понимание сути делает вас человеком который может все, а заучивание в лучшем случае дает ограниченное понимание, в худшем вы наделаете кучу ошибок.
Краткий пересказ статьи автора, спасибо кэп.
Причем здесь автор? Я вообще то высказывал свое мнение.
У каждого свое мнение. Каждая сторона права, и в тоже время никто не прав. Через некоторое время будут холивары «ООП vs (что-то новое)». Таков Мир.
Лично я не знаю, как бы я проектировал без ООП.
Если бы точно такую же статью написал кто-нибудь другой «неизвестный», то почти все бы проголосавали против (поставили минусы). А комментарии были бы в стиле «Да ты программировать вообще умеешь?» с большим количеством плюсов.
Авторитет имеет значение.
Да, если бы не упоминание Дейкстры, то дальше бы даже не читал… Просто слишком много про ООП говорят те, кому нечего сказать.
Интересно, как выглядит объектно-ориентированная среда разработки, о которой мечтает автор?
Видимо, как Pharo, про которую он написал книгу, или как Seaside, о которой говорится в статье.
Дааа, выглядят они в стиле 90-х годов…
Интересно читать ругательные статьи про ООП.
Сделал я большой проект процедурным методом, и теперь мне в него лезть очень страшно.
С трудом изучал ооп (вот есть в нём один настоящий минус по крайней мере — изучать самому после процедурного подхода тяжело), но когда наконец более-менее разобрался, начал переделывать этот проект на ооп.
Теперь в процедурную реализацию, которая пока работает, лезть по-прежнему страшно. А вот в ооп-реализации даже через несколько месяцев я легко могу вспомнить, где что нужно найти и поменять или как можно что-то добавить. И очень часто я поменяв или добавив что-то достаточно основательное, запускаю — и с удивлением обнаруживаю, что оно работает с первого раза.
То, что проект написанный при помощи ооп, которое я использовал в первый раз, гораздо понятнее и проще в поддержке и обновлении, чем тот процедурный, который казалось бы написан давно знакомым методом — очень сильно меня впечатляет до сих пор.
Для меня главный принцип ооп — разделение обязанностей. Если хорошо продумать круги обязанностей каждого модуля и как можно лучше разделить модули — получается очень здорово. Мне нравится.
Для многих ООП рассматривается как стиль программирования.
Если код в проекте может встретиться единожды и этот код с полной уверенностью больше нигде не пригодится, его все равно «оборачивают» в класс, подобное видел и с функциями.
Если уж нужно ООП то и использовать нужно грамотно.
А не
class HelloWorld { print "hello world"; }
Ну, в C#, например, как попало функцию не кинешь не обернутую в класс.
Прямо про меня история. Тоже получил своего опыта с процедурной разработкой (когда программа на 1-2 тысячи строк становится абсолютно неподдерживаемой). С трудом выучил ООП самостоятельно (ну вот ни разу не просто оказалось). Теперь процедурный стиль вспоминаю как страшный сон.
UFO just landed and posted this here
Поддержу. Запихать в голову функциональное программирование после 10++ лет джавы — не просто.
Во-вторых, что настолько сложного в изучении ООП? Функциональное программирование после императивного — это да, а разнесение функциональности по классам и прочее чем сложно для понимания?


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

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


Можно хоть на ассемблере писать. У всего есть своя цена.

А мне нра. Правда, иногда люди перегибают палку, и лепят классы туда, где намного лучше подходит процедурный стиль, например. Так они привыкли — возможно даже и не знают, что бывает по-другому.
Про Лисп говорят, что в каждой нетривиальной программе содержится (как минимум один) интерпретатор Лиспа. Мне всегда казалось, что к ООП это тоже относится — в каждой написанной на процедурном языке нетривиальной и (успешно) развивающейся программе реализована более или менее развитая самодельная объектная модель.
Согласен. Ядро линукс к примеру хоть и написано на С, но очень многие вещи сделаны в ООП стиле:
структура данных и набор функций оперирующих с ней -> класс и методы
файловая система вообще реализует полиморфизм
«Я не люблю кататься на велосипеде потому, что надо крутить педали.»

«ООП не оправдало наших надежд!»

«Сейчас мы запили ФЯ с аспектами и монадами!»

Какой-то старческий бубнёж. Всех ООП устраивает, а Оскара не устраивает. И что? Отформатировать диск? Или весь интернет сразу? Ведь всё, что есть или является ООП или очень стремиться им стать. Наверное, назло Оскару.
Всех ООП устраивает


откуда такая информация, что «всех» устраивает?
Оскара не устраивает.

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

Меня не устраивает термин ООП. Уже давно, почти с самого начала, это не объектное, а классовое и интерфейсно ориентированное программирование. И парадигма звучит не как «всё есть объект» а как «для всего есть абстракция и контракт». Именно в переходе от объектов к классам происходит смещение крыши у некоторых разработчиков и появляется ощущение пустоты в душе.

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

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

Мир не-ООП вокруг крайне мал. А этот мир создают тысячи вендоров и миллионы разработчиков в жёсткой конкуренции. Сейчас ООП вчистую выигрывает эту конкуренцию, а значит — всех устраивает.
Оскара не устраивает.


Вопрос был не о том ;)

анализа литературы по разработке и аудитории различных конференций


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

Но пока сторонники функциональной парадигмы пишут своё ПО на IDE которое полностью оопэшное и запускают его на осях которые полностью оопэшные.


Есть и обратная сторона медали. ООП-шники используют в своей работе много «вещей» написанных на функциональных языках, например RabbitMQ — используя его вы думаете о меседжинге и очередях, а не о функциональщине и Erlange. Тоже самое и с IDE — какая мне разница на какой технологии она написана и насколько ее создатель разделяет мои взгляды на программирование? (главное чтобы работала). Вопрос ведь не в том, что я использую, а на чем я пишу/хочу писать/люблю писать.

Мир не-ООП вокруг крайне мал.


У меня есть свой взгляд на эту ситуацию (хотя я очень не люблю сравнивать OOP VS. FP и не вижу конструктива в этом). Но… FP — это программирование с точки зрения математики (чем «функциональнее» язык, тем он ближе к формальным математическим законам), FP дает вам «Formal provability» и требует от вас того же. ООП — это программирование с гуманитарной точки зрения — создавай объекты как ты «видишь мир», описывай взаимодействие как ты его «видишь». Эта свобода все облегчает — мне нужно знать формальные законы, которые связывают мои типы данных и их преобразования. Но отсюда и проблемы — imagination меняется с изучением домена, рефакторить не просто, разбираться в чужом коде сложно — это чужой imagination. Отсюда паттерны, соглашения и тд.

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

То, что вы говорите разумно и все это понимают, в частности майкрософт понимает настолько, что даже развивает отдельный функциональный язык для своей платформы F#, правда, одновременно интегрирует принципы фцнкционального программирования и в C# в виде лямды и методов расширения.

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

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

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

Кроме этого я практически не встречал предложений а как же всё-таки надо. Хотя давно известно «критикуешь — предлагай»

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

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

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


Хорошее замечание. Но тут дело снова-таки в распрораненности. Чтобы критиковать технологию нужно хорошо в ней разбираться. ООП-программистов, которые хорошо разбираются в FP и продолжают при этом больше склоняться в сторону ООП, я не знаю. Ни одного. Хотя много пишу на функциональных языках и много общаюсь с «единодумцами». Есть очень известная цитата, не помню кого (к сожалению), «Самая большая проблема изучения ФП в том, что после его изучения сложно смириться с тем, что делают ООП языки».

А поверхностый взгляд на вопрос приводит к критике вида «все это фигня» — что не разумно считать критикой at all.
Кстати, я вообще сомневаюсь, что ФП можно назвать парадигмой в силу минимализма ограничений.

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

Я могу бесконечно критиковать ООП в матлабе.
Во-первых, подобно PHP, вместо того, чтобы взять за основу динамическое ООП типа смолтока, взяли за основу Java. В динамическом языке. Кошмар. Но это к делу не относится.

Есть оптимизационная либа CPLEX с двумя интерфейсами, классическим матлабным и ООП. Вот эквивалентный код.
y = cplexqp(cov(dailyReturns), linearPart, -oneVec, 0, expectedReturn - rf, 1);
Против:
cplex = Cplex('A'); cplex.Model.sense = 'minimize'; cplex.addCols(zeroVec', [], zeroVec', inf * oneVec'); cplex.addRows(0, oneVec, inf); cplex.addRows(1, expectedReturn - rf, 1); cplex.Model.Q = cov(dailyReturns); cplex.Param.qpmethod.Cur = 6; %(1) concurrent algorithm cplex.Param.barrier.crossover.Cur = 1; %(2) enable crossover cplex.solve(); y = cplex.Solution.x;

В реальном скрипте приходится писать по второму варианту из-за строчек (1) и (2) с опциями. Не-ООП интерфейс не полон. Хороший matlab-style код выглядел бы как y = cplexqp(..., ..., cplexoptimset('Crossover', 1)); — так устроен родной генетический оптимизатор, например.

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

1. Функции не нужен конструктор. Когда нужен, он элементарно делается на ФВП. y = @(y)@(x) foo(x, y); Десяток паттернов вида конструктор+метод (от Команды до Абстрактной фабрики) — завуалированные функции.
2. Функции не нужен метод Solve, она по определению что-то делает.
3. Не нужно разбираться, где точки входа и выхода. Если выходов несколько, можно вернуть кортеж.
4. Методы addRows и addCols превращаются в параметры. Если функция выглядит тяжеловесной, умолчания всегда можно на месте упаковать: add5 = @(x) add(x, 5);
5. Параметров у таких функций много, поэтому нужна возможность IDE выдачи названий параметров, а редкие параметры именуются а-ля cplexoptimset('Crossover', 1).

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

Первоклассная функция — это такой ограниченный объект с одним входом и выходом. В отличие от объекта в ООП, эта ограниченность дает возможность функции комбинировать. Я не люблю ФП, потому что не считаю, что отсутствие состояния стоит секса со стеком трансформеров, но сами функции люблю, потому что это простые инженерные коробочки; у каждой всегда ясно, где точка входа, где выход.
К сожалению, я практически ничего не понял из того что вы написали. Это слишком специфические примеры для обсуждения которых требуется хорошее знанием функционального языка.

Кроме того я не спорю, что для ФП есть обширная область применения. Тем более в силу моего увлечения ИИ я постоянно чувствую притяжение тёмной стороны силы со стороны ФП.

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

Я не критикую ФП. Об ООП в инженерных пакетах я имел в виду несколько другое — саму программу, а не математические библиотеки и способы их вызова. Интерфейс, ошибки, потоки, API и т д всё это будет или невозможно или гораздо сложнее без мейнстрима Java или .net

Матлаб не функциональный язык (не функциональнее питона), и к ФП мой пример имеет мало отношения. Что там непонятного — с одной стороны однострочник с понятным входом и выходом (функция же), с другой — долгое и унылое конструирование объекта с вызовом метода solve. В первом случае я прочитал несколько строчек с описанием входных параметров, во втором — туториал, потому что в ООП мире часто не понятно, что за чем вызывать (у объектов нет понятия вход и выход) и доки часто не помогают — не понятно, нафига нужен метод аddCols пока не увидешь, как он используется в туториале.
Об ООП в инженерных пакетах я имел в виду несколько другое — саму программу, а не математические библиотеки и способы их вызова.

Матлаб написан на матлабе и большая часть открытого кода не ООП. Тот же ga выглядит вот так: pastebin.com/zUjJY7qc (лучше не кликать, смотреть нужно последние строчек 30, остальное — проверка входных данных). ga вызывает конкретные функции типа galincon: pastebin.com/0hfHG2Vs
Что в матлабе еще остается? GUI. Да, GUI, наверное, единственное родное применение ООП, не случайно хайп ООП совпал с переходом на графические интерфейсы. Он в матлабе, вроде, написан на яве и тормозной, блин. Исходники закрыты, но открытый клон GNU Octave, например, ООПшен ровно настолько, насколько это минимально возможно в С++ (по типу STL, Степанов свое творение ООП не считает, хотя там везде class да struct и даже наследование иногда)
Я не то чтобы совсем не понял. Я не понял какое отношение этот пример имеет к критике ООП.
Мне кажется, что как первый код так и второй одинаково малопонятны без описания, а первый сильно смахивает на второй только обёрнутый в метод.

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

Я сейчас читаю книгу Степанова «Основы программирования». Читать тяжело очень много математики и упражнения. И мне очень жаль что десять лет назад когда нас учили на ТурбоПаскале, этой книги не было.

1) Степанов считает С++ лучшим языком для программирования, для обучения программированию и в том числе для обучения алгоритмам, — «Мы выбрали язык C++, поскольку в нем механизмы абстракции сочетаются с точным редставлением существующей машины»
2) Степанов в своих статьях явно указывает на недостатки LIST и ФП языков. А ООП считает одной из важных составляющих С++.
3) STL это библиотека универсальных алгоритмов, и поэтому они конечно развязаны с данными, структура и работа с которыми определяются принципами ООП.
Вот цитата Степанова: «Да. STL не является объектно-ориентированным. Я думаю, объектно-ориентированность является почти такой же раздутой фальшивкой (hoax), как и теории искусственного интеллекта.»

STL — это обобщенное программирование, которое в С++ сделано дактайпингом времени компиляции, что дает обобщенность уровня динамических языков с дактайпингом во время выполнения и скорость. Поддержка обобщенного программирования делала С++ уникальным на то время, поэтому у Степанова такое отношение к С++. Сейчас есть D, который я терпеть не могу за повторение истории С++, есть Clay, в котором возможности С++ сочетаются с легким синтаксисом, есть языки с сильным JIT (Julia), которые даже статичности не требуют, а тогда ничего, кроме С++ не было.

Видимо, требуется объяснить, почему STL не ООП. В С++ есть два языка. Допустим, вы ходите реализовать полиморфную формулу. Типа 2*x+y В стиле обобщенного программирования это делается так:
template<class T, class U, class R> R add(T x, U y) {
return 2*x + y;
}

Монстроподобно, но это потому что это С++ с его ужасным синтаксисом, в целом код простой. В Clay, например, он выглядит так
add(x, y) = 2*x + y;


Но семантика одна и та же. На этапе компиляции все типы нам будут известны. Дальше в роль вступает дактайпинг — если существует operator+(X x, Y y) и operator*(int i, X x) просто используем их. Если не существует — компилятор падает. И все. Никаких проблем с диспетчеризацией.

В стиле ООП это делается так:
IAddable add(IAddable x, IAddable y) {
return x.add(y);
}


Стоп, а как нам написать x.add? Функция add на самом деле требует двойную диспетчеризацию, которую не любят в статическом ООП. Если не городить визитор, то вот так:
IAddable X::add(IAddable y) {
return y.addX(2 * x);
}

IAddable Y::add(X x) {
//наконец-то все типы известны и вызываем operator+(X x, Y y)
return (*this) + x;
}

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

У такого метода есть недостаток — сообщения об ошибках компилятора, подобные трейсбекам интерпретатора, рекурсивные и непонятные, и необходимость всей программе быть в одном объектом файле — плагины потребуют перекомпиляции (в С++ еще есть ограничение на статическое разрешение типов, но это не принципиально, в Clay его нет, например)
1) ООП это парадигма программирования реализующая концепции полиморфизма, наследования и инкапсуляции для класов. Всё. Ничего больше, что вы пытаетесь привязать к ООП, им не является. Не надо привязывать парадигму к реализации, какое еще такое «статическое ООП»?

2) С++ это не ООП и конечно не два языка. Потому что ООП это не язык, не подход, не стиль и не шаблон программирования. С++ это язык реализующий парадигму ООП, как и Java, C#, Python, Ruby.

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

4) Опять же не смешивайте парадигму с ее реализацией, STL это не обобщенное программирование, а его реализация с помощью шаболнов и функций. Цитата:
В C++ ООП реализуется посредством виртуальных функций и наследования, а ОП — с помощью шаблонов классов и функций. Тем не менее, суть обеих методологий связана с конкретными технологиями реализации лишь косвенно. Говоря более формально, ООП основано на полиморфизме подтипов, а ОП — на параметрическом полиморфизме. В других языках то и другое может быть реализовано иначе.


5) Обобщенное программирование и шаблоны в С++ не являются неявной типизацией (duck typing). Неявная типизацией обычно называют вид динамической типизации в ОО языках. Естественно что языкам реализующим такую типизацию нет необходимости в шаблонах и строго говоря парадигма обобщенного программирования для них не приемлема.

6) «Поддержка обобщенного программирования делала С++ уникальным на то время».? Да ладно, а как же собственно Ada, a Eiffel. Да и фунциональные языки уже существовали? Или, что, сейчас появилось много новых языков с поддержкой ОП? Кроме Delphi, Java, .NET языков я припомню разве что функциональные Наskel и Scala.
ООП это парадигма программирования реализующая концепции полиморфизма, наследования и инкапсуляции для класов. Всё.

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

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

STL непосредственно связан с реализацией. Ее нельзя сделать на подтипировании — иерархия интерфейсов будет чудовищной и неэффективной.
Обобщенное программирование и шаблоны в С++ не являются неявной типизацией (duck typing).

Вы специально не дочитали? Я пишу: дактайпинг времени компиляции. Гуглите по-английски. Возможно есть термины и получше, мне этот нравится, потому что все проблемы дактайпинга в наличии (необходимость анализа трейсбэка и реализации при ошибках).
«Поддержка обобщенного программирования делала С++ уникальным на то время».? Да ладно

На всем этом тоже не сделаешь STL в том виде, в котором оно есть. У тайпклассов и, тем более, дженериков, есть определенные ограничения.
Из перечисленного специфично для ООП только наследование… полиморфизм на интерфейсах (подтипировании) очень негибкий.

Как вы странно читаете, между строк. Я перечислил вещи которые в CS считаются основой парадигмы ООП, без привязки к реализации. Развитие идей ООП в лице GoF например используют все эти свойства ООП. Вы же начинаете
1) Отрицать принятые в сообществе вещи, что как-то снижает мою оценку адекватности беседы.
2) Опять же переходите к деталями реализации, в виде интерфейсов, которых нет во многих ОО языках, например в Smalltalk или Python.

STL непосредственно связан с реализацией. Ее нельзя сделать на подтипировании — иерархия интерфейсов будет чудовищной и неэффективной.

STL это и есть реализация, основанная на шаблонах и параметрическом полиморфизме.
Конечно ее нельзя перенести на язык без шаблонов.
Можно ли реализовать абстрактные алгоритмы без шаблонов (обобщенного программирования)? Да.
Даже Java и C# делали это без дженериков. С дженериками (а скоро и с лямбдой) это не стало эффективнее, лишь облегчилась запись.
Не надо привязывать парадигму к реализации, какое еще такое «статическое ООП»?
Без дактайпинга.
Не бывает ООП с типизацией, бывает ОО язык с типизацией
Обобщенное программирование и шаблоны в С++ не являются неявной типизацией (duck typing).
Вы специально не дочитали? Я пишу: дактайпинг времени компиляции. Гуглите по-английски. Возможно есть термины и получше, мне этот нравится, потому что все проблемы дактайпинга в наличии (необходимость анализа трейсбэка и реализации при ошибках).
Если какой-то один чудак на Stack Overflow использует неправильное выражение, это не значит что оно становиться термином.
Тем более что выражение а «дактайпинг времени компиляции» вообще логически неграмотно, исходя из определения дактайпинга. Причем не важно определять duck typing как тип динамической типизации, или через duck test.
Да duck typing возможен и некоторых статически языках, вроде C# но учже через дополнительные аннотации. Но в этом случак будет использована уже динамическая типизация.

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

А С++ как был 10 лет назад уникальным языком, так им и остается. И радует, что развивается.
Как вы странно читаете, между строк. Я перечислил вещи которые в CS считаются основой парадигмы ООП, без привязки к реализации.

Напоминаю: «А ООП [Степанов] считает одной из важных составляющих С++.», «STL это библиотека универсальных алгоритмов, и поэтому они конечно развязаны с данными, структура и работа с которыми определяются принципами ООП.».
Мы обсуждали С++, в котором ООП сделано на сабтайпинге. Я в этой нити не писал об ООП вообще. Я вообще ООП два раза упомянул, посмотрите внимательно, в каком контексте.
К в «ООП вообще» у меня свои претензии, которые я описывал в критике ООП-подхода в динамическом языке Matlab, но с вами я этого не обсужал.
Если какой-то один чудак на Stack Overflow использует неправильное выражение, это не значит что оно становиться термином.

Я еще использовал такую фразу, как «язык с сильным JIT». Самое время скопипастить из википедии, что такое JIT и почему он сильным не бывает. Тут даже чудака со stack overflow не будет.
Еще раз, STL это реализация generic алглоритмов на основе шаблонов, как инструмента ОП для С++.

Круто, потому что изначально вы писали «STL это библиотека универсальных алгоритмов, и поэтому они конечно развязаны с данными, структура и работа с которыми определяются принципами ООП.». Это полный бред, потому что Степанов ООП с его принципами крайне недолюбливает и ООП — последнее, что ему нужно в С++.
А С++ как был 10 лет назад уникальным языком, так им и остается.

С++ сейчас не уникален как язык. Наследство уникальное конечно и я из перечисленных языков только на нем деньги зарабатываю, но язык… Есть как минимум D, который я не люблю именно за то, что он все равно С++, а С++ нужно облегчать. ООП, например, выкинуть — сразу столько проблем уходит, типа «нужен мне тут виртуальный деструктор или нет»
Хм, разве «инкапсуляция» и «сокрытие данных» — не одно и то же !?
Нет. Инкапсуляция — объединение внутренностей внутри класса (таким образом, чтобы доступ к этим функциям лежал только через этот класс, и увидеть их можно было только в этом классе). А сокрытие данных — модификаторы доступа к данным (private, protected, public) и прочие механизмы, которые ограничивают доступ (в том числе видимость) к данным.
Странно немного это. Те, кто, к примеру, изучал Delphi, наверняка встречались с понятием «пяти уровней инкапсуляции». Это как раз 5 модификаторов доступа: public, private, protected, automated и published . В большинстве остальных языков таких модификаторов 3( что верно, ведь программисты Borland засунули в Delphi модификаторы automated и published для внутренних нужд самой IDE ). И вообще, в ООП даже нет такого понятия, как «сокрытие данных». Есть 4 основных понятия:
абстракция, полиморфизм, инкапсуляция и наследование
.
published сделан для RTTI, а IDE в свою очередь пользуется RTTI. Но все равно это часть языка
Ничего странного в принципе. Инкапсуляция это один из столпов ООП, т.е. достаточно общее понятие и как раз был бы странно сводить ее к модификаторам доступа (Delphi и его облучающие материалы разумеется не являются авторитетными в вопросах теории ООП). Что касается инпсуляции, то это скорее сокрытие логики реализации. Модификаторы доступа можно считать производным механизмом, применяемым (опционально) в реализации ООП.
Давно мечтаю найти первоисточник того, что добавило абстракция в основные принципы ООП.

P. S. Про automated впервые слышу((
Если для published генерируется RTTI информация, то для automated генерируется запить в библиотеке типов COM.
Automated и Published часто используются при создании своих собственных визуальных UI-компонентов для оболочки-конструктора IDE.
эээ много лет писал на Delphi, потом много лет не писал. Что-то я не помню «automated». Это что-то новое?
Пишу как на C#, в котором без объекта класса даже в консоль не написать «Hello world!», и на на C для микроконтроллеров, когда приходится считать, а влезет ли прошивка в память.

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

Но постоянные отсылки на смолтолк заставляют думать что статья не 2010 а горздо более ранняя.
Смолток обычно упоминается как классическая (чистая) реализация ООП.
Все верно написано и про классы тоже. Большинство программистов пишут классы не задумываясь об объектах. В сущности все верно — классы позволяют разбить программу на модули, а модульная система для сложных процессов самое оно. Однако изначально смысл несколько другой и был реализован этот смысл в SmallTalk. Потом уже появился С с классами С++, и классы стали использовать как неймспейсы фактически, конечно после этого Алан Кей сказал, что это не то о чем он говорил.
Если посмотреть ООП код любой сейчас, то там нет объектов почти, там есть структуры классов, наследования классов, описания классов, интерфейсы и минимум объектов.
В любом случае есть альтернатива в виде функциональных языков и, о боже, там все работает не хуже, чем в системах с классами )
Ну почему же, как неймспейсы используются статические классы или классы со статическими методами. Остальным когда-то суждено испытать на себе силу «new».
feligz имел в виду несколько другое отличие. Если в теории класс представляет собой множество объектов, имеющих схожую семантику и интерфейс, то современные языки программирования зачастую требуют еще и схожей реализации. То есть если есть два объекта одного класса, то их методы при вызове работают по одинаковому алгоритму, отличаюсь лишь внутренним состоянием объекта.

Но так было не всегда. Так, в языке smalltalk было два объекта, относящихся к булевому «классу», и их поведение принципиально различалось. Если переписать это на Java, то получится что-то вроде следующего:
public enum SmalltalkBool {
	FALSE {
		public SmalltalkBool And(SmalltalkBool arg) {
			return FALSE;
		}
		public SmalltalkBool Or(SmalltalkBool arg) {
			return arg;
		}
		public void If(Runnable arg) {
		}
	},
	
	TRUE {
		public SmalltalkBool And(SmalltalkBool arg) {
			return arg;
		}
		public SmalltalkBool Or(SmalltalkBool arg) {
			return TRUE;
		}
		public void If(Runnable arg) {
			arg.run();
		}
	};
	
	public abstract SmalltalkBool And(SmalltalkBool arg);
	public abstract SmalltalkBool Or(SmalltalkBool arg);
	public abstract void If(Runnable arg);
}


Если этот кусок кода проанализировать с точки зрения современных паттернов программирования, то мы увидим три класса — два одиночки (singleton), наследующих общий чисто абстрактный класс. Программист же на smalltalk или теоретик, изучающий модель акторов, увидят здесь два объекта с общим интерфейсом.
«Статические классы» — это противоположность ООП.

Сначала теоретики CS провозгласили «всё есть объект» и придумали ООП; потом практики CS — для удобства реализации — наложили ограничение «любой объект есть экземпляр некого класса»; потом все так сосредоточились на классах, что понятие класса, к которому не относится ни один объект перестало восприниматься как абсурд, и стало привычной частью ООП-языков.
Как объект можно воспринимать и сам класс, в таком случае статические методы становятся методами класса, а статический класс (класс, не имеющий экземпляров) становится реинкарнацией идеи чистого объекта.

Кстати, в Object Pascal принцип «класс — это тоже объект» был реализован в полной мере, отчего в языке появились такие загадочные вещи, как виртуальные статические методы и даже абстрактные конструкторы.
О «виртуальных статических методах» можно подробнее?
Гугл об их существовании ничего не знает, и даже моя больная фантазия их не в состоянии вообразить.
Вообразить нетрудно. Только они не будут отличаться от виртуальных методов объекта, за исключением того, что в них не будет передаваться this (хотя он будет использоваться для выбора конкретного метода). Не знаю, то ли это, о чем идет речь в предыдущем комментарии. Скорее всего, нет, поскольку к принципу «класс это объект» такой механизм отношения не имеет.
Ха, но тогда в чём семантическое отличие от виртуальных методов объекта?
Я как пользователь объекта всё равно должен квалифицировать вызов указанием конкретного экземпляра — и мне снаружи никак не видно, будет ли реализация использовать this, или проигнорирует.
Нет, вызов будет идти из метода конкретного экземпляра. И определяться его типом. Что-нибудь такое:
class A{
  static virtual void F(){ 
    Console.WriteLine("FA"); 
  }
  public void G(){ F(); }
}
class B:A{
  static override void F(){
    Console.WriteLine("FB"); 
  }
}

Тогда new A().G(); напечатает «FA», а new B().G(); — «FB». Никакого this в F не передаётся.
type
  TFoo = class
    class procedure Run(); virtual;
  end;
  TBar = class(TFoo)
    class procedure Run(); override;
  end;

...

var
  tfoo : class of TFoo;
begin
  tfoo := TBar;
  tfoo.Run(); // Вызывается TBar.Run()
end;


Могу и соврать, поскольку давно уже не писал ничего на Delphi, но манипуляции с метаклассами видел неоднократно.
А этот механизм позволял создавать классы «на лету»?
Новые классы — не позволял создавать.
Позволял создавать объекты неизвестного во время компиляции класса, по «ссылке на класс».
“Си позволяет легко выстрелить себе в ногу; с C++ это сделать сложнее, но, когда вы это делаете, вы отстреливаете себе ногу целиком.”
— Отстрелите себе голову. И больше не говорите загадками.

“Я придумал термин ‘объектно-ориентированный’, и вот что я вам скажу: я не имел в виду C++.” — Алан Кей.
— А зря!..

“В C++ всего 2 вещи получились не так: начальный замысел и реализация.” — Бертран Мейер
— Зря, Скотт Мейерс был иного мнения.

“Внутри С++ сидит более компактный и понятный язык, отчаянно пытающийся выбраться наружу.” — Бьерн Страуструп
— Ииии?

“C++ — это история, повторяющаяся как трагедия. Java — это история, повторяющаяся как фарс.” — Скотт МакКей
— Трагедия — это объектно-ориентированный PHP. Перечисленное — не трагедия.

“Java, лучший аргумент за SmallTalk после C++.” — Фрэнк Винклер
— Скажите это разработчикам на C.

“Если бы у Java был настоящий сборщик мусора, большинство программ удаляли бы себя во время исполнения.” — Роберт Сьюэл
— Если бы у бабушки был х… А что случилось со сборщиком мусора у Java? Куда делся? А?..

“Есть всего 2 типа языков: те, на которые все жалуются и те, которыми никто не пользуется.” — Бьерн Страуструп
— И чо?..

Классы существуют только в нашем сознании. Можете ли вы привести хоть один пример из реального мира, что класс — это реальная, физическая сущность? Нет, не думаю.
— Object в Java, QApplication, QWidget, CDialog и т.п. Нет, ни о чём не говорит? Понятно, что если сразу начинать с Гамма, Хелм, Джамса и Влиссидеса, то понять ничего невозможно.

Вы когда-нибудь задумывались, почему программу на объектно-ориентированном языке понять настолько сложнее, чем на процедурном?
— Частенько. Нет, утверждение не верно.

В процедурных программах процедуры вызывают другие процедуры. Процедурный код показывает… процедуры, вызывающие другие процедуры. Все хорошо и просто, так ведь?
— А в классах функции класса обращаются к функциям другого класса. Всё также хорошо и просто. Так ведь?

В объектно-ориентированных программах объекты посылают сообщения другим объектам.
— Это ооооочень поверхностное увтерждение… к тому же неверное для общего случая…

Я думаю, поэтому SmallTalk’еры так любят программировать в дебаггере
— Странно, я всё время считал (по наускиванию Стива МакКонелла), что если человек пытется разрабатывать с помощью отладчика, то он ни черта не соображает в своём собственном коде.

дайте нам IDE, которая будет показывать объекты вместо классов!
— А приложение вам не дать с единственным диалоговым окошком «Сделать хорошо? Да и Да-да-да».

но при этом часами пытаемся понять, какие именно строчки нужно написать!
— Поправка! ВЫ пытаетесь часами понять, какие именно строчки нужно писать.

Одна из причин, почему мы тратим столько времени, в том, что нам приходится листать код туда-сюда… через множество маленьких методов.
— Вы же только что их предлагали?..

Предлагаю вам, однако, назвать хоть один механизм в языках программирования, который поддерживает изменчивость.
— Мда…

не код должен генерироваться из модели — модель должна быть кодом.
— Легко! Только это будет вполне замечательная модель, из которой генерируется отвратительный код. И наоборот. Это уже сто лет как доступно. Вы не знали?

но мы все еще не овладели этим
— Рад, что вы это поняли.

ЗЫ: Автор! А оно того вообще стоило? Я понимаю: человек профессор, автор 202 публикаций и т.п… Но это ведь не даёт право такую фигню нести на уважаемом ресурсе…
А я уже почти два года программирую на node.js и забыл про ООП. К сожалению, и CoffeeScript, хоть и содержит в синтаксисе некоторый сахар, все же агитирует к использованию ООП. Видимо, я один такой люблю классическу js. Может быть, комментарий не совсем сходится с топиком, но все же всегда есть способ как обойтись без ООП, и часто этот способ будет проще даже для собственного понимания, чем результаты подгонов кода под парадигмы.
Не хочу вас расстраивать, но не могу не заметить, что javascript и его производные — объектно-ориентированные языки
Яваскрипт не является объекто-ориентированным языком, не смотря на наличе типа Object. Кофескрипт, с одной стороны, пытется эмулировать классы, а с другой, мимикрирует под Окамл или Хаскел.
Яваскрипт не является объекто-ориентированным языком

С чего вы взяли?
Ну… в этой ситуации… мы… просто наше… это самое… мы уже… здесь наше полномочия всё. окончено.
Вроде ясно что автору не нравится ООП, но из статьи не понятно — а что он считает лучше? Процедурное программирование? Или логическое? В последнее время такие статьи растут как грибы после дождя: стало модно объявить что ООП не справляется с ожиданиями, которые были возложены на него лет так 40 назад, поэтому давайте его обхаем. Хотелось бы конкретных примеров: например, пусть автор представит аналог скажем VCL без ООП? Как спроектировать и реализовать подобного объема архитектуру, есть рецепт? Ну или все мы знаем PHP — огромный массив разрозненных функций. Одних только с префиксом array_ несколько десятков. Было бы неудобнее, если бы их все реализовывал объект? Чем неудобнее? Мне кажется чаще бывает наоборот: ООП не хватает там, где бы он мог облегчить жизнь.
Как заметили выше, от того что писать obj.func() вместо func(obj) суть не меняется.
Кстати говоря, хорошее и тонкое замечание, которое развеивает миф о том, что ООП — «зло». Вы привели примеры того, где как раз без ОО не обойтись. И про PHP вы все сказали верно — было бы гораздо удобнее пользоваться классами в отдельно взятых случаях.
UFO just landed and posted this here
Много «ученых» пишут статьи и книги просто ради самих статей и книг, и автор явно из их числа. В отличие от статьи получил удовольствие от чтения большинства комментов. Много думающих и размышляющих, но мы разобщены, а энти «ученые» нет.

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

Следствия.
Из 1 пункта, следует, что основное направление для ООП это создание библиотек (возможно неявно внутри программы), которыми удобно пользоваться. Для маленьких программ и библиотек это часто бессмысленно, поэтому и возникают дискуссии «про баян и козу» как стороны начинающих, так и со стороны «маститых», но не практикующих ученых.
Из 2 пункта, приходит понимание, что дискуссии о том какой язык лучше для ООП со статической типизацией али с «утинной» и про всякие тонкости с множественным наследованием и перегрузкой просто бессмысленны. Если на практике большие задачи решаются значит, так можно и спор уместен только про нюансы, как сделать это еще лучше.
Бывают, конечно, случаи более сложные, но значительно реже. Это про автора оригинальной статьи.
А шутка про сборщик мусора Java меня покорила.
Раз так искрометно завидуют Java, значит не зря я на нем пишу :)
Насчёт типов — страшнейшая ахинея. Типы — это ограничения, которые накладываются на интерпретацию данных по указанному адресу (в памяти). Не хотите типов? void* на Си, и сами разбирайтесь, инт это или char*.
Просто у него была задача раскритиковать «10 вещей», и пройтись по главным, известным вещам, а не мелочам типа огромных цепочек наследования и обилия классов, которые упоминают практики-комментаторы.
Недолюбливаю ООП, но статья — бред
Жаль, что автор ничего не сказал про композицию vs наследование. Как уже не раз писалось практиками: многие просто слишком увлекаются наследованием в ущерб композиции. Вот это действительно может дать слишком запутанный код.
Похоже на троллинг, слишком частные ситуации, слишком удобные высказывания. Для каждого абзаца можно написать абзац в опровержение.
Ненавижу слово ненавижу, такое чуйство что дяденьку ктото заставляет объекты писать. Детский сад какой то.
Не нравятся плюсы, пиши на чистом си.
Хочешь быть ближе к природе, пиши на ассемблере или в машинных кодах в хекс редакторе.

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

Мне не нравиться в си инкримент указателей, я считаю что указатель это адрес, а значит должен увеличиваться на 1 а не на размер типа на который указывает указатель, но блин это не повод писать статьи и намекать всем что надо менять язык программирования. Ведь если немного подумать это выбор из двух зол, благодаря которому указатель можно интерпретировать как массив. А уж если сильно прибило то используй (char*).
Хотя есть и минус, безтиповый указатель (void) не имеет инкримента, что немного раздражает, так как нет типа явно говорящего, что его размер 1 байт.

Автор к сожалению думать не любит =(
безтиповый указатель (void) не имеет инкримента

stackoverflow.com/questions/3523145/pointer-arithmetic-for-void-pointer-in-c
incrementing/decrementing a void* pointer, is a valid expression in C (but not in C++).

In the C standard (N1256 draft):
6.2.5-27: A pointer to void shall have the same representation and alignment requirements as a pointer to a character type.
Проблема ООП-языков — в навязывании этого самого ООП. Почему в C# нельзя написать hello world без класса, просто засунув main в глобальный неймспейс? Почему single dispatch прибит гвоздями к наследованию (а multiple dispatch вообще нету)? Почему сокрытие данных приделано к классу?

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

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

Потому, что когда провозглашают «There's more than one way to do it», то получается Perl, знаменитый тем, что программам на нём не нужен обфускатор: каждый программист выбирает свой набор методик, и любые два Perl-программиста пишут в действительности на разных языках.
Потому что уменьшается количество сущностей. Можно было бы сделать глобальный неймспейс классом, подобно Ruby, но это сахар. А вот неймспейсы а-ля С++ — лишняя сущность, учитывая первоклассность классов.
А js вообще динамический язык.
До сих пор не могу понять сторонников процедурного программирования, потому что необходим ответ на вопрос.

Допустим у нас есть солушн на 50 проектов, в среднем в проекте 50 классов, в классе в среднем 5 методов — в итоге получается 12500 методов. А теперь перепишем все это в процедурном стиле — получим 12500 функций без классов и неймспейсов в глобальной области видимости.

В итоге, вместо однообразных методов Create в классах File, FileInfo и т. д., мы получим сотню функций CreateFile, CreateFileInfo и т. д. (и это еще самые простые названия, пользовательские подлиннее будут), которые засорят вывод intellisense.

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

В общем, есть и другие вопросы, но я не встречал вживую ни одного приверженца процедурного программирования, поэтому обсудить не с кем)
UFO just landed and posted this here
А что насчет intellisense и хранения функций в файлах — по какому принципу их компонуют?
UFO just landed and posted this here
Не знал, что бы еще предложить кроме первого варианта. Потому и спросил, а то первый вариант выглядит как зачаток ООП. Остается то, что в файле, обернуть в статический класс, и уже становится легче. Это как писать на js функции инлайном и принадлежащие window, или вынести все в отдельный файл и обернуть в объект.
UFO just landed and posted this here
WinAPI вообще-то объектно-ориентирован, там есть методы типа CloseHandle и вроде даже наследование (кто-то приводил пример в предыдущем ООП-сраче).
Он просто сделан с сишной мордой из-за совместимости и очень хреново сделан, надо сказать, по сравнению с тем же POSIX, который намного более классически устроен.
Если точнее, то объектно-ориентированным является GUI с его оконными классами, здесь в роли «методов» выступают оконные сообщения. Поскольку функция-диспетчер оконных сообщений для конкретного оконного класса находится под полным контролем программиста, вполне можно устроить «наследование» одного класса от другого через агрегирование.

Я даже как-то развлекался, и писал обертку на С++ над оконным API, которая позволяла преобразовать оконный класс в обычный или наоборот (правда, до конца не дописал). Выглядела не страшнее ATL.

Другое дело, что извращаться подобным образом имело смысл лишь на Windows 95/98/ME, поскольку при изолированных друг от друга процессах зарегистрировать свой оконный класс глобально не получится, а в пределах одного процесса имеется много более красивых способов коммуникации (если брать ООП, то тот же COM более прозрачным образов ложится на языки программирования).
Ну, на Паскале, когда он еще был процедурным языком, в качестве namespace могло использовалось имя модуля, так что все не так страшно.
К тому и веду, что в итоге все равно какое-то подобие неймспейсов приходится применять, все-таки с ними удобнее, или есть другое решение?
Почему вы считаете, что при написании в процедурном стиле не должны применяться никакие приемы организации функций по назначению? Где сказано, что надо все валить в одну кучу, что в процедурном языке не должно быть модулей или неймспейсов?

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

Все равно, когда начинаешь избавляться от неудобств процедурного стиля в итоге приходишь к ООП.
приемы построения архитектуры программы, и будем иметь только «процедурное программирование с приемами».
Вот, пошли «шаблоны проектирования» и прочие «приёмы проектирования» вкупе с книжкой «Как эффективно писать на С++» издания 1998 года. Чем плохи «шаблоны» и «приёмы» — что им можно не следовать. Когда же они «отлиты в гранит синтаксис», то попытки не следовать им будут отсекаться на ранней стадии компилятором.
Настоящий программист может написать программу на Фортране на любом языке! :D
существует очень тонкая грань между хорошо организованным процедурным кодом и плохо организованным ООП.
Т.е. вы утверждаете/признаёте, что даже плохо организованный ООП-код находится на, в общем, хорошем уровне организации по меркам процедурного кода?
С точки зрения организации — наверное. Я вообще сторонник объектно-ориентированного подхода.

Однако тут есть 2 момента:
Во-первых, когда я говорю про ОО-код, я имею в виду именно парадигму, а не язык. Есть много примеров кода на С++, который не является ОО вообще. И есть примеры кода на С, которые, наверное, можно считать написанными с испоьзованием ООП.
Во-вторых, плохой код, обычно, плох во всем. Я бы претпочел рабоать с хорошим процедурным кодом, чем с полхим объектно-ориентированным.
Ни одна парадигма не является панацеей точно также как и не умело следуя парадигме можно писать трудно поддерживаемый код. Обсуждать это и холиварить бесполезно все зависит от типов мышления команды, которая данный код разрабатывает. Никто и никогда не заставит функциональщика писать в объектном стиле и наоборот. Потому как данные люди слепо следуют описанным правилам игры (парадигмам).
Если в проекте бездумно используют парадигмы только из слов крутости — это ставит под сомнение профпригодность команды. Любая парадигма либо методология это по факту банальная рекомендация по организации кода внутри вашей команды. Выбирайте то, что вам близко и что все одинаково понимают. Если в процессе работы над проектом перестает устраивать организация кода, становится запутанным для понимания — рефакторите его так, как считаете нужным исходя из выбранной парадигмы.
Главная проблема в ООП — переоценка парадигмы программистами. Сначала изучают ООП в поисках серебряной пули, а потом обижаются, не найдя искомого…

Все остальные проблемы ООП решаемы.
Когда я читаю подобные статьи, мне кажется, что они написаны наоборот, не против, а за ООП (C++, etc.) и направлены только на то, чтобы программисты прокачивлали свои скиллы и не делали глупостей, которые могу сводить на нет плюсы технологии
в общем-то, параграф «об авторе» это и подтверждает.
Автор типичный теоретик программирования. Я бы посоветовал бы ему больше писать реальные проекты, а не писать подобный бред. Пусть попробует написать бизнес-логику крупного проекта на процедурном или функциональном языке, я потом погляжу на его код.
И что, вы посмотрите, дальше?
Если для вас ООП парадигма является более понятной, чем функциональная это не значит, что последнее плохо.
По сути, без претензий и холиваров, чем инструкции:

class A { function b():String { return 'Hello world'; } }
function A_b():String { return 'Hello world'; }

A a = new A();
A.b();

A_b();

отличаются друг от друга?
Тем, что в первом случае вы написали точку, а во втором нет?
Это всего лишь _способ_ группирования данных / логики. На вкус и цвет все фломастеры разные. Поэтому одна группа людей будет предпочитать выделить память, инициализировать объект — другая вызвать эту же функцию. Да в первом случае у вас будет контест по умолчанию (this) во втором вам его придется _явно_ передавать в _каждую_ функцию. Чисто визуально на этом различия заканчиваются. Далее все зависит от рук человека, который будет этот код писать. Ибо, что в классах вы можете написать бред запутав свою программу:

class A {

protected SomeClass someClass;

function b():void { this.c(); /* что-то ещё */ this.f(); }
function c():void { this.f(); /* что-то ещё */ someClass.a(); }
function d():void { }
function f():void { someClass.d(); }

}

что в функциях. Ни с ООП, ни без него вы не застрахованны в том, что ваш код будет «понятным» кому-то ещё кроме вас.
Э-э! Уважаемый! А теперь в классе появляются данные!..
… а потом виртуальные методы. А потом совершенно искусственное ограничение, что run-time override возможен только по «нулевому» аргументу, и все остальные варианты должны выражаться через него — ограничение, возникшее, вероятно, потому, что «так было удобно, получилось эффективно реализовать, и в 99.7% такого механизма хватает». А почему хватает? Потому, что альтернативы нет, была бы — ей бы активно пользовались. А потом — ограничение, что менять виртуальный метод объекта во время его жизни нельзя, даже если очень надо…
Ну, ограничение не совсем искусственное. Дело в том, что если критичные аргумент всего один — то его всегда можно сделать нулевым.

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

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

ps: прошу заметить, что я не наезжаю на ООП и не защищаю функциональщину и прекрасно понимаю преимущества, а также недостатки данных парадигм;
Не уверен, что с ограничениями не нужно бороться. В любом случае, надо уметь видеть, что «вот здесь есть ограничение», понимать, на каком этапе выбора/разработки парадигмы оно возникло, и принимать решение — смириться, или сделать шаг назад в выборе парадигмы, или посмотреть, как это ограничение обходили раньше (до того, как оно возникло) и учесть эту информацию. Не могу поменять виртуальный метод? Хорошо, положу функциональный объект в поле своего объекта, и буду вызывать его. Виртуальные методы работают медленно из-за двойного обращения к памяти? Вспомним, как виртуальные функции реализовывались на C и запишем табличку прямо в объект. Заодно и поменять сможем при необходимости. Язык не даёт добавить метод в существующий объект? Узнаем, как это делали в тех языках, где такая возможность была… и пожелаем удачи тем, кто потом будет разбираться в нашем коде.
М-м, а если посмотреть на Python?
Там все методы виртуальные и менять можно когда угодно и что угодно.
Как в общем и в Ruby.
Если использование этих языков в конкретной ситуации допустимо, то это тоже возможный вариант.
Вспомнились фразы:
Вам не нравятся кошки? Да Вы просто не умеете их готовить (с)
«Ubuntu» is an ancient african word meant «I can't configure Slackware» ©
Ubuntu тут не при чем, однако смысл сходен.
Что касается IDE — так это он IDEA поверх Java не видел :)
Раздел «Немного об авторе» — 3 абзаца регалий и книг, и ни одного слова про реально разработанный софт (я не исключаю, что он есть, заметьте) — отлично подытожил мое впечатление о статье.
Так где же идеальный неООП-код от автора оригинала? Или хоть какой-то код… Всё голословно.
А чем генетический код не пример реализации ооп?
Смысле — автор спрашивал примеров классов в физической реальности. Дык — вот оно. Мы с моим котом, например, деррайвд от общего прототипа, и это можно проследить в наших с ним днк.

Даже TObject есть, биологи зовут его LUCA
А чем генетический код не пример реализации ооп?


Природа как и некоторые программисты, видимо, тоже переборщила с использованием ООП при создании живых организмов. Поэтому все они далеки от совершенства. Мутации, частые нарушения генетического кода — дурной пример использования ООП…
Для ФП придётся удалить всех существ и передавать их в мир в момент какого-то действия над ними.
Факт.
У программистов есть уникальная возможность посмотреть на что могла бы быть похожа их cpp программа через миллиард лет, если предоставить её самой себе…
Вот, кстати, не надо! Такой отказоустойчивости и способности работать даже при повреждении кода, нам, программистам, остается только позавидовать.
Статья вызвала бурные обсуждения, как перевод, так и оригинал. Все, что хотел сказать автор: «ООП — не панаценя». Сделал он это конечно не традиционным способом, но благодаря Холивару в итоге донес до большего числа людей. Респект ;)
Я ещё автор хотел сказать, что он хреновый практик.
Не пойму, почему (почти?) все воспринимают эту статью как негативную по отношению к объектному программированию?

Из-за слова «ненавижу»? Так, там рядом стоит «временами».

Из-за критики парадигмы? Но ее действительно не существует в том смысле, что нет единого мнения о том, что же это такое. Впрочем, мне кажется, это больше дискредитирует современное ИТ-сообщество (да и вообще людское общество), нежели саму идею объектности. …И сам термин ООП настолько заляпали грязными ручонками, что вот я, к примеру, стараюсь его максимально избегать. Да и изначально присутствие слова «ориентированный» не обещает ничего хорошего…

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

И, кстати, автор статьи — довольно известный Smalltalker.
И, кстати, автор статьи — довольно известный Smalltalker.

А заметно, что автор — динамический. Только у любители динамики могут написать то, что описано в «5. Типы»
Читаю комментарии и горько плачу.
Плачу от того, как легко некоторые гуманоиды опускают состоявшегося профессионала, перечень заслуг которого занимает в этой статье 12 строк.
При этом есть подозрение, что если все гуманоиды скинуться достижениями, то 12 строк не наберется.
Но убивает даже не это, а то что с легкой руки вместе с Оскаром по раздачу пускают:
Эдсгера Дейкстра;
Бьерна Страуструпа;
Алана Кея;
Бертрана Мейера;
Адель Голдберг;
Роберта Галагера;
Кента Бэка;
Скотта МакКейя;
Роберта Сьюэла;
Фрэнка Винклера и прочих.
Т.е. всех тех, кто жопу порвал на ниве программирования в общем и ООП в частности, чтобы оно было хотя бы таким, каким вы его сейчас видите и имеете счастье пользовать.
И после этого вы говорите что: «теоретик, мало практики, бредятина!».
Вы кому это говорите? Всем тем, кто ЭТО придумал?!

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


Узок их круг, страшно далеки они от народа… (с)

Почему бы народу, в самом деле, не посчитать себя пользователями их продукта? И не бросить им те же помидоры, которые летят в них самих от их пользователей со словами «да, вы написали эту программу. Но какой у вас опыт в её эксплуатации? Нулевой. Вот поработайте на своей программе с наше, тогда и можете писать об её преимуществах и недостатках. А пока вы для нас… теоретики.»

Это одна возможная интерпретация позиции «критиков». Есть и другая:
Статья, очевидно, в большой степени идёт под неявным тегом «сарказм». Так почему же нельзя обозвать её автора «теоретиком», заключив свои возражения в тот же неявный тег? Не думаете же вы, что те, кто ругает статью, в самом деле так считают?

[режим адвоката дьявола OFF]
Причём здесь авторитет товарищей, перечисленных в топике, если их единичные фразы по сути вырваны из контекста?
Что касается автора статьи, то он не прав в том, что выдаёт желаемое за действительное и пытается убедить весь мир, что чёрное и шершавое — суть одно и то же.
ООП никто не выдаёт за решение всех проблем, просто с использованием ООП почти всё пишут, а из ФП более-менее на практике применяется только Erlang. Процедурный подход и то более популярен — язык Си.
Вой о том как перейти на ФП всему миру сродни построению коммунизма.
Вывод: Оскар — тролль 80го уровня. Ну красавец-же!
Не, ну вот учил-учил Вася паттерны, сидел — смотрел как тимлид ловко раскладывает задачу на классы и выделяет связи и методы. Он конечно многого не понимал, и в подсознании постоянно крутилась мысль «на**… фига?», но он гнал эту богомерзкую мысль проч.

В конечном счете он перестал видеть в задачах — ЗАДАЧИ, он стал видеть в них классы, шаблоны. На него снизошла ООП-благодать. Он использовал ООП везде где только мог, даже в прикладных утилитах, о которых никто никогда не вспомнит и которые решали задачу 2+2. Он тешил себя ВЕЛИКОЙ мыслью, что «мой код такой гибкий, что я могу сложить сферического коня с квадратом малевича». Он накладывал шаблоны, добавлял 10-ый уровень абстракции, и 5-ый интерпретации. ОН — гуру ООП!
А вы тут приводите какие то противные мысли непонятных людей. Вася не согласен. Он теперь тимлид и завтра на новом собеседовании обязательно спросит с кандидата все 100500 паттернов…
Хабраюзер Петр Хренов — ветеран ООП, заколенный в боях морской волк, пришел домой из офиса и зашел на хабру. Увидел «ругательную статью» про ООП, пробежался по тексту и смекнул «наших бьют, обижают няшные кресты, наверное фукнциональщик или прохфессур оторваный от действительности и вообще». Включил цундеру и начал истерить: «Бака, бака, кресты самые лучшие, лучше них нету и не нужно, больше практикуй и будешь как я, сможешь сесть в офисе рядом со мной, и тогда ты поймешь, поймешь всё». А мог бы программы писать.
Насчет минусов ООП вспоминается одна цитата: «Пессимист видит трудности в любой возможности, оптимист видит возможности в любой трудности» (с) Уинстон Черчиль.
Полагаю, налицо индивидуальная непереносимость объектно-ориентированного подхода. Что ж, на то у нас имеется море других парадигм.
Да, статью следовало бы обрамить тегом \<sarcasm\>. Я по началу принял статью за чистую монету…

Автор (Оскар, я имею ввиду) говорит о том, что ни парадигмы ни паттерны не имеют никакого значения сами по себе. Они нужны для того, чтобы код был эффективным, простым и понятным.
Если ваш код не такой, всё что вы говорили и писали — мусор…
Да, статью следовало бы обрамить тегом \<sarcasm\>

не не. Надо было выделить метод -> гетСмысл(сарказм=правда)
Уже давно заметил, что писать НА ооп значительно проще, чем писать О ооп.
Читнул тут наконец, недавно, после большой рекламы, МакКонелла про «совершенный код». Нашёл подтверждения своим давним подозрениям, что ООП — это всего лишь хороший способ организации и упаковки (в том числе и повторного использования) кода. Чтоб «в одну харю менеджить в десять раз больше функциональности». И так, чтобы, при неизбежных изменениях кода из-за меняющихся требований, его надёжность и предсказуемость сохранялась по максимуму.
Sign up to leave a comment.

Articles

Change theme settings