Когда я, так сказать, прошёлся по Интернету, я заметил одну интересную особенность. Все парадигмы программирования, где-либо обсуждаемые, воспринимаются людьми совершенно спокойно. Если, например, говорят про процедурное программирование, то говорят про него абсолютно спокойно. То же самое — про модульное программирование. Декларативное программирование — никаких бурь, волнений или холиваров. Функциональное программирование — то же самое.

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

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

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

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

1. Всё, что есть в ООП, уже давно есть в других парадигмах


Почти все языки программирования являются тьюринг-полными, за исключением языков разметок, как то: HTML, XML, CSS и т.д. Если говорить крестьянским языком, тьюринг-полный язык — язык, на котором можно написать абсолютно любую мыслимую программу. Из этого следует довольно-таки всеобщий тезис: то, что есть в любом наудачу выбранном языке, есть во всех остальных языках. То же можно сказать и про парадигмы. Все отличия языков (и парадигм) — это разные способы реализации тех или иных команд, не считая отдельных лексических особенностей.

Кстати, этот же тезис (всё, что есть в N, есть и в M, и в K, и в R и т.д.) можно сформулировать так: молоток уже состоит из железа да дерева, зачем же нам ещё и пассатижи? Но ведь так никто не станет утверждать.

2. ООП смешивает данные и действия над ними. Это плохо


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

3. Наследование закрепощает программу, делает трудным внесение изменений


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

Если не предполагается расширять родительский класс третьим классом — такое наследование попросту бессмысленно. Если вы создаёте магазин спиртных напитков, то классы Beer, Vodka и Vine можно унаследовать от класса Alcohol, но совершенно не нужно создавать ещё и класс Drinks, если только вы не хотите продавать ещё и, скажем, парагвайский чай.

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

4. Инкапсуляция не имеет смысла


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

Но это верно лишь чисто технически. Философия ООП гласит: правильно организованный и инкапсулированный класс можно рассматривать как чёрный ящик. Представьте себе коробку, на одной стороне которой разнообразные кнопки, слоты для подачи данных, а на другой — выходной слот, который возвращает информацию. Возьмём, к примеру, стек. Представьте коробку, на одной стороне которой есть один слот для вставки данных и кнопка push рядышком. На обратной стороне — кнопка pop. Вы подаёте туда записку с числом 8 и давите кнопку push. Затем подаёте ещё бумажку и второй раз давите push. И так N раз, а затем жмёте pop. Из ящика вылетает бумажка с числом 76 (или другое, в общем, то, которое вы подали). Нужно ещё число? Второй раз давите pop. И так до морковкина заговенья тех пор, пока ящик не опустеет. А если вы продолжите давить pop, механизм из ящика завоет: стек пуст! Именно так и выглядит объект.

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

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

Хотя, вряд ли это «увы» здесь вообще уместно.

5. В реальном мире нет иерархий отношения, повсюду лишь иерархии включения


Да разве? Но ведь никто не мешает создать, например, иерархию, где все реки мира (Конго, Сена, Темза, Амазонка, Колыма и т.д.) являются объектами одной всеобъемлющей «Реки», которой присущи свойства (например, состоит из воды) и действия (например, течёт), а уже она будет наследоваться от «Водоёма», который тоже состоит из воды, а от «Водоёма» можно унаследовать ещё и «Озеро», объектами которого будут отдельные озёра (Байкал, Каспийское море, Титикака и т.д.). Схема довольно грубая. Но иерархии отношения — это тоже абстракция. Что-то а-ля платоновской идеи, если хотите. В реальном мире их нет, они существуют только в уме, это обобщение, и не более того. Но ведь именно так человек очень часто мыслит. Мы ведь можем сказать «носок», без уточнения, каков у него цвет, из какого материала соткан и т.д., но существует ли этот «носок» в действительности?

И всё же нас не должно смущать, что нет ни «объекта», ни «носка».

6. Методология ООП изначально ошибочна


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

7. Но даже миллионы мух не убедят нас, что навоз — это вкусно


Самый популярный аргумент против ООП. Мол, массы в большинстве своём глупы (всё же я не думаю, что это относится и к программистам), бегают по «модным шмоткам» и восхищаются ими.
Но задумайтесь, а если бы на пьедестал взошло не ООП, а, скажем, ЛП? Думаете, было бы всё по-другому? Ничего подобного! Нашлись бы и фанаты, и злостные противники, а на ООП смотрели бы как на инструмент (к этому я, вообще-то, и призываю), а не как на таблетку, сотворённую самим Богом и потому незаменимую.



Почему эта статья — в защиту ООП?


Все современные разговоры про парадигмы программирования, как мне видится, сводятся к двум диаметральным посылкам: оставим ООП и выкинем всё остальное, или же выкинем ООП и… ну, вы поняли меня.

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

Если вам не нравится ООП


Кому — ООП, кому — ФП, кому — ПП. А кому-нибудь, может быть, вообще более всего мил свиной хрящик. Если вы не любите кошек — наверное, вы просто не умеете их готовить.

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


  1. JSmitty
    25.07.2018 09:42
    +1

    Одна из существенных проблем ООП, кмк, — реализация операций. То есть на классическую парадигму оно очень плохо ложится. Сложение чисел или конкатенация — тому яркий пример: objA.plus(objB) или objB.plus(objA)? (я в курсе про хелперы, но их существование не укладывается в классическую парадигму).

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

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

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


    1. dvmedvedev
      25.07.2018 10:11

      Реализация операций не зависит от ООП и в некоторых языках решается перегрузкой операторов.


      1. mayorovp
        25.07.2018 10:33
        -1

        Проблема тут не в реализации, а в том как обеспечить полиморфизм.


        1. dvmedvedev
          25.07.2018 10:37

          Наверное, все-таки разговор про иммутабельность?


          1. mayorovp
            25.07.2018 15:03

            В первом абзаце — нет, не про иммутабельность.


            1. igor_suhorukov
              26.07.2018 00:07

              Тсс, а то Егор Бугаенко с адептами набегут!


    1. adeptoleg
      25.07.2018 10:40
      +2

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


    1. thatsme
      25.07.2018 11:03

      тому яркий пример: objA.plus(objB) или objB.plus(objA)? (я в курсе про хелперы, но их существование не укладывается в классическую парадигму).

      Не совсем понимаю где проблема.


      std::string a("123");
      std::string b("444");
      const std::string a{"123123"};
      
      std::string c{a+b};
      std::string d{b+a};
      
      a+=aa;
      
      aa+="xxx"; // compiler throws an error here

      По моему всё семантически чётко и ясно. Или всё-таки где-то проблемы?


      1. thatsme
        25.07.2018 12:56

        >>const std::string a{«123123»};

        должно быть
        const std::string aa{«123123»};


      1. qw1
        25.07.2018 13:41

        Что делать, если мне часто нужно переворачивать строку?
        Писать метод в функциональном стиле

        std::string reverse(const std::string& src);

        или в процедурном
        void reverse(std::string& str);

        Но в ООП это никак не заходит.


        1. thatsme
          25.07.2018 16:49

          Угу опять вопрос мутабельности. Это холивар. А утилитарно всё зависит от цели:


          1. std::reverse() — swap
          2. std::string::rbegin() — реверсный итератор
          3. std::string::crbegin — константный реверсный итератор

          Вы действительно считаете, что эта проблема "буриданова осла", кого-то остановит от желания программировать на C++ или в ООП парадигме в целом? Дать право программисту выбрать длительность жизненного цикла объекта и доступа к нему, или отобрать? Совсем! Чтоб неповадно было.


          Вопрос выбора инструмента, дело каждого конкретного программиста. Всё это вкусовщина. Небо наземлю не упадёт если объекты будут mutable.


          Вот вам гениальный пример для батхёрта (пусть стошнит каждого функциональщика):


          class A {
            mutable std::mutex __mutex;
            std::string              __str;
          public:
            void  set(const std::string& str)
            {
               std::lock_guard<std::mutex> sync(__mutex);
              __str=str;
            }
            const std::string get() const
            {
               std::lock_guard<std::mutex> sync(__mutex);
               return __str;
            }
          };

          Ух пронесло, — небо не упало!


          Вы не поверите, люди до сих пор пишут на чистом C! Тут в ветке даже Дельфисты отметились.


          Вам шашечки или ехать?


          1. qw1
            25.07.2018 17:09

            кого-то остановит от желания программировать на C++ или в ООП парадигме в целом?
            На C++ можно программировать и в функциональном стиле.

            Вам шашечки или ехать?
            Я отвечал на
            >> objA.plus(objB) не укладывается в классическую парадигму
            > Не совсем понимаю где проблема

            Что есть неудобства в ООП, когда объекты предоставлены из внешней (стандартной) библиотеки, и тут приходится съезжать на ПП или ФП.

            Сам-то я не против ООП, но не отрицаю его проблемы.


            1. vintage
              26.07.2018 19:58

              1. qw1
                26.07.2018 20:52

                Это типа extension methods, подсмотренные в c#?


                1. vintage
                  26.07.2018 21:34

                  Там же чёрным по белому написано: любую функцию можно вызвать как метод её первого аргумента.


                  1. qw1
                    27.07.2018 00:11

                    Если это способ реализовать недостающие функции объектов, к коду которых нет доступа, то это просто костыль, синтаксический сахар ))

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


                    1. vintage
                      27.07.2018 09:26

                      То, о чём вы говорите — это уже monkey patching и от него больше вреда, чем пользы.


      1. qw1
        25.07.2018 13:45
        +1

        семантически чётко и ясно. Или всё-таки где-то проблемы?
        Это потому что конкатенация предусмотрена создателями библиотеки std. Но описание перегрузки оператора умножения над двумя std::vector«double», чтобы считалось скалярное произведение, выходит за рамки ООП.


        1. thatsme
          25.07.2018 17:01

          Вы наверное имели в виду STL. И что вам мешает следовать хорошему тону STL, и писать такие-же библиотеки. В STL кстати есть functional в котором в том числе ести и функциональный класс std::multiplies.


          Самое главное, вас ведь никто не ограничивает писать то как вы хотите и как считаете нужным, главное что-бы вам удобно было. А зависать над вопросом "в какой парадигме мне это реализовать", — не продуктивно. Выбирайте хоть ФП, хоть ООП, хоть haskel хоть Java. И реализуйте это то как считаете верным. Какой смысл в войне между отвёрткой и гаечным ключём? Никакой! И тот и другой инструмент может понадобится.


    1. bm13kk
      25.07.2018 15:00

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


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


      1. Neradivy
        26.07.2018 23:01

        несколько операторов в одной строке [не нашел нужного научного термина, но думаю суть понятна]

        Кортеж?


    1. MaM
      26.07.2018 07:40
      -1

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


  1. SerafimArts
    25.07.2018 10:14

    Если, например, говорят про процедурное программирование, то говорят про него абсолютно спокойно

    Чистое процедурное программирование — это треш, угар и содомия с логарифмическим графом зависимостей скорости разработки от количества кода. Говоря проще: Больше кода и больше проблем, где-то в некой точке X переходящей в уничтожение как личности каждого, кто попытается добавить туда ещё какую-нибудь процедурку/функционал.

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

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

    P.S. А на ООП сваливаются все камни по той причине, что это некое «над» решение, которое успешно совмещает (в реальной жизни имеется ввиду, а не сферическом ваккууме) под своим крылом и функциональщину, и процедурщину, и декларативное, аспектное, контрактное, прототипное и прочие программирования. Это стержень архитектуры, а остальное — это лишь решение частных мелких проблем/алогритмов (ФП — это вообще ярковыраженный представитель таких решений, где для решения частной задачи надо понаклепать с десяток функций, которые потом композицией выстраиваются в красивую программку).


    1. mikhailian
      25.07.2018 10:40

      Есть один подход, в котором процедурное программирование вполне себе удобно. Это языки-обязки над низкоуровневым кодом. Таким когда-то было PHP, и он выстрелил. Таким сейчас является Lua. Он тоже не имеет себе равных в некоторых узких областях применения.


    1. VolCh
      25.07.2018 10:51

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


    1. untilx
      25.07.2018 11:16

      Напомните, на чём там написаны ядра linux, windows или freebsd?


      1. ElectroGuard
        25.07.2018 11:26

        Когда писались эти ядра, хорошо проработанной и реализованной концепции ООП еще не было. В результате получили такое чудо как Win API. Которое только Delphi смогло к более-менее удобоваримому и однообразному виду привести. Яркий пример, что может получится в результате использования ФП, к слову.


        1. speakingfish
          25.07.2018 19:02

          Странно приводить VCL как пример хорошей обёртки над WinAPI. VCL в Delphi ужасен и тянет груз совместимости с Win16. Было дело — использовал такую вещь как Watcom Optima — это тот же Delphi, только C++ и не отягощённый грузом совместимости — всё было гораздо проще, компактнее и по возможностям базовой библиотеки превосходило Delphi. (В своё время много использовал и Delphi и напрямую WinAPI и свои не-Delphi-йские компонентные системы над Win32 API делал и делал backports на Win16.)


        1. untilx
          26.07.2018 08:57

          Ну, первая версия ядра linux — 91 год, а C++ появился в 83. То есть времени для появления более-менее надёжных практик достаточно. А вот намного более поздняя HaikuOS уже в основном написана на C++ (кстати, BeAPI офигенная штука, намного удобнее WinAPI), хотя отдельные части всё ещё C.

          Ещё пример: микроконтроллеры. Довольно мало любителей писать под них на плюсах. Ну, потому что ограничение ресурсов слишком жёсткое. Это уже не говоря про FPGA, где свой маленький мир.

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

          Я не говорю, что C++ и ООП плохо, просто есть места, где их использовать не стоит.


        1. fatronix
          26.07.2018 10:53
          +1

          Ядро гугловской Фуксии тоже в процедурном стиле написано, например. Даром что C++ и писать начали недавно.


    1. thatsme
      25.07.2018 17:11
      +1

      Чистое процедурное программирование — это треш, угар и содомия

      Это самый очевидный подход для любого новичка и совершенно мёртвый в современном мире.

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

      Расскажите это: Линусу Торвальдсу или создателям почти любой ОС, создателям apache, nginx, tarantul, и т.д.


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


      1. playermet
        25.07.2018 20:11

        Расскажите это: Линусу Торвальдсу или создателям почти любой ОС, создателям apache, nginx, tarantul, и т.д.
        Вот только они не написаны в чистом процедурном стиле. То что в C нет классов не значит что в нем нельзя использовать ООП.


        1. JobberNet
          26.07.2018 11:09

          Не объяснишь, почему они всё это не написали в ФП?


        1. A1ien
          26.07.2018 16:10

          Да, большинство современных проектов на C реализованны именно в рамках объектно-ориентированной парадигмы. В ручную:)


  1. Alozar
    25.07.2018 10:17

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

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


  1. ElectroGuard
    25.07.2018 10:24

    Я вообще слабо представляю системы порядка единиц/десятков миллиона строк кода написанных в фп парадигме. Как написавший 2/3 от нескольких миллиннострочных проектов.
    Также не совсем очевидны выгоды от иммутабельности. Возможно в каких-то случаях она полезна, сложно сказать. Как по мне — то проще найти кто меняет данные и разобраться с проблемами, чем запрещать мутабельность вообще. Может, конечно, языки такие, что это сделать сложно или невозможно. В Delphi это делается элементарно.


    1. mayorovp
      25.07.2018 10:39

      Тут ключевой вопрос не «кто может менять объект», а «когда его могут менять».

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


      1. ElectroGuard
        25.07.2018 11:12

        Тут есть какой нюанс. Иммутабельность довольно просто 'эмулируется' read only свойствами/инкапсуляцией. То есть — нужно — сделали иммутабельным. Не нужно — сделали обычным. А вот в тех языках, где всё иммутабельное выбора, увы, нет.


        1. cuwHuk
          25.07.2018 20:40

          А вот в тех языках, где всё иммутабельное выбора, увы, нет.

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


          1. qw1
            25.07.2018 21:35

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


            1. cuwHuk
              25.07.2018 22:02
              -1

              Насколько мне известно:
              1. Со строками компилятор С# действует подобным способом
              2. В функциональных языках на уровне «для программиста» (как это делается в рантайме отдельный вопрос) иммутабельность реализуется путем создания копии, т.е. программисту в принципе нет необходимости реализовывать иммутабельный словарь


              1. qw1
                26.07.2018 00:43

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


            1. cuwHuk
              25.07.2018 22:43

              Кстати, вы по-моему путаете иммутабельность с потокобезопасностью… И я тоже про иммутабельный словарь повторил


              1. qw1
                26.07.2018 00:39

                Ну так иммутабельный словарь потокобезопасен.


                1. TheShock
                  26.07.2018 02:37

                  Снег — белый, но не всё, что белое — снег


    1. Akon32
      25.07.2018 11:26

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

      Иммутабельность полезна в случаях, когда создаётся кусок данных (объект), который используется в нескольких местах и/или в разных потоках. Тогда вероятность того, что такой объект ВНЕЗАПНО поменяется, равна нулю. К слову, иммутабельность легко реализуется на любых ООП-языках (может, и не только ООП) — достаточно не писать сеттеров и не менять поля объекта кроме как в конструкторе. А вот наоборот — "чуть" сложнее.


      1. ads83
        26.07.2018 00:37

        Стандартный вопрос на собеседовании: «как реализовать неизменяемый объект?» и на ответ, данный вами

        достаточно не писать сеттеров и не менять поля объекта кроме как в конструкторе
        стандартный дополнительный вопрос: «а если я в конструктор передам изменяемый nestedObject? И потом изменю его состояние?». В результате беседы приходим к выводу, что вся иерархия объектов должна быть неизменяемой. И что вручную это сделать накладно, если в языке какой-нибудь Integer или String по своей природе mutable.
        P.S. В основном я с вами согласен — неизменяемость полезна при многопоточности и может здорово упростить жизнь. Я лишь хочу подчеркнуть, что гарантии неизменяемости «из коробки» полезны. Особенно если есть четкая грань, что mutable а что нет. Например scala.mutable.Array vs scala.immutable.List — сразу понятно что к чему даже новичку в языке.


        1. VolCh
          26.07.2018 07:42
          -2

          > «а если я в конструктор передам изменяемый nestedObject? И потом изменю его состояние?».

          То ничего не изменится — наш объект останется иммутабельным (если забыть про рефлексию и подобные трюки). :)


        1. vintage
          27.07.2018 10:00
          -1

          а если я в конструктор передам изменяемый nestedObject? И потом изменю его состояние?

          Вы просто не сможете это сделать:


          Error: cannot implicitly convert expression bar of type Bar to immutable(Bar)


    1. VolCh
      25.07.2018 14:28

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


  1. bgnx
    25.07.2018 10:39

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


    1. qw1
      25.07.2018 14:04

      Это касается только языков, которые не умеют выделять память под композицию объектов как одно целое. Например, в C++ не никакой разницы, делать

      class InputDevice : public Device { ... }
      или
      class InputDevice {
         public: Device device;
      }


      1. bgnx
        26.07.2018 07:28

        Вы имеете ввиду аллокацию на стеке? А нет ли в с++ оверхеда по памяти на сам объект класса? То есть если внутри класса Device будет еще одно поле


        class Device {
           public: AnotherDevice device;
        }

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


        1. qw1
          26.07.2018 07:40

          С++ аллоцирует память под композицию 1 раз, независимо от того, объект на стеке создан или в куче. В структуре объекта поле public: AnotherDevice device;
          это не указатель, это сам объект AnotherDevice, все его поля. Компилятор знает, с какого смещения начинается вложенный объект и формирует указатели на вложенный объект, когда они нужны, добавлением константы к указателю на объект-композит.


          1. bgnx
            26.07.2018 08:09

            А в с++ размер объекта будет строго равен сумме размеров объектов его полей или добавится еще небольшой оверхед на какие-то служебные поля? Получается что если есть даже минимальный оверхед на объект в один бит то с ростом цепочки вложенности будет расти и размер главного объекта а с наследованием длина цепочки переопределений на размер объекта не повлияет.


            1. elmm
              26.07.2018 09:56

              Сумма полей. К таковым, в данном случае, относятся укзатели на виртуальные функции — тоесть размер всех переменных-членов класса + vtable, а далеехоть так хоть этак определяй InputDevice — результат будет одинаковый.


            1. qw1
              26.07.2018 12:18
              +1

              Без виртуальных методов будет строго одинаково.
              Для каждого включенного объекта с вирт. методами будет на 1 указатель больше (vptr).

              Однако, если не наследоваться, виртуальные методы не нужны :D


  1. Mabusius
    25.07.2018 10:41
    +3

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


    1. adeptoleg
      25.07.2018 10:54

      Не могу себе представить программиста гуманитария :) верстальщика да, программиста…


      1. Mabusius
        25.07.2018 11:01

        Верстальщик это по сути junior JavaScript developer. Если нет, то верстальщик становится невостребованным на рынке. Гуманитариям приходится плакать, но продолжать жрать кактус. Плач выражается в хейте ООП.


      1. AstarothAst
        25.07.2018 11:16

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


        1. roscomtheend
          26.07.2018 10:28
          -2

          Не встречал таких. Физиков, математиков и конструкторов — встречал, экономистов — максимум тестеры или верстальщики (без особого JS), а вот программистов, не умеющих в «ться», встречаю постоянно.


        1. JobberNet
          26.07.2018 11:14

          У меня есть диплом по экономике, но он второй, а не первый, и он не красный.
          Первый диплом красный и он на инженера-программиста.


      1. OnelaW
        25.07.2018 13:15

        Видел, правда ещё не разобрался к какому классу относятся эти товарищи.При мне работали Барышни-погромистки в великой желтой программе, все сплошняком гуманитарии. И да, они таки писали.


    1. CheY
      25.07.2018 11:59

      А вы этой теорией за чей лагерь? «За ООП» или «против ООП»?)


      1. Mabusius
        25.07.2018 12:17

        Я за то, что все хорошо в меру.
        Как то раз делал тестовое задание при приеме на работу. Нужно было написать демона, который пингует адрес и шлет репорты, если пинг не проходит. Там кода 10 строчек. Ну я и написал просто 10 строчек. Понятно, что для демонстрации скиллов этого не достаточно и я прикрутил демону ООПешную возможность прикручивать разные способы отправки репортов. Но все равно первые же два вопроса были «Почему не весь код ООП?», «Почему не использовали фреймворков?». Прикручивать какойнибудь симфони ради 10 строчек кода, да еще и демону?.. На работу меня тогда не взяли…


        1. thatsme
          25.07.2018 17:28

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


          Вообще это такой суровый ынтырпрайз, не написал 2000 строк и всё через ООП вместо десяти которыми можно решить задачу. При этом перед тем как писать код ещё и UML диаграммы все нарисовать от use-case и заканчивая deployment. Это как дрескод нарушуть и в плавках на банкет явиться.


  1. powerman
    25.07.2018 10:47

    1. ООП смешивает данные и действия над ними. Это плохо

    Думаю, Вы не совсем правильно поняли этот аргумент. Плохо когда пытаются абсолютно всё представлять объектами, искусственно симулируя наборы данных и действий там, где их нет: число 3 это не объект, равно как и функция sum(a,b int) не является частью/методом какого-то объекта. Всё хорошо в меру, где-то используемые кодом абстракции действительно лучше представлять в виде объектов, но требование чтобы объектом было абсолютно всё добавляет accidental complexity на пустом месте.


    1. Наследование закрепощает программу, делает трудным внесение изменений

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


    1. Методология ООП изначально ошибочна
      Абсолютно необоснованный аргумент. ООП создавалось для того, чтобы моделировать своеобразный виртуальный мир, состоящий из объектов, как и наш мир.

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


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

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


    1. Mabusius
      25.07.2018 11:09

      Плохо когда пытаются абсолютно всё представлять объектами, искусственно симулируя наборы данных и действий там, где их нет

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

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


    1. AndrewMayorov
      25.07.2018 11:20

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

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

      Так вот, для упрощения работы программиста в незапамятные времена были придуманы библиотеки процедур и вообще структурное программирование. Сейчас апологеты композиции (composition over inheritance) говорят, что вам достаточно скомбинировать библиотечные функции нужным образом чтобы получить требуемое сложное поведение. Это так, но таковая композиция сама по себе является сложной сущностью. Аналог такой сущности — стойка с сетевым оборудованием. Все компоненты в стойке стандартны, но конкретная конфигурация стойки — нет.

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

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


      1. powerman
        25.07.2018 11:43

        По-сути, без наследования (и связанного с ним полиморфизма) ООП особого смысла не имеет

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


        1. AndrewMayorov
          25.07.2018 11:49

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


          1. powerman
            25.07.2018 12:05

            Ещё точнее — речь шла о наследовании как инструменте, а не о полиморфизме. Если наследование применяется не как инструмент для создания реальной иерархии, DRY и моделирования отношений is a между сущностями предметной области, а просто как синтаксическая форма записи необходимая для использования полиморфизма в конкретном языке (т.е. речь о создании абстрактных классов нужных исключительно для декларирования набора поддерживаемых методов, от которых потом выполняется множественное наследование не вкладывая в это никакого смысла кроме "я поддерживаю этот набор методов и подразумевающуюся с ним семантику") — в этом ничего плохого нет (как впрочем в этом нет и настоящего наследования чего либо).


            1. AndrewMayorov
              25.07.2018 12:13

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


    1. untilx
      25.07.2018 11:21
      +1

      Наш мир не состоит из объектов.

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


      1. rjhdby
        25.07.2018 12:48

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

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


        1. mayorovp
          25.07.2018 13:04
          +1

          Кажется, у вас детектор сарказма сломался…


          1. rjhdby
            25.07.2018 13:21

            Ну так тэга то не было, а по косвенным признакам не сработал — бывает…


        1. untilx
          26.07.2018 08:38

          Сарказм и отсылка к парадоксу Тесея


  1. AndrewMayorov
    25.07.2018 10:49

    Что характерно, например, в разработке веб-фронтенда такие хейтеры ООП спокойно используют HTML DOM и не жалуются, что это не кошерно. Возможно, даже не обращают внимание на факт соприкосновения с объектами.
    Автор поднял правильную тему, и в правильном ключе. Спасибо.


    1. ElectroGuard
      25.07.2018 11:03

      Я, например, жалуюсь. DOM, как и HTML — то еще… чудо. HTML то нарушает еще одну известную парадигму, смешивая код (js) с интерфейсом (всё остальное). Но, другого просто нет, увы.


      1. AndrewMayorov
        25.07.2018 11:21

        А вы не смешивайте, вот и все.


  1. dom1n1k
    25.07.2018 10:54
    +1

    По моим впечатлениям, самые полярные и непримиримые мнения по функциональщине.


    1. Stas911
      25.07.2018 20:17

      Плюсую, про ООП, кмк, все давно смирились с неизбежным


    1. cuwHuk
      25.07.2018 20:48

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


    1. TheShock
      26.07.2018 02:40

      По моим впечатлениям, самые полярные и непримиримые мнения по функциональщине.

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

      Другая проблема, что сейчас много людей говнокодят на JS в процедурном стиле с элементами ФП и топят, что они — функциональщики, потому что отказались от классов.


  1. fzn7
    25.07.2018 10:55

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


    1. JobberNet
      25.07.2018 11:22

      ФП тоже со скрипом на имеющиеся аппаратные возможности натягивается (я про ограниченный объём памяти), но тем не менее находит применение.


  1. JobberNet
    25.07.2018 11:17

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


    1. AndrewMayorov
      25.07.2018 11:29

      Я не автор, но отношусь к этому сугубо отрицательно. Говорят, множественное наследование сложно, потому что может возникнуть «deadly diamond of death», но эту проблему можно элементарно решить на уровне компилятора. Если в классе возникает проблема неоднозначности выбора метода, то нужно заставить разработчика явно реализовать этот метод. Вот и все, вроде.


  1. Misiam
    25.07.2018 11:17

    На одном из форумов в интернете была замечательная мысль:
    «Не понимаю, почему они выбирают между OOP и процедурами? Можно же выбирать между OOP и HTTP»


  1. muhaa
    25.07.2018 11:23
    +1

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


    1. AndrewMayorov
      25.07.2018 11:37

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


      1. muhaa
        25.07.2018 11:52

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


        1. k12th
          25.07.2018 12:56

          Приходит Java-прогер в столовую и говорит: приготовьте мне oop OOP = new OOP();


          1. qw1
            25.07.2018 14:11

            OOP oop = new OOP();


            1. k12th
              25.07.2018 14:13

              Не бывать мне java-программистом:D


    1. Busla
      25.07.2018 12:24

      Красивее всего с ООП получается писать нечто вроде графических редакторов.
      это пока вы не реализуете Undo/Redo и банальное сохранение.


      1. muhaa
        25.07.2018 14:42

        Думаю, если поведение undo/redo/save и поведение при редактировании инкапсулировать в объекты, то действительно все станет плохо. Во всяком случае, мне такие вещи не удаются.
        Я думаю проблема в том, что undo/redo/save — это более низкий уровень абстракции по сравнению с основными функциями объекта в графическом редакторе. А поведение при редактировании — это общее поведение группы объектов а не отдельного объекта.
        Лично я для undo/redo/save делал объекты не plain и все изменения проводил через отдельный менеджер. Поведение при редактировании реализовывал отдельными классами-обработчиками.
        ООП в классическом виде хорошо работает для задач типа отображения на различных устройствах с общим базовым классом различных графических объектов, так же имеющих общего предка и прочие функции того же уровня абстракции.


      1. picul
        25.07.2018 17:39

        А в чем с ними проблема?


      1. playermet
        25.07.2018 20:31
        +2

        Undo/Redo типично реализуются через паттерн Команда, который существует как раз благодаря ООП. В чем проблема то?


        1. VolCh
          26.07.2018 07:45

          Ну, большинство ООП-паттернов создано чтобы обойти ограничения ООП :) Так что «паттерн существует благодаря ООП» звучит как «полиция существует благодаря преступникам». Причинно следственная связь отражена вроде верно, но есть нюансы.


          1. Neikist
            26.07.2018 09:23

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


            1. VolCh
              26.07.2018 10:22
              +1

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


        1. muhaa
          26.07.2018 10:22

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


          1. VolCh
            26.07.2018 10:32

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

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


            1. muhaa
              26.07.2018 12:48
              +1

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


              1. VolCh
                26.07.2018 17:47

                Нужно при отмене не заставить логику не работать, а заставить работать обратную логику, если это возможно. Или просто при отмене N-ой команды объекту создать его заново и провести N-1 команду.

                А я воспринимаю ООП в стиле «меня, объект А, просят сделать то-то — я решаю делать это так-то (варинт — не делать, проигнорить или эксепшен бросить).


                1. muhaa
                  27.07.2018 09:28

                  В говорите о ситуации, когда команда должна менять только один объект. Это очень простая ситуация. Допустим, мы разрабатываем редактор электрических схем. Как при перемещении узла схемы заставить адекватно реагировать все связанные элементы схемы, и чтобы при этом они учитывали границы листа (например) и чтобы потом еще можно было делать undo/redo? Я разрабатывал такие вещи, но с вынесением логики редактирования в отдельные классы. Наверняка это можно сделать и на командах, но мне сложно представить достаточно изящное решение.


        1. Busla
          26.07.2018 10:27

          Речь была о красоте. Паттерн Команда — довольно громоздкая конструкция.


  1. VaalKIA
    25.07.2018 11:32

    ООП в каком-то роде моделирует реальный мир

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

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


    1. picul
      25.07.2018 17:38
      +2

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


    1. TheShock
      26.07.2018 02:41

      нам говорят — наследуйтесь, оно всё летает!
      Кто говорит?


  1. k12th
    25.07.2018 11:35

    Наследование закрепощает программу, делает трудным внесение изменений

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


    Философия ООП гласит: правильно организованный и инкапсулированный класс можно рассматривать как чёрный ящик.

    Любой библиотечный код (начиная от соседнего файла) можно и нужно рассматривать как чёрный ящик, и ООП тут, в общем-то, не при чем. Никто не полезет в ваш код, пока он работает как надо. Over-engineered система сокрытия это удел в основном c++ и потомков (хотя хватило бы public и protected (по умолчанию)).


    В реальном мире нет иерархий отношения, повсюду лишь иерархии включения

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


  1. AndrewMayorov
    25.07.2018 11:40

    А еще есть ощущение, что многие ставят знак равенства между «ООП вообще» и «моделированием доменной модели через ООП». Это совсем не одно и тоже. Как правило, построить доменную модель на объекта действительно очень сложно. И редко нужно.


    1. muhaa
      25.07.2018 12:20
      +1

      Или точнее, знак равенства между описанием доменной модели и описанием поведения объектов доменной модели. Само описание доменной модели на ООП отлично работает. Пример: Common Information Model. Что касается описания на ООП поведения доменных объектов — с трудом представляю когда это может быть оправдано. Для одной задачи нужно одно поведение, для другой другое и непонятно как разделить общее по сути поведение между взаимодействующими классами.


  1. DuMMeR
    25.07.2018 11:41

    Почти все языки программирования являются тьюринг-полными, за исключением языков разметок, как то: HTML, XML, CSS

    CSS3 является тьюринг-полным. На нём реализовывали Rule 110, который в свою очередь является тьюринг-полным клеточным автоматом.


  1. OLDRihard
    25.07.2018 12:44
    +1

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


    1. AndrewMayorov
      25.07.2018 12:55

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


      1. mayorovp
        25.07.2018 13:08

        Минус в карму автору статьи еще не означает что минусанувший — анти-ООПешный радикал. Кто-то мог счесть пост переливанием из пустого в порожнее. Или аргументы могли показаться слишком слабыми. Или же приведенные аргументы противников могли показаться «соломенным чучелом». Или просто форматирование не понравилось. Или все вместе взятое.


  1. AndrewMayorov
    25.07.2018 12:55

    del


  1. bm13kk
    25.07.2018 15:16

    Но задумайтесь, а если бы на пьедестал взошло не ООП, а, скажем, ЛП?

    Что за ЛП ?


    1. picul
      25.07.2018 17:40

      Видимо, логическое программирование.


  1. dimaaan
    25.07.2018 15:59
    -2

    Лично для меня этот спор остался в далеком прошлом.
    С приходом мультипарадигмальных ЯП, таких как Scala, C#, можно выбрать лучший подход по ситуации.
    Но выбор не должен диктоваться личными предпочтениями. Там где есть большое и сложное состояние в памяти, там где данные первичны, лучше подойдет ООП, а там, где первичны алгоритмы, функции, многопоточность лучше выбрать ФП подход.
    Именно этим и обусловлены рост и падение популярности разных подходов в разное время. В 90-е были популярные десктопные приложения. А это, в первую очередь, сложное состояние, которое декомпозировали, инкапсулировали, выстраивали предметную область из этих абстракций.
    С приходом популярности веб приложений и HTTP протокола, приоритеты поменялись. Приложения стали выстраиваться как конвейер по обработки запросов, с внешним хранилищем состояния и популярность ФП стала расти.
    Интересно к этом делу подошел ReactJS, где оба подхода совмещаются.


    1. VolCh
      25.07.2018 20:07
      +1

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


      1. dimaaan
        25.07.2018 20:48

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


        Пример 1.
        Мы пишем микросервис, без фреймворков. Для этого нам нужно:
        1 открыть сокет на прослушивание и переадресовать клиента в обработчик
        2 считать запрос в буфер
        3 распарсить его
        4 сделать ему валидацию
        5 выполнить запрос к хранилищу
        6 отправить ответ
        Требования к сервису: многопоточность, надежность.


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


        Пример 2.
        Пишем десктопную корпоративную систему учета чего-то-там, пусть будет товара. В ТЗ у нас есть пользователи, права, виды товара, катерогии, группы, отчеты, загрузка/выгрузка данных, цены, скидки, контрагенты и еще 1000 других сущностей. Сущности могут вести себя по разному в зависимости от состояния. Все это хаотично взаимодействует с сервером, интерфейсом, файловой системой, БД, туда подключают сканер по COM порту…
        Здесь предметная область сложная, запутанная, может не поддаваться строгой формализации, часто меняться. В этом основная сложность, и тут принципы ООП как раз могут помочь.


        1. picul
          25.07.2018 23:40

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


          1. dimaaan
            26.07.2018 00:42

            у Вас каждый пункт использует результат работы предыдущего, так что даже пресловутое ФП не поможет с многопоточностью

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


            ФП не поможет с многопоточностью

            Вообще то может помочь, иногда. Нам не обязательно ждать завершения считывания данных из сокета, чтобы начать парсинг. Это называется параллелизм данных. Хотя это не относится ни к ФП, ни к ОПП, мне кажется что такую фичу легче будет реализовать используя ФП подход, хотя бы потому что это требует конечного автомата (но это сильное заявление, проверять мы его, конечно же, не будем :) )


            лучший вариант — реализовать саму функцию последовательно и запускать несколько демонов для ее выполнения для разных запросов.

            Обычно, оно так и происходит. Только демоном называют отдельный процесс, а у нас это пул потоков. Но если мы хотим асинхронный сервер, то можно выстроить ф-ии в цепочки promis'ов, тут ФП тоже будет кстати.


            1. picul
              26.07.2018 02:18

              Тут может помочь иммутабельность, например.
              Иммутабельность чего, чем помочь?
              Нам не обязательно ждать завершения считывания данных из сокета, чтобы начать парсинг.
              Мой опыт с ФП весьма ограничен, но я вот вообще не понимаю, как на нем такое вот организовать ( мы ведь возвращаем данные из функции целым куском, а не по частям ). А вот на императивном — запросто.
              Но если мы хотим асинхронный сервер, то можно выстроить ф-ии в цепочки promis'ов, тут ФП тоже будет кстати.
              Насколько я понимаю, в зависимости от тяжести подзадач, это может иметь как позитивный, так и негативный эффект ( из-за оверхеда task-системы ). А распаралеливание по демонам при большом количестве запросов и железо загрузит, и оверхед сведет к минимуму.


            1. TheShock
              26.07.2018 02:44

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


  1. Jef239
    26.07.2018 02:09

    Забавно, что автор не увидел основные проблемы ООП. Это

    1. Качество иерархии. Для одной и той же предметной области разные люди придумывают разные иерархии. И если иерархия придумана плохо — мы получаем кучу friendly и ООПшное спагетти. Конечно, нерешаемых проблем нет и программист высокого класса может для любой задачи придумать хорошую иерархию. Но средних программистов больше, чем хороших.
    2. Отсюда вторая проблема — порог входа. Чтобы написать ООПшный код, который не рухнет за 2-0 лет развития, нудно быть намного более сильным проектировщиком, чем в случае процедурного кода.
    3. Следующая проблема — соответствие предметной области. Есть области, где иерархия естественна. Прежде всего это всякие GUI-библиотеки. А есть области, где иерархию нужно вымучивать, натягивая сову на глобус. В итоге все объекты — солитоны, а от ООП — одно название. Ну и оверхед, который в данной ситуации лишний.
    4. Ещё одна проблема — методология проектирования. В ООП принято, что мы делаем кирпичики, потом из них нечто собираем. Причем кирпичики делаются один раз, а используются — много раз. Для многих предметных областей это так. Но не для всех. В итоге — опять оверхед, и прежде всего — по времени разработки.

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

    И лишь ООП преподают как религию, как единственный инструмент для всего. :-( Отсюда и толпы бывших студентиков, считающих ООП панацеей, а С++ венцом творения в любых областях. А где сектанты — там и флейм с ними.


    1. picul
      26.07.2018 02:33

      1. Проблема людей, а не ООП. Средний программист при любом подходе выдаст средний результат, на то программист и средний.
      2. То, что между ООП и процедурным кодом запросто проводится однозначное соответствие, конечно, никак не отменяет сказанное Вами. (sarcasm)
      3. Опять же, натягивание совы на глобус — это проблема людей. ООП — инструмент, и есть задачи, где он подходит не лучше всех, но из-за этого не стоит выбрасывать его на помойку, что и пытается донести автор статьи. И в общем случае, оверхеда от использования ООП, ясное дело, нет.
      4. Ничто никем нигде не принято. Хотите — пишите сначала высокоуровневую логику, а потом — низкоуровневые детальки. Оверхеда по сравнению с чем-либо другим, опять же, не видно.

      Качество преподавания ООП, ИМХО, не хуже чем качество преподавания чего-либо другого :) Религию разводят, опять же, люди; личное мнение студентов-сектантов — проблема студентов-сектантов.


      1. Jef239
        26.07.2018 02:53

        Согласен с вами, коллега. ООП — хорош, но не для людей. Вот создадим сильный ИИ — тогда ООП и покажет свою мощь. :-)

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

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

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

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

        Нельзя рассматривать стиль программирования в отрыве от людей, его использующих. И в отрыве от задачи. Это единая система для минимизации затрат — люди + задача + стиль.


        1. AndrewMayorov
          26.07.2018 11:08

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


        1. VolCh
          26.07.2018 11:41

          Точно так же этот человек написал бы кучу процедур/функций для полноценности api работы с глобальными данными.


    1. TheShock
      26.07.2018 02:44

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


      1. Jef239
        26.07.2018 03:02
        -1

        Почему же? Попробуйте аргументировать.

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

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


        1. TheShock
          26.07.2018 03:35
          -1

          Простите, но ведь это вы придумываете демагогические «факты», потому и ваша задача их подтверждать.

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

          реализация в ООП представляет собой натягивание совы на глобус
          Пруф?

          В результате сова просто лопается
          Пруф? Пруф, что лопается только при парадигме ООП?

          Цена ООП-решения больше зависит от выбора иерархии, чем иных решений.
          Пруф?

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


          1. Jef239
            26.07.2018 03:58
            -1

            Понятно, аргументировать не можете. :-(

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

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

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

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

            Хрестоматийным пример — разная стоимость денег на разных этапах проекта.


            1. TheShock
              26.07.2018 04:29
              -1

              Понятно, аргументировать не можете. :-(
              А вы это и не пытались делать

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

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

              О! А теперь вы занимаетесь подменой тезиса. Ну уж нет, не получится такая грязная демагогия. Пруф, что я требовал доказать, что ООП всегда хуже? Я лишь сказал, что у каждой идеологии есть свои проблемы, процитируйте в этом топике, где я хоть раз сказал, что ООП — лучшее решение. Вы хейтите ООП, а я лишь пытаюсь указать, что совершенно неаргументированно. Вы привели кучу домыслов и ни разу не подтвердили фактами. Или вы считаете, что цитата на Баш — это доказательство? Понятен уровень вашей аргументации. Ну так на Баше и высказывайтесь, ваша цитата может даже в лучшее бездны попадет, чего тогда на Хабре выступаете? Я в этом топике ни разу не топил за ООП я лишь указывал на то, что ваш коммент — всего лишь неаргументированное хейтерство.

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

              И еще пытаетесь сменить направление, приписав мне то, что я в этом топике ни разу не говорил.

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

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


              1. Jef239
                26.07.2018 05:07

                Пруф, что я требовал доказать, что ООП всегда хуже?
                Ноль проблем:
                И пруф, что зависимость от выбора иерархии повышает сложность поддержки, в сравнении с ЛЮБОЙ другой зависимостью при создании архитектуры на любой парадигме.

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

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

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

                Вы однозначно, без «но» заявили, что «сова просто лопается».
                Понятно, у вас другой диалект русского языка. Украина? Перечитайте пост и обратите внимание на слово "зачастую". Это и есть то самое «но», которое вы не увидели.

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


                1. TheShock
                  26.07.2018 05:39
                  -1

                  Пруф, что я требовал доказать, что ООП всегда хуже?

                  Ноль проблем:
                  И пруф, что зависимость от выбора иерархии повышает сложность поддержки, в сравнении с ЛЮБОЙ другой зависимостью при создании архитектуры на любой парадигме.


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


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

                  Цена ООП-решения больше зависит от выбора иерархии, чем иных решений.


                  И в этой цитате нету никаких «но» и «зачастую». Вы заявили, что цена больше зависит от выбора иерархии, чем в иных решениях. Вот и докажите.

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

                  Поэтому пример, который мы знаем одинаково — лучше.

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

                  что я знаю о них больше вас

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

                  Перечитайте пост и обратите внимание на слово «зачастую». Это и есть то самое «но», которое вы не увидели.

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

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

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

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


                  1. Jef239
                    26.07.2018 05:50

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

                    Не вижу смысла спорить с собеседником, который плохо понимает смысл слов.

                    К сожалению, на данном этапе понимания русского языка, вы любой написанный мной текст поймете неверно. :-(


                    1. TheShock
                      26.07.2018 15:21

                      Я понял. Когда нету аргументов — назови противника «не понимающим языка хохлом» и слиняй с гордо поднятой головой. Вы пробили очередное дно.


              1. Jef239
                26.07.2018 05:44

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

                Мой вам совет — найдите человека с нативным русским языком и вместе с ним перечитайте, что я писал, а что не писал. А уж потом — возражайте


                1. TheShock
                  26.07.2018 05:47

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


            1. TheShock
              26.07.2018 04:47

              Как пример — много ли вы знаете поддерживаемых игр 20летней давности?
              Добавлю ещё на счет этого. Игры Valve, idSoftware и на базе Unreal Engine поддерживаются уже от двух десятилетий, постоянно развивая один и тот же движок. Основная причина постоянных усовершенствований движка — безумно быстрая и жёсткая смена технологий и требований, которая многим другим направлениям даже не снилась. 3d max, Blender, Photoshop, Cubase развиваются уже более двух, а то и трех десятков лет. Банальной Lineage 2 уже 15 лет, а первой — уже 20. World Of Tanks выпускает живые обновления для огромной базы пользователей до 6 раз в год уже 8 лет. Far Cry вышел в 2004, а начали разработку ещё раньше — уже больше 15 лет. Про CryEngine слыхали? Первая версия Fifa вышла 25 лет назад и новая игра выходит каждый год.


              1. Jef239
                26.07.2018 04:55

                Угу, меньше процента. Основная масса — выпущена и заброшена. Если говорить про id Software, то где сейчас Spear of Destiny? Когда последнее обновление вышло? :-) Движок — да, развивается. А вот сама игра — нет. И таких, заброшенных игр — 99%, если не 99.9.


                1. TheShock
                  26.07.2018 05:05

                  Как и любого софта на любой парадигме. Сколько вы знаете программ на Хаскеле, которые поддерживаются более 20 лет? Я назвал, ваша очередь.

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

                  Кстати, Копье Судьбы, которое вы почему то привели в пример — Всего лишь одна из частей Вольфенштейна, недавно вышло его новая часть, Так что серия живет, Спасибо, что поинтересовались


                  1. Jef239
                    26.07.2018 05:13

                    ОТЛИЧНО! Вы начинаете понимать главное.

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

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


                    1. TheShock
                      26.07.2018 05:43
                      -1

                      Оппа! Переобулись! Сначала вы топили, что чем дольше поддержка, тем ООП — хуже. Цитирую:

                      В ООП цена переделки иерархии на поздних этапах выше, чем в иных методологиях.

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

                      У вас какая-то каша в голове. Хейтерство не идет на пользу вашим аргументам. И определитесь с позицией. Вы переобуваетесь быстрее, чем я успеваю читать ваши сообщения.


                      1. Jef239
                        26.07.2018 06:14
                        -4

                        И в третий раз — учите русский язык. Мне действительно лень писать на уровне начальной школы и иностранцев. Найдите человека с нативным русским — и он вам все растолкует.

                        Ну серьезно — ну лень мне! :-) У меня своей работы хватает. Ну не учитель я русского для иностранцев.

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

                        Начинаем разбирать текст.

                        Выше цена переделки чего? Иерархии. Цена других переделок — обычно ниже.

                        Цена переделки иерархии выше когда? На поздних этапах.

                        Слово «этапы» во множественном числе. А вся поддержка — это один этап. Значит речь не только о ней. А намного больше — про поздние этапы написания кода.

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

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


                        1. TheShock
                          26.07.2018 15:23

                          Знаете что? Попробуйте придумать иерархию классов для книг. В комплексе — издательство + типография + магазин + библиотека. А я буду подбрасывать вам объекты, которые не совсем книги. Но в отдельных местах встречаются. Ну и посмотрим, легко ли будет их вам вместить в иерархию.
                          Я могу придумать плохую нерасширяемую архитектуру на любой парадигме. Знаете, что это доказывает? Ничего.


                        1. michael_vostrikov
                          26.07.2018 15:30

                          Попробуйте придумать иерархию классов для книг. В комплексе — издательство + типография + магазин + библиотека.

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


                        1. VolCh
                          26.07.2018 17:59

                          В комплексе у нас будут 4 иерархии. Нет никакой нужды в системе управления книжным холдингом моделировать книги в разных контекстах одним объектом :)


  1. ads83
    26.07.2018 02:18

    Во-первых, где ООП смешивает данные и функции? Во-вторых, утверждение, что это плохо<...>

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


  1. Beshere
    26.07.2018 09:09
    +1

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

    Главное преимущество ООП — управление сложностью.


    1. Mabusius
      26.07.2018 10:52

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


  1. random1st
    26.07.2018 13:38

    Высосите тему статьи из пальца — чем банальнее, тем больше у нее комментаторов


  1. uvelichitel
    27.07.2018 10:23

    ООП это не парадигма, это метода.

    Объе?ктно-ориенти?рованное программи?рование (ООП) — методология программирования
    wiki