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


«Никто не знает, что такое ООП»

Это правда. Все трактуют по-разному. Даже сам Алан Кэй, человек, который придумал термин, не слишком рад тому, во что это всё превратилось:

> “OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things.”
> — Alan Kay

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


«Все примеры из книжек — это кошки и собаки»

Ну конечно. Никто не станет показывать на собеседовании паттерн CQRS с Event Sourcing. Показывают Animal, потому что это просто.

Это не руководство к действию. Это иллюстрация. Как for (int i = 0; i < 10; i++) — вы же не думаете, что весь код должен быть таким?


«DTO туда-сюда, а методы всё равно чистые»

Да, и это отлично. Инкапсуляция — это не магия. Это просто «держи данные под контролем».

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


«Паттерны GoF — это костыли»

Так и есть. Но это хорошие костыли. Проверенные временем.

> “The point of OOP is to manage dependencies, not to model cats and dogs.”
> — Robert C. Martin

Да, Strategy можно заменить на Func. Но стоит ли выбрасывать идею только потому, что синтаксис стал проще?


«Интерфейсы плодятся, DI магичен, всё сложно»

Сложно — когда делаете «по учебнику», не понимая зачем. Интерфейс нужен, чтобы не зависеть от реализации. DI — чтобы не было new в каждом методе.

> “SRP doesn't say you need tiny classes. It says a class should have one reason to change.”
> — Robert C. Martin


«ООП не нужен: смотри на Linux»

Конечно, в ядре Linux не до полиморфизма. Это системный код, где важны предсказуемость и скорость. Но если вы пишете код, который поддерживают 10 человек и меняют годами — с интерфейсами, классами и тестами вам будет проще.

> “All successful software gets changed. And object-oriented design helps you manage that change.”
> — Grady Booch


Вместо вывода

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

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

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


  1. php7
    11.05.2025 19:49

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


    1. BorisU
      11.05.2025 19:49

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


      1. stay_protected
        11.05.2025 19:49

        как раз обязан - ооп изучают на примере работы аэропорта и прям первая серьёзная ооп прога это описать классами все процессы аэропорта


        1. Yoitz
          11.05.2025 19:49

          Во-первых, кто, где и как учит ООП через такие "кейсы", позволите поинтересоваться? Не строит экстраполировать свой опыт на опыт вообще всех. У нас нет стандарта образования с точностью до конкретных задач и проектов.

          Во-вторых, как наличие образовательной программы курса/книжки, использующей модель аэропорта как какой-то учебный проект, делает ООП ОБЯЗАННЫМ решать ВСЕ вопросы? Метод вам вообще ничего не должен, кроме как решать поставленную перед ним абстрактную задачу - вы же не говорите, что какой-то мат. метод обязан решать ВСЕ задачи. (Оптимальность и корректность выбора метода полностью лежит на том, кто метод выбирает и использует)

          В-третьих, описание классами процессов, да, вы, верно, просто быстро писали и имели ввиду иное, однако описание ПРОЦЕССОВ классами, конечно, иногда удобно, но обычно говорят о каких-либо акторах, сущностях и тп. Т.е. нет класса "процесс регистрации", обычно есть класс "регистрационная форма" или "регистрационная стойка" с соотв. методами.


          1. Viilture
            11.05.2025 19:49

            Некоторые люди не понимают, что программист это инженер.

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

            Усложнять, то что должно упрощать жизнь, это не инженерный подход.


        1. Dhwtj
          11.05.2025 19:49

          описать классами все процессы аэропорта

          Хороший тамада. И конкурсы интересные


      1. rukhi7
        11.05.2025 19:49

        ООП это всего лишь инструмент

        а может это даже и не инструмент, а метод, в смысле способ?


    1. DirectoriX
      11.05.2025 19:49

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


      1. Dhwtj
        11.05.2025 19:49

        Я приемлю чужой код в любой парадигме. Но у меня уже сложилось привычки.

        Я пишу (по мелочи) на 6 языках. Но некоторые использую чаще.


      1. Q3_Results
        11.05.2025 19:49

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


        1. Bedal
          11.05.2025 19:49

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

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


          1. morijndael
            11.05.2025 19:49

            А вот и представитель новой, четвёртой группы :р


            1. Bedal
              11.05.2025 19:49

              представитель новой, четвёртой группы 

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

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

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

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


              1. Jijiki
                11.05.2025 19:49

                ну писать с нуля функционал, оно интересно, я тоже хотел анимации на С закодить, но я конечно сохранил задумку, но по ощущениям оно того не стоит когда рядом можно запустить std::array или std::vector, ну а разрабатывать что-то уровня хронос, это извините высший пилотаж как и по С так и по С++, тут хотябы всё просто собрать ) в итоге солидарен с вами, просто уже пользуешься инструментом без изучений для того для чего он создан, ну а вайб не знаю, вот я 3 дня курировал ИИ ради кусочка кода просто потомучто лень было не на своём языке разбираться как сортировать. в итоге просто по шагам по алгоритму ему задал промпт и сделали )

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

                вот только что переписал свою либу матеши для 3д с С на С++ по канонам ООП радость нескончаемая, наконечно всё читаемо всё как должно быть )


              1. GarfieldX
                11.05.2025 19:49

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


      1. Keeper11
        11.05.2025 19:49

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

        Экзотермичен ли Ад?


      1. Vadiok
        11.05.2025 19:49

        Если брать, например, PHP с его экосистемой (Composer, существующие фреймворки, библиотеки), то писать придется именно ООП.

        На JS/TS функциональный подход скорее более популярный (правда тут у меня статистики нет). По крайней мере, в отличие от PHP, писать функциями довольно естественно для языка.


        1. mayorovp
          11.05.2025 19:49

          Одно название там от функционального подхода, ФП не сводится к использованию функций.


          1. askv
            11.05.2025 19:49

            А вот, кстати, можете кратко в двух словах пояснить, в чём именно суть функционального программирования? Спрашиваю для себя, так как не понимаю. Процедурное программирование понимаю, ООП тоже в принципе. Я понимаю, что ФП это какой-то следующий уровень абстракции, но какой именно?


            1. nin-jin
              11.05.2025 19:49

              1. askv
                11.05.2025 19:49

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

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


                1. nin-jin
                  11.05.2025 19:49

                  Например, классическое:

                  • вызов чистой функции может быть заменён на результат её вызова

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

                  • вызовы чистых функций гарантированно можно переставлять местами


                  1. askv
                    11.05.2025 19:49

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


                    1. nin-jin
                      11.05.2025 19:49

                      Не компьютеру, а компилятору. Плюс ему проще ошибки детектировать. И дебажить тоже.


                      1. askv
                        11.05.2025 19:49

                        А тут вопрос, эта оптимизация она только на стадии компиляции делается целиком или и на этапе выполнения тоже? Я имею в виду возможный параллелизм и т.д.


                      1. nin-jin
                        11.05.2025 19:49

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


                      1. askv
                        11.05.2025 19:49

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


                      1. nin-jin
                        11.05.2025 19:49

                        Зависит от реализации компилятора, библиотек и сложности вычислений.


                      1. askv
                        11.05.2025 19:49

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

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


                      1. netch80
                        11.05.2025 19:49

                        Может и при выполнении. Но тут начинает сильно зависеть от языка, компилятора и прочего.

                        Простейший пример - если вы записали c=a*b, где все участники - матрицы, вполне возможно, что при размерах матриц миллион на миллион среда сама раскинет это на 100 компов в кластере. А вам не надо было писать все итерирования строк-столбцов, вы просто попросили результат - произведение матриц.

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


                    1. WASD1
                      11.05.2025 19:49

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

                      Примечательно, что практике обычно наоборот.

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


                1. mayorovp
                  11.05.2025 19:49

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


                  1. aelaa
                    11.05.2025 19:49

                    Переопределение имени таки не есть изменение значения переменной


                    1. mayorovp
                      11.05.2025 19:49

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


                      1. IUIUIUIUIUIUIUI
                        11.05.2025 19:49

                        В таком случае присваивание выглядит и ведёт себя как просто name shadowing, и старое имя можно просто удалить — в чём его смысл, если оно никуда не захвачено?


                      1. mayorovp
                        11.05.2025 19:49

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

                        Продемонстрирую кодом на Rust:

                        fn foo() -> i32 {
                            let x = 2;
                            if true {
                                let x = 3;
                            }
                            x
                        }
                        
                        fn bar() -> i32 {
                            let mut x = 2;
                            if true {
                                x = 3;
                            }
                            x
                        }
                        
                        fn main() {
                            dbg!(foo()); //[src/main.rs:18:5] foo() = 2
                            dbg!(bar()); //[src/main.rs:19:5] bar() = 3
                        }
                        


                      1. IUIUIUIUIUIUIUI
                        11.05.2025 19:49

                        Так это разные переменные, и никакого присваивания снова нет. foo α-эквивалентна этому:

                        fn foo() -> i32 {
                            let x = 2;
                            if true {
                                let y = 3;
                            }
                            x
                        }


                      1. mayorovp
                        11.05.2025 19:49

                        Но ведь name shadowing как раз и означает существование двух разных переменных с одним именем...


                1. toiori
                  11.05.2025 19:49

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


            1. pythonist1234
              11.05.2025 19:49

              Применение функций к набору объектов? Всё это map-reduce?


            1. Vytian
              11.05.2025 19:49

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

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


            1. mayorovp
              11.05.2025 19:49

              Основные "киты" современного функционального программирования:

              1. функции как значения - тут в JS всё в порядке;

              2. функции в математическом понимании, они же чистые функции - тут язык вообще не помогает;

              3. работа с данными через сопоставление с образцом, оно же паттерн-матчинг - в зачаточном состоянии;

              4. комбинирование функций через стандартные комбинаторы (включаю сюда знаменитую do-нотацию для монад) - в JS просто отсутствует;

              5. программа как доказательство - в JS просто отсутствует, в TS даже не старались;

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


              1. ImagineTables
                11.05.2025 19:49

                оно же паттерн-матчинг - в зачаточном состоянии;

                В языке нет, и неизвестно когда будет (сам удивляюсь). Но есть внешние реализации в соответствии с пропозалом. Я остановился на этой (https://github.com/shuckster/match-iz), чего и всем рекомендую.

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


            1. Akon32
              11.05.2025 19:49

              Ну... В ООП основное средство выражения абстракций - объекты, в ФП - функции. Это не следующий уровень абстракции, они примерно эквивалентны (в ООП можно сделать объект "функция", который будет вести себя как функция, в ФП можно сделать функцию obj: (State,Args) -> (NextState,Result), которая преобразовывает состояние "объекта").
              Для практического примера использования ФП можно посмотреть, как используется map() на python (или на scala, или на другом языке):
              ```

              ys = list(map(lambda x:x*2),xs)

              или, в ООП-стиле:

              ys=[]
              for x in xs:
                ys.append(x.__mul__(2))

              Здесь мы передали функцию lambda x:x*2 в типовой цикл преобразования списка в другой список, реализованный в функции map(). Точно так же могли передать метод (2).__mul__вместо анонимной функции.

              Это не вся суть ФП, но наиболее частоиспользуемая, очевидная и полезная.


              1. askv
                11.05.2025 19:49

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

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


                1. Rsa97
                  11.05.2025 19:49

                  Ну так функции первого порядка и методы типа map или reduce как раз пришли из функционального программирования.
                  Само по себе функциональное программирование не сильно сложнее процедурного, просто требует другой логики. Иммутабельность переменных, отсутствие итеративных операторов (for, while), pattern matching.


                1. kogemrka
                  11.05.2025 19:49

                  Современные языки программирования заимствуют друг у друга хорошие идеи.

                  И вот у вас и в C++ уже много лет как есть самые настоящие замыкания (лямбды), и периодически пытаются завести в комитет пропозалы на pattern matching и, с другой стороны, есть вроде как считающаяся функциональной Scala, на которой вполне себе можно писать и в императивном стиле.


              1. bolk
                11.05.2025 19:49

                import operator
                # …
                ys.append(operator.mul(x, 2))

                :)


              1. netch80
                11.05.2025 19:49

                или, в ООП-стиле:

                Это не ООП-стиль, а процедурный (он же императивный). ООП ортогонально императивности или функциональности.


            1. Dhwtj
              11.05.2025 19:49

              На пальцах. Нестандартное объяснение.

              ФП замораживает время. Все время снаружи. А функции полноправные жители: создаются, принимаются и отправляются. И как аргумент и как результат.


              1. askv
                11.05.2025 19:49

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


                1. Dhwtj
                  11.05.2025 19:49

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


                  1. vanxant
                    11.05.2025 19:49

                    ... Как только определите pure версии функций fread и random)


    1. gun_dose
      11.05.2025 19:49

      Было бы логично, чтобы этот комментарий написал человек с ником php5, но никак не php7.


    1. SashkaCosmonaut
      11.05.2025 19:49

      Лично я гораздо чаще слышу: "используешь ООП -- лох". И полно таких статей на Хабре. Отсюда и холивары.


    1. Rorg
      11.05.2025 19:49

      "не принимайте критику от того, у кого вы не спросили бы совета." ©


    1. Devastator82
      11.05.2025 19:49

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


  1. oficsu
    11.05.2025 19:49

    ООП не нужен: смотри на Linux

    Цитируя мой же коммент к предыдущей статье:

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


    1. Chamie
      11.05.2025 19:49

      Да там теперь даже Rust есть…


      1. Viilture
        11.05.2025 19:49

        С учётом развития ИИ, может лучше не надо rust развивать.

        Пусть ИИ си код проверяет, rust всё равно чуть медленне будет.


        1. mayorovp
          11.05.2025 19:49

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


        1. Chamie
          11.05.2025 19:49

          Чего бы Расту всегда медленнее быть? А «ИИ» как раз в таких деталях и не справляется, когда нужно общую картину в голове представлять.


    1. edo1h
      11.05.2025 19:49

      Ну я бы не сказал «в немалых», ооп там используется адресно, там где выгода от него особенно заметна


    1. domix32
      11.05.2025 19:49

      Конечно, в ядре Linux не до полиморфизма.

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


    1. demotu
      11.05.2025 19:49

      Вы, видимо, имеете ввиду динамический полиморфизм в Linux ядре. Но он есть и в Haskell и в Rust, но ни тот ни другой не поддерживает ООП (нет наследования).


      1. oficsu
        11.05.2025 19:49

        Наследование доступно и на практике используется в C, как это и продемонстрировано по моей ссылке в разделе "Inheritance"


        1. demotu
          11.05.2025 19:49

          Я не говорил, что наследование нельзя реализовать в C. Но то, что оно используется в Linux Kernel - я не знал.


    1. kukovik
      11.05.2025 19:49

      Многие просто путают ООП и языки с встроенной поддержкой ООП. Поэтому у них Linux без ООП.


  1. oficsu
    11.05.2025 19:49

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

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


    1. xSVPx
      11.05.2025 19:49

      Так тогда вообще нет никаких проблем...

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


  1. slavcopost
    11.05.2025 19:49

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

    Тут я вслух прокричал "конечно стоит выбрасывать любую идею если она делает синтаксис сложнее"


    1. geher
      11.05.2025 19:49

      Иногда усложнение синтаксиса сильно упрощает понимание.


  1. ubpskh
    11.05.2025 19:49

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

    ООП должно делать код надёжнее, понятнее и проще в работе. Если этого не происходит, то надо подумать и сделать нормально.

    Либо же вообще в этом месте не применять, если не получается


    1. stay_protected
      11.05.2025 19:49

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


      1. Dhwtj
        11.05.2025 19:49

        вы просто не умеете их готовить

        Я умею их не готовить когда не нужно


    1. posledam
      11.05.2025 19:49

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


      1. nin-jin
        11.05.2025 19:49

        А что не так с договорами и их методами?


        1. posledam
          11.05.2025 19:49

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


          1. nin-jin
            11.05.2025 19:49

            А что такое "физический реальный договор"? Растровый скан распечатанного текста? Физическая симуляция взаимодействия молекул чернил с молекулами бумаги? Договор - это прежде всего объект бизнес процесса, абстракция.

            Метод "подписать" формирует цифровую подпись текста и прикрепляет её к договору. Когда все подписанты это сделали, договор считается заключённым. Всё. Через какие там события под капотом происходит синхронизация состояния договора между разными системами - не особо важно.


            1. posledam
              11.05.2025 19:49

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

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

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


              1. askv
                11.05.2025 19:49

                Кажется, я примерно понимаю о чём Вы пишете. В пределе это выливается в то, что программа начинает диктовать людям, как им жить, обычно в форме фразы: "у меня компьютер так посчитал, я ничего не могу сделать".


              1. digrobot
                11.05.2025 19:49

                Поэтому метод "Подписать" в классе это искажение реальности

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

                Новички об это часто спотыкаются

                Новички вообще обо всё спотыкаются, потому что они новички.


          1. Refridgerator
            11.05.2025 19:49

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


          1. mayorovp
            11.05.2025 19:49

            Что-то я не вижу как из одного следует другое.

            Если у нас есть противоречие между бизнесом и операционным учётом, то почему "виновато" ООП? И если у договора всё-таки появился метод "подписать", который меняет его состояние, то где тут противоречие?


            1. posledam
              11.05.2025 19:49

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

              Представьте, что бумажный паспорт имеет функцию "получить деньги на кассе" или "заключить сделку". Абсурд? Но когда мы пишем класс, с подобными методами, уже не абсурд :)


              1. mayorovp
                11.05.2025 19:49

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


                1. posledam
                  11.05.2025 19:49

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


                  1. Free_ze
                    11.05.2025 19:49

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

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


          1. VladimirLadynev
            11.05.2025 19:49

            Да, все верно. Чувствуется опыт.


  1. danilasar
    11.05.2025 19:49

    Возникло чувство, будто это пост-ответ на другую недавнюю публикацию) Совпало или действительно так, но в любом случае интересно наблюдать за развернувшейся полемикой


    1. Kahelman Автор
      11.05.2025 19:49

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


  1. ImagineTables
    11.05.2025 19:49

    ООП не нужен: смотри на Linux

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


    1. GospodinKolhoznik
      11.05.2025 19:49

      Классы нужны чтобы неявно передавать данные класса (поля) в процедуры класса (методы). Если вместо неявной передачи данных передавать их в явном виде, код станет только понятнее. И классы станут не нужны.


      1. mayorovp
        11.05.2025 19:49

        Во-первых, есть языки (Python, Rust) где аналог параметра this передаётся явно, и к его полям обращение идёт тоже явно. Но менее ООП они от этого не становятся.

        Во-вторых, от явных вызовов вида obj->vtbl->foo(obj, …) код понятнее не становится. Любая необходимость дублировать параметр делает код сложнее, а не проще.


        1. GospodinKolhoznik
          11.05.2025 19:49

          менее ООП они от этого не становятся

          Ещё как становятся. Если класс используется только как контейнер данных, то это уже не класс а структура данных и к ООП отношения не имеет.

          от явных вызовов вида ... код понятнее не становится

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


          1. posledam
            11.05.2025 19:49

            Согласен, для формошлёпства и перекладывания из DTO в JSON, ООП не нужен, всё это от лукавого.


          1. mayorovp
            11.05.2025 19:49

            Ещё как становятся. Если класс используется только как контейнер данных, то это уже не класс а структура данных и к ООП отношения не имеет.

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

            Кажется, вы как-то странно понимаете что такое контейнер для данных.

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

            Моя же многолетняя практика свидетельствует о том, что запись вида obj.foo(…) достаточно явная для понимания, и если кому-то доставляют сложности осознание откуда при этом выpове берётся this - ему надо учить язык, а не рассуждать о явном и неявном.


            1. GospodinKolhoznik
              11.05.2025 19:49

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

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

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

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


              1. mayorovp
                11.05.2025 19:49

                По моему если из класса убрать методы, [...]

                Погодите, а где я вообще писал про "убрать методы"? Я ж вам два языка привел, в которым обращения к полям явные, но и методы все на месте.

                Вы вообще с чем спорите?

                Что принципиально меняет замена obj.foo на this.foo в вашем примере [...]

                Как вы умудряетесь терять контекст диалога когда весь диалог прекрасно умещается на одном экране? Мои примеры были вот такие:

                1. "страшная" неявная передача this: obj.foo(bar, baz)

                2. "чудесная" явная передача без всяких ООП-излишеств: obj->vtbl->foo(obj, bar, baz)


                1. GospodinKolhoznik
                  11.05.2025 19:49

                  Вы вообще с чем спорите?

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

                  Мои примеры были вот такие

                  Почему во втором примере obj->vtbl->foo(obj, bar, baz) а не просто foo(obj, bar, baz) ? Зачем сюда тащить излишние ООП конструкции? ))


                  1. mayorovp
                    11.05.2025 19:49

                    Потому что иногда динамическая диспетчеризация всё-таки нужна. Кстати, это и на первое ваше утверждение отвечает.


                    1. GospodinKolhoznik
                      11.05.2025 19:49

                      Эта необходимость в динамической диспетчеризации вызвана ограничениями определённого языка программирования, или же это глобальная необходимость всего computer science как такового?

                      Просто если эта необходимость является фундаментальным принципом, это одно, а если это просто недоработка какого то конкретного языка, может быть надо просто bug report завести?


                      1. mayorovp
                        11.05.2025 19:49

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

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


          1. nin-jin
            11.05.2025 19:49

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

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


            1. GospodinKolhoznik
              11.05.2025 19:49

              Я высказал свои соображения. Можете их отрицать, можете быть несогласны. Дело ваше. Убеждать я вас ни в чём не буду))


              1. nin-jin
                11.05.2025 19:49

                Ой, неужели я тут общаюсь с самим Тимом Питерсом. Бывает же такое!


                1. GospodinKolhoznik
                  11.05.2025 19:49

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


                  1. nin-jin
                    11.05.2025 19:49

                    Фундаментальные истины общие для всех и в разных формулировках могут появляться спонтанно в разных мозгах. Но каждая глупость уникальна и дословно распространяется исключительно мыслевирусным путём.


                    1. GospodinKolhoznik
                      11.05.2025 19:49

                      Вы впадаете в крайности.


      1. sasha_semen
        11.05.2025 19:49

        Эх внутрях 1с не ковырялся. Там в порядке вещей 5 вложенных вызовов, в которые передаются структуры, на каждом следующем вызове эти структуры перекладываются в другие. В общем жутко получается. И это еще без динамических приколов.


      1. ImagineTables
        11.05.2025 19:49

        Классы нужны чтобы неявно передавать данные класса (поля) в процедуры класса (методы)

        Вам нужны?

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


  1. Jijiki
    11.05.2025 19:49

    мне без вектора в С тяжко буду признателен, поэтому ООП )


    1. IUIUIUIUIUIUIUI
      11.05.2025 19:49

      Хм, интересно, как я в хаскеле пользуюсь вектором без ООП.


  1. Vasjen
    11.05.2025 19:49

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

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


    1. Kerman
      11.05.2025 19:49

      Есть одно мерило хорошего кода – он работает

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

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

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

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

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

      Я сейчас наговорил кучу банальных вещей, простите.


      1. posledam
        11.05.2025 19:49

        Стоит всё же кое что добавить к сказанному. Споры вокруг ООП чаще всего напоминают спор глухого со слепым. Огромный пласт работы, в которой задействованы программисты, это императивная логика, построенная на вызове методов, аннотациях и условиях, а классы это 99% контейнеры данных, контейнеры логики (контроллеры например), просто наборы методов для внедрения в DI. Нет тут никакой потребности в инкапсуляции, что и от кого скрывать? Это верхнеуровневая логика, прямо за ней уже находится пользователь, а не другой программист. Код призван решать конкретную бизнес задачу. Он типовой, похож на копипасту, но для бизнеса он крайне важен, так как закрывает таску в джире и открывает новую фичу. В этих условиях нужно понять разработчика, ему этот ООП как филькина грамота. Даёшь функциональщину! Вот это дело. Паттерн матчинги, лямбды, вот это всё нужно. А ваши ООП, это для дедов :)


        1. FirExpl
          11.05.2025 19:49

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

          Инкапсуляция тут нужная для следующей цели: явно сказать другому программисту, что вот к этим данным/логике доступ есть только у класса by design, и если кому-то зачем-то вдруг потребовалось получить к этому доступ из вне, то он явно что-то делает не так и должен ещё раз подумать, а не фигню лю он делает. И бить по рукам компилятором за любые попытки игнорировать логику создателя класса.


          1. posledam
            11.05.2025 19:49

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


            1. FirExpl
              11.05.2025 19:49

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

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


              1. posledam
                11.05.2025 19:49

                Это всё понятно, тут наверное и вопросов нет нужно ли ООП, зачем ООП, кому всё это нужно, кому нужны эти наследования и инкапсуляции, давайте писать просто функции и структуры :)


        1. VladimirLadynev
          11.05.2025 19:49

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

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

          Я профессиональный погромист, если что.


          1. WASD1
            11.05.2025 19:49

            мне кажется это одно и то же (я бы даже сказал больше - простота рефакторинга это следствие хоршо использованного ООП).

            Ну ну то есть DataProduct - не обладает ни одним из свойств, а OOPProduct - обладает сразу обоими потому, что оба этих свойства взаимосвязаны:

            class DataProduct {
            public:
              int price;
            };
            
            class OOPPrucuct {
            ...
            public:
              int getPrice() const {... }
            };



        1. ImagineTables
          11.05.2025 19:49

          ему этот ООП как филькина грамота. Даёшь функциональщину! Вот это дело. Паттерн матчинги, лямбды, вот это всё нужно. А ваши ООП, это для дедов :)

          А это ООП или функциональщина?

          db.Categories    
            .GroupJoin(db.Products,
                Category => Category.CategoryId,
                Product => Product.CategoryId,
                (x, y) => new { Category = x, Products = y })
            .SelectMany(
                xy => xy.Products.DefaultIfEmpty(),
                (x, y) => new { Category = x.Category, Product = y })
            .Select(s => new
            {
                CategoryName = s.Category.Name,     
                ProductName = s.Product.Name   
            });
          


          1. inkelyad
            11.05.2025 19:49

            А это ООП или функциональщина?

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


      1. Vasjen
        11.05.2025 19:49

        Вы вырвали часть мысли и исказили, увы.

        Нет. Написать работающий код любой дурак может.

        Это пока бизнес-контекст относительно прост.

        Код пишется людьми и для людей

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

        Читаемость кода - это не лирика и не демагогия, как вам показалось.

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

        Технический долг - это не страшилки программеров.

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

        Понятный код способен ускорить на порядок разработку и снизить на порядок стоимость поддержки проекта

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

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

        Я сейчас наговорил кучу банальных вещей, простите.

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

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


        1. VladimirLadynev
          11.05.2025 19:49

          Есть одно мерило хорошего кода – он работает так, как ожидается и за него заплатили столько, сколько ожидалось. Все остальное лирика и демагогия в чистом виде. Хорошего, с точки зрения бизнеса. 

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

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

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


          1. Vasjen
            11.05.2025 19:49

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

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

            Самое обидное, что Вы даже не поймете в чем здесь дело.

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

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

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


        1. VladimirLadynev
          11.05.2025 19:49

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

          @Vasjen Да, Вы правы не существует метрик читаймости. И примеру с новым сотрудником сложно что-то противопоставить.

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

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

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

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


          1. Vasjen
            11.05.2025 19:49

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


        1. vdudouyt
          11.05.2025 19:49

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


        1. Kerman
          11.05.2025 19:49

          Код пишется для бизнеса

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

          С чем вы хотите поспорить? С тем что код чаще читается, чем пишется? Ну удачи.

          Что значит "для бизнеса"? Не для бизнеса.

          Я так тоже могу упростить до крайностей, смотрите: Бизнесу нет дела до кода, бизнес делает деньги. И всё, что ему нужно - это деньги. Код ему не нужен. Код - это вообще-то затраты на поддержку, а бизнес затраты не любит. Вывод: бизнес должен избегать написание кода.

          Нет метрик этой читаемости, увы.

          Да всмысле? Вот же сами пишете:

          Что вот можно взять нового сотрудника и он разберется, что в этих строчках происходит? Или за несколько минут/часов сможет найти баг в незнакомо проекте?

          Именно так. Вот тот самый пресловутый wtf/min. Есть ещё kloc, глубина наследования, связность классов.

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

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

          Вы можете сказать

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

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


        1. WASD1
          11.05.2025 19:49

          С одной стороны согласен с вами (хотя я работаю в системном программировании и у нас тут куча объективных perf- и compatibility- требований).

          Но вот по поводу читаемости - мне кажется вы просто повторяете софизм, которому 2000 лет (вероятно специально - хотите эпатировать оппонента).

          Да нельзя сказать С КАКОЙ ПЕСЧИНКОЙ ИМЕННО появилать "куча песка".
          Но несомненно существует "это - несколько песчинок, а это - уже куча песка".

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


      1. demotu
        11.05.2025 19:49

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


  1. Oeaoo
    11.05.2025 19:49

    ООП замечательно тем, что его можно хоронить бесконечно.


    1. atues
      11.05.2025 19:49

      Напомнило анекдот, извините :)

      Самолет терпит аварию, в живых на необитаемом острове остаются капитан, штурман и стюардесса. Через неделю капитан говорит: "Хватит разврата" и убивает стюардессу.

      Еще через неделю капитан говорит: "Хватит разврата" и закапывает стюардессу.

      Еще через неделю капитан говорит: "Хватит разврата" и выкапывает стюардессу


      1. Rorg
        11.05.2025 19:49

        А, так вот откуда взялась стюардесса. Я просто часто встречал фразу а-ля "зачем вы снова откопали стюардессу" и не мог понять откуда она.


        1. VladimirLadynev
          11.05.2025 19:49

          Может быть и хорошо, что Вы не знали.


  1. i-netay
    11.05.2025 19:49

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


  1. gorod0k
    11.05.2025 19:49

    Вспомнились холивары моей студенческой юности, "что лучше, c++ или Дельфи"


  1. tkovacs
    11.05.2025 19:49

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


  1. posledam
    11.05.2025 19:49

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


    1. dimas062
      11.05.2025 19:49

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


      1. posledam
        11.05.2025 19:49

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


        1. askv
          11.05.2025 19:49

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


          1. posledam
            11.05.2025 19:49

            Классика :)


          1. iamkisly
            11.05.2025 19:49

            Есть замечательный старый анекдот.

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

            Который совсем не анекдот, поэтому я обычно дублирую "я сделал" посты на Reddit.


            1. askv
              11.05.2025 19:49

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


            1. Okeu
              11.05.2025 19:49

              Анекдот не совсем жизовый, я как минимум видел жалобы на крайней степени токсичность у коммьюнити stackoverflow))


        1. dimas062
          11.05.2025 19:49

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


    1. VladimirLadynev
      11.05.2025 19:49

      Да. Да. В этой части Вы прямо апостол.


  1. askv
    11.05.2025 19:49

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

    Универсальная максима. Одной этой фразой можно заканчивать почти любой холивар. )


    1. posledam
      11.05.2025 19:49

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

      Вот самый банальный пример: "всё есть объект". Попытка глобального обобщения разбивается о суровую реальность. Когда "всё объект", технически это приводит к необходимости вот это "всё" держать в куче, чтобы была ссылка на объект. Но это не всегда рационально, местами крайне избыточно и сильно бьёт по производительности. И начинаются пляски, ну ладно "не всё объект" или по крайней мере не всегда, давайте вот отдельно выделим примитивы (Java), или объекты-структуры (ValueType, C#).


      1. askv
        11.05.2025 19:49

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


        1. posledam
          11.05.2025 19:49

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


          1. askv
            11.05.2025 19:49

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


      1. Kahelman Автор
        11.05.2025 19:49

        «Все есть объект и все надо держать в куче» это издержки реализации ООП в Java. Остальные мейнстримовые языки не лучше в этом смысле. Если не ошибаюсь Додо сих пор единственным ООП языком в «классическом» понимании можно считать только Simula. Где как раз и была реализована идея «посылки сообщения» объекту. Вы могли любое сообщение(вызов функции объекта в терминах C++, Java,C#) послать любому объекту. Далее объект либо обрабатывал его, либо возвращал not-implemented.

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

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

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

        У меня в свое время долго была путаница в понимании объекта и класса, поскольку в C++/Java де-факто классов нет, есть только тип, который назвали классом.

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


        1. posledam
          11.05.2025 19:49

          Ну далеко не только в Java же. Но везде есть свои, как говорится, приколы.

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


          1. KMiNT21
            11.05.2025 19:49

            чем строчка с вызовом метода у объекта по его ссылке не "отправка сообщения"?

            Тем, что такой подход плодит полную дичь, когда начинаются споры, подобные таким, как были тут комментариях к одной статье на тему ООП.
            - pizza.bake / - oven.bake pizza
            - cook.turn_on oven / oven.turn_on
            - box.wrap_up pizza / pizza.wrap_up_in_box
            - и т.п.

            Мышление на уровне отправки сообщений уменьшает вероятность того, что программист будет говорить пицце "приготовься". Так легче осознать зоны ответственности. Где данные (как пицца), а где Акторы.

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


            1. posledam
              11.05.2025 19:49

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

              В любом мало-мальском современном ЯП можно использовать такой подход, но удовольствия в этом мало, если применять вообще везде. Такое нужно применять когда в этом есть необходимость. Например, для распределённых вычислений, берём Akka или Orleans. Для стримов берём кафку, если синхронный реквест/реплай нужен, то городим огород на AMQP или берём Nats. Ну а если это монолит, то очереди в памяти, в гошке те же ченнелы.

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

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


              1. Kahelman Автор
                11.05.2025 19:49

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


                1. posledam
                  11.05.2025 19:49

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


                  1. Rsa97
                    11.05.2025 19:49

                    Подписываетесь на сообщения "Пользователь создан " и отправляете сообщение "Создать пользователя", добавляя уникальный маркер. Когда пришло сообщение "Пользователь создан" с этим маркером, отправляете сообщение "Добавить в корзину".


                    1. mayorovp
                      11.05.2025 19:49

                      Это уже событийная архитектура получается, что не тождественно отправке сообщений.


        1. PrisonerOfDarkMatter
          11.05.2025 19:49

          А за что тут ногами бить? Алан Кэй сам написал "Erlang is much closer to the original ideas I had about “objects” and how to use them"


        1. VladimirLadynev
          11.05.2025 19:49

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


        1. netch80
          11.05.2025 19:49

          Я предпочитаю называть два основных стиля ООП - "активные объекты" и "пассивные объекты". В случае Simula/etc. имеем первый. В случае C++, Java, C#, тысячи их - второй. Да, они разные.

          В Эрланге же у вас появляется класс gen-Server, который из которого создается процесс (объект).

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


      1. nin-jin
        11.05.2025 19:49

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

        Это, разумеется, не так. Простой пример на D:

        import std;
        
        void main() {
            
            uint foo = 1; // 1
            auto bar = Complex!float( 3, 4 ); // 3+4i
            
            writeln( foo.init, " ", bar.init ); // 0 nan+nani
            writeln( foo.sizeof, " ", bar.sizeof ); // 4 8
            writeln( foo.max, " ", bar.im.max ); // 4294967295 3.40282e+38
            
            writeln( (++foo).stringof ); // foo += cast(uint)1
            writeln( std.math.stringof ); // package math
            
        }


        1. posledam
          11.05.2025 19:49

          Не знаком к сожалению с синтаксисом D. Вижу тут выведение типа через auto, нет объекта как такового, это структура и компилятор явно вызывает известные на момент компиляции методы применительно к конкретной структуре известного типа, поэтому это работает на стеке. А давайте в общий базовый тип и вызовем метод, общий для всех объектов. Получится?

          Пример на C#

          object v = 42;
          // вызов метода общего для всех-всех объектов
          Console.WriteLine(v.ToString()); // выведет: 42
          

          Компилятор "не знает" чей ToString() я вызываю, в рантайме вызывается метод, вычисляемый для конкретного экземпляра, через vtable.


          1. domix32
            11.05.2025 19:49

            я вызываю, в рантайме вызывается метод, вычисляемый для конкретного экземпляра, через vtable.

            Разве C# не использует девиртуализацию и инлайнинг? Хоть он и с GC, но вроде он все ещё компилируемый.


            1. Free_ze
              11.05.2025 19:49

              Это сработает на этапе JIT-компиляции, а в байткоде - честный callvirt.


            1. posledam
              11.05.2025 19:49

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


          1. mayorovp
            11.05.2025 19:49

            Конкретно в вашем случае объект оказался в куче не из-за вызова ToString, а из-за приведения к object, прямой вызов 42.ToString() без особых проблем выполняется на стеке.

            И даже если усложнить пример, сделав так чтобы был вызван именно метод базового класса - он всё равно будет вызван на стеке, спасибо механизму constrained call:

            Foo foo;
            Console.WriteLine(foo.ToString());
            // …
            struct Foo {}
            


            1. posledam
              11.05.2025 19:49

              42.ToString() выполняется на стеке только благодаря костылю .NET, в виде ValueObject, который с одной стороны наследуется от Object, с другой стороны не является ссылочным типом, пока его не присвоили в object (boxing). И это простой пример, потому как обычно, в стек много не положишь, а объектов нужно всяких много. Где же им ещё размещаться, как не в куче?


              1. mayorovp
                11.05.2025 19:49

                А с чего вдруг значимые типы (value types) костыль-то?


                1. posledam
                  11.05.2025 19:49

                  Это моё ИМХО :) Введение значимых типов в язык это очень хорошо для производительности, но из стройной иерархии "всё есть объект" очень выбивается. В последних версиях дотнета большой упор на поддержку структур, стековые ссылки, readonly-структуры. Но выглядит всё как костыль, хоть и добротный. Взять например отсутствие возможности закрыть дефолтный конструктор и определить свой иницилизатор, подковёрные игры с duck typing (в using), всё это хорошо, но очень непрозрачно.


          1. Free_ze
            11.05.2025 19:49

            std.stdio.write - шаблонная функция, полагаю, вам намекают на статический полиморфизм. Кстати, в том же C# компилятор умеет делать мономорфизацию для аргументов-типов в дженериках с where T: struct, что позволяет обходиться без боксинга для значимых типов.


            1. posledam
              11.05.2025 19:49

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


              1. Free_ze
                11.05.2025 19:49

                А это уже не проблема или ограничение C#. Если надо - кладите структуру в другую структуру и в Span/stackalloc, язык это позволяет.


          1. nin-jin
            11.05.2025 19:49

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


      1. Proscrito
        11.05.2025 19:49

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

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


  1. gun_dose
    11.05.2025 19:49

    «Никто не знает, что такое ООП»

    Благо в php этот вопрос легко решён: если в коде есть стрелочки "->", значит это ООП.


    1. netch80
      11.05.2025 19:49

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


      1. posledam
        11.05.2025 19:49

        Хах :) Вопрос с подвохом.


      1. gun_dose
        11.05.2025 19:49

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

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


        1. netch80
          11.05.2025 19:49

          Но если вам так нравятся мыслительные упражнения

          Давайте без таких излишне полемических приёмов.

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

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

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

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


          1. gun_dose
            11.05.2025 19:49

            Касаемо развития и сопровождения, всё зависит от используемого языка. Например, в php-коде отсутствие ООП - это признак легаси. А вот в js применение ООП уместно разве что для разграничения пространства имён функций.

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


            1. Kahelman Автор
              11.05.2025 19:49

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


              1. gun_dose
                11.05.2025 19:49

                Всё зависит от того, что за проект. Например, если взять WordPress или Drupal 7 и более ранней версии, то там ООП практически не используется. Если взять OpenCart или Битрикс, то там ООП привинчен практически без всякого понятия, именно чтобы было.

                Но если брать Laravel, Symfony, Drupal 8 и более поздних версий, то там всё сделано вокруг ООП, и всё красиво, модно, элегантно, а главное понятно.

                Я сам начинал писать на php ещё 12 лет назад на Drupal 7. Там всё было полностью процедурно, а если и были какие-то объекты, то это был stdClass (в php так называется самый базовый класс, от которого наследуются все остальные). И когда я в 2016-2017 стал переходить на Drupal 8, по началу мне было тяжело, потому что там повсеместно (хоть и не везде) был ООП-подход. Помню тогда очень многие плевались, что стало якобы непонятно и тяжело. Но набив руку и разобравшись как с самим ООП, так и с новым API, я понял, насколько огромные преимущества даёт ООП. Если в Drupal 7 и более ранних версиях функционал каждого модуля писался в огромном файле, где было 2-3 тысячи строк и несколько десятков функций, то сейчас файлов стало больше, но они очёнь чётко структурированы, разложены по пространствам имён и т.д. Структура настолько понятная, что даже если мне надо посмотреть, как что-то сделано в незнакомом мне модуле, я безошибочно могу с ходу открыть нужный мне файл, не читая документацию и не запуская отладчик.

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

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


        1. posledam
          11.05.2025 19:49

          Если я не пользуюсь самолётами, а езжу только поездами, можно ли считать, что в моём мире не существует самолётов?


  1. Stanislav_Z
    11.05.2025 19:49

    Обсуждения на тему понимания ООП похоже также бессмертны, как и "Были ли американцы на луне"


  1. gsaw
    11.05.2025 19:49

    Никто и не говорит, что ООП мертв. Мертвы люди которые ООП использовали :)

    В нынешнем проекте к примеру, объекты все сплошь и рядом тупые контейнеры для данных. Причем все value objects, одноразовые. Вся логика для работы с ними в совсем других классах. "Dog" не гавкает и базовый класс у него не "Animal". Инкапсуляция вроде бы и есть, но class это скорее просто какой то stateless модуль с набором функций.

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

    Из-за выше перечисленных двух пунктов и наследования как такового не используется. Чаще только в каких нибудь утилитарных классах.

    Ещё и реакторное функциональное программирование все больше и больше проникает в java

    Я не говорю, что ООП мертво, скорее как и во всем, побеждает более прагматичный подход. В нулевых к примеру, что бы сделать RPC вызов, надо было бороться с какой нибудь CORBA, описывать все в XML, а сейчас достаточно http и Json в 80% случаев.

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


    1. posledam
      11.05.2025 19:49

      Всё зависит от применения. Прикладная логика редко требует разработки классов. В основном это чистый императив и DTO. На этой почве чаще всего и звучат "ООП нинужен", когда основная часть работы это перекладывание данных из JSON в DTO и запросы в БД. При чём на плечах огромной кучи библиотек и платформы, с кучей классов под капотом. По той же логике можно с уверенностью сказать, что микроэлектронника не нужна. Да, у меня есть телефон, куча аппаратуры, я просто кнопки жму, зачем мне нужна ваша микроэлектронника? :)

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

      Утверждения про "побеждает", это примерно как щупать в слепую слона за хобот и утверждать, что хобот, это всё что нужно, хобот победил :)


    1. mayorovp
      11.05.2025 19:49

      В нулевых к примеру, что бы сделать RPC вызов, надо было бороться с какой нибудь CORBA, описывать все в XML, а сейчас достаточно http и Json в 80% случаев.

      На самом деле это больше была проблема инструмента, а не подхода. Так-то в итоге с теми же http и Json индустрия пришла в целом к тому же - contract first, кодогенерация по возможности. И к ООП тут вообще ничего не привязано.


  1. arutune
    11.05.2025 19:49

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


  1. netch80
    11.05.2025 19:49

    ООП не нужен: смотри на Linux

    Смешно тут то, что авторы таких утверждений не понимают (или не хотят признавать), что Linux, и ядро любого Unix, и ядро Windows - они все на ООП как раз классического пассивного, не-Кеевского типа. Полиморфизм на виртуальных функциях - в полный рост. Уровень сисколлов: есть универсальный read() на всех, write(), close(), fcntl(), вплоть до epoll и io_uring, ко всем применяются одинаковые методы для большинства работ, внутри происходит переключение. В реализации read(), например, ret = file->f_op->read_iter(&kiocb, &iter); - f_op это Virtual Method Table.

    Инкапсуляция делается только на границе user land / kernel land, да. Но это ограничение языка. Был бы даже очень урезанный C++ - всякие private и protected были бы везде. А пока следят на уровне верификации кода (начиная с визуальной).

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

    Так что вы с этим

    Конечно, в ядре Linux не до полиморфизма

    неправы, Linux ещё больше играет за вашу же команду: ООП нужен - там, где удобен.


    1. mayorovp
      11.05.2025 19:49

      Наследования в явном виде очень мало, да.

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


    1. DenSigma
      11.05.2025 19:49

      ООП, как вы привели пример из Линукса - это всего лишь организация кода, и подозреваю, не единственно возможный. Довольно странно реализовывать и зашивать ПРЯМО В ЯЗЫК эту организацию.

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

      Имхо, достаточно было бы в Си добавить средства, облегчающие организацию VMT, и на этом стоило бы закончить.

      Апд. Еще бы, имхо, полезно было бы добавить модули и переменные модулей с системой инициализации, чтобы можно было организовать что-то типа Spring с DI, и было бы вообще замечательно.


      1. mayorovp
        11.05.2025 19:49

        Имхо, достаточно было бы в Си добавить средства, облегчающие организацию VMT, и на этом стоило бы закончить.

        …и эти средства называются как? Правильно, виртуальные методы. Которым нужны классы, и вот уже ООП в язык подъехало.

        Апд. Еще бы, имхо, полезно было бы добавить модули и переменные модулей с системой инициализации, чтобы можно было организовать что-то типа Spring с DI, и было бы вообще замечательно.

        Иронично, что это вы пишете сразу после своего прошлого комментария, хотя Spring с DI - это довольно сложная конструкция, которая куда сложнее в реализации чем ООП в каком-нибудь С++.


        1. Kahelman Автор
          11.05.2025 19:49

          Так у Apple вроде был Objective-C- C with classes, вместо «православного» С++, но народ в общем и целом предпочел C++


      1. netch80
        11.05.2025 19:49

        Имхо, достаточно было бы в Си добавить средства, облегчающие организацию VMT, и на этом стоило бы закончить.

        VMT - раз.
        private - два (надо же защищать от внешнего неавторизованного доступа).
        namespaces - три (есть тут у меня один компонент, названия типа rrx_sub_trr_pkt_new задалбывают).

        Вот уже именно что языковые средства и 1/5...1/4 от C++ уже есть.

        И что странного в зашивке в язык, если там всё равно уже зашито 100500 всего начиная с типов, а это конкретно - используется очень значительной частью софта?


  1. SystemSoft
    11.05.2025 19:49

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


  1. ALexKud
    11.05.2025 19:49

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


  1. panzerfaust
    11.05.2025 19:49

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


  1. ponikrf
    11.05.2025 19:49

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