(Объектно-Ориентированное Помешательство)

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

Симптомы:

1. Клиническая полиморфофилия

  • Больной не может написать простой метод, не завернув его в десяток интерфейсов и абстракций.

  • Любая функция превращается в класс с тремя уровнями наследования.

Пример:

Вместо `print("Hello, World!")` больной пишет:

class Message:
    def get_text(self):
        pass

class HelloWorldMessage(Message):
    def get_text(self):
        return "Hello, World!"

class MessagePrinter:
    def print(self, message: Message):
        print(message.get_text())

printer = MessagePrinter()
printer.print(HelloWorldMessage())

“Зато гибкость!” – уверяет больной.

2. Синдром “Фабрики фабричных фабрик”

  • Каждая новая сущность создаётся исключительно через фабричные методы или фабрики.

  • Больной испытывает тревогу, если объект создаётся без фабрики.

Пример:

class Car:
    pass

class CarFactory:
    def create_car(self):
        return Car()

class CarFactoryFactory:
    def create_factory(self):
        return CarFactory()

factory = CarFactoryFactory().create_factory()
car = factory.create_car()

Больной гордится “гибкостью” системы, хотя коллеги в шоке.

3. “Наследовать – значит существовать”

  • Пациент не может создать сущность без наследования.

  • Даже простые структуры данных превращаются в сложные иерархии.

Пример:

class Animal:
    def make_sound(self):
        pass

class Mammal(Animal):
    pass

class Primate(Mammal):
    pass

class Human(Primate):
    def make_sound(self):
        print("Hello, World!")

person = Human()
person.make_sound()

На вопрос “Зачем столько уровней?” больной отвечает: “На будущее, для расширяемости!”

4. Обсессивное применение паттернов проектирования

  • Пациент не может писать код без применения какого-либо паттерна.

  • Даже самые простые задачи решает через стратегию, декоратор или мост.

  • Отрицает существование кода, написанного без паттернов.

Пример:

Вместо простого условия:

if user.role == "admin":
    grant_access()

Больной пишет:

class RoleStrategy:
    def grant_access(self):
        pass

class AdminRole(RoleStrategy):
    def grant_access(self):
        grant_access()

strategy = AdminRole()
strategy.grant_access()

“Так ведь SOLID!” – гордо заявляет больной.

5. Полное отрицание процедурного и функционального программирования

  • Больной считает, что процедурный код – это признак непрофессионализма.

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

  • Каждая функция превращается в метод класса, даже если ей это не нужно.

Пример:

def add(a, b):
    return a + b

Пациент переписывает на:

from abc import ABC, abstractmethod

# Абстрактный класс для чисел
class Number(ABC):
    @abstractmethod
    def get_value(self):
        pass

# Конкретная реализация чисел
class Integer(Number):
    def __init__(self, value: int):
        self.value = value

    def get_value(self):
        return self.value

# Абстрактный класс калькулятора
class Calculator(ABC):
    @abstractmethod
    def add(self, a: Number, b: Number) -> Number:
        pass

# Конкретная реализация калькулятора
class BasicCalculator(Calculator):
    def add(self, a: Number, b: Number) -> Number:
        return Integer(a.get_value() + b.get_value())

# Использование
num1 = Integer(5)
num2 = Integer(10)
calculator = BasicCalculator()

result = calculator.add(num1, num2)
print(result.get_value())  # Выведет: 15

“Объектно-ориентированный подход!” – уверяет больной.

Методы лечения:

1. Шоковая терапия: заставить пациента написать проект на чистом C или Go.

2. Функциональное программирование: вводить в рацион элементы Haskell и Elixir.

3. Чтение кода Кена Томпсона и Роберта Мартина: помогает осознать, что хороший код – это не про количество классов.

4. Детокс: временный запрет на DI-контейнеры и фабрики.

5. Терапия процедурными скриптами: написать полезный скрипт в 10 строк, осознать, что это работает, и заплакать.

Прогноз:

  • В лёгких случаях пациенты могут вернуться к нормальному программированию.

  • В тяжёлых случаях остаются архитекторами на Java и требуют рефакторинга даже у домашнего ToDo-списка.

Заключение

«ООП головного мозга» – опасное расстройство, приводящее к избыточной сложности кода. Если ваш коллега пишет адаптер для вывода “Hello, World!”, немедленно вызывайте специалиста!

P.S.: Текст полностью написан ChatGPT, но он настолько хорош, что не мог не поделиться ))

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


  1. kalbas
    30.01.2025 07:33

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


  1. dv0ich
    30.01.2025 07:33

    Слепое фанатичное следование чему угодно - даже самой Лучшей, Доброй и Гениальной концепции - порождает только проблемы, дичь, трэш и угар.

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

    У каждой медали есть обратная сторона и это надо бы учитывать.


    1. soul-catcher
      30.01.2025 07:33

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

      В примерах кода я не увидел ни одного применения паттерна.

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

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

      UPD: поэтому мой голос за то, что автор не понимает ООП и не знает паттернов проектирования.


    1. stanislavskijvlad
      30.01.2025 07:33

      После ваших слов захотелось пересмотреть фильм "Догма".


  1. a-tk
    30.01.2025 07:33

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


    1. ionicman
      30.01.2025 07:33

      Проблемы 3:

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

      2. Попытка использовать везде одни и теже инструменты и подходы. Типа: "ООП и СОЛИД хорошо - везде про это написано, давайте и тут запилим" - а там одна функция из 10 строк во временном скрипте, который один раз в жизни должен выполнится для получения временых данных, которые будут использованы один раз - зато круто и расширяемо и по бест практис :)

      3. Большинcтво компонентов софта не живет больше 1-2 лет, за исключением энтерпрайза и некоторых других исключений, не надо думать и закладывать туда все возможное и делать максимально универсально, нужно всегда делать балансируя между достаточной универсальностью и простотой - и именно это и есть золотая грань, которую да - очень сложно держать. Не надо бояться переписывать и рефакторить - иногда проще и быстрее переписать компонент с нуля на современном фрейморке и в современной парадигме, учтя опыт его текущего использования и контекста, чем пытаться патчить/расширять существующий.

      Ну и, всегда стоит помнить статью "Вы - не Гугл" :)


      1. tolyanski
        30.01.2025 07:33

        Большинcтво компонентов софта не живет больше 1-2 лет

        эт конечно вы загнули) БОЛЬШИНСТВО компонентов живет 5-10-15 лет, к сожалению...

        Не надо бояться переписывать

        пока по башке не получили от продакта или собственника бизнеса


        1. Wendor
          30.01.2025 07:33

          Про 1-2 года.... я даже услышал как WordPad/notepad/calc икнули)


        1. a-tk
          30.01.2025 07:33

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


      1. avshkol
        30.01.2025 07:33

        Как раз раскладываение кода по разным ящикам - один из способов управления сложностью.


        1. a-tk
          30.01.2025 07:33

          Особенно если на ящиках нормально написано, что в них лежит.


      1. pes_loxmaty
        30.01.2025 07:33

        Это не управление сложностью, а перекладывание ее по разным ящикам

        Так ведь divide et impera

        Вам вероятно не попадались проекты такого размера, что он не может уместиться целиком в голове одного человека (ну во всяком случае новичек в команде не сможет преисполниться за вменяемое время)


      1. Nipheris
        30.01.2025 07:33

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

        Тут что-то на фронтэндерском, не получается прочитать.


      1. mitix
        30.01.2025 07:33

        Про "сложность - это всегда константа", честно говоря не понял, что это значит?


      1. Dhwtj
        30.01.2025 07:33

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


    1. breninsul
      30.01.2025 07:33

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

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

      В общем-то слепое следование догматам никогда ни к чему хорошему не приведёт


      1. ScratchBoom
        30.01.2025 07:33

        Я такое в основном встречал в сгенерённом коде в библиотеках для AWS


      1. a-tk
        30.01.2025 07:33

        А Вы уверены, что то решение не было написано чьей-то кровью на стене?


    1. SpiderEkb
      30.01.2025 07:33

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

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


    1. Ritan
      30.01.2025 07:33

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


    1. Dhwtj
      30.01.2025 07:33

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

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


  1. ednersky
    30.01.2025 07:33

    Спасибо за статью. Давно хочу точно такую написать про типы и хейтинг исключений, которые, увы, "всё заполонили", но пока руки так и не дошли.


  1. Juzujka
    30.01.2025 07:33

    Хорошо бы и промпт для ChatGPT приложить. Мы же на Хабре, интересуемся исходниками.


    1. avshkol
      30.01.2025 07:33

      Универсальный ответ в 2025 году и далее: ))))

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

      Промпт:

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

      1. Симптомы болезни:

        • Чрезмерное использование паттернов проектирования даже в простых задачах.

        • Отрицание процедурного и функционального программирования.

        • Превращение каждой функции в метод класса, даже если это не нужно.

      2. Примеры кода:

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

        • Пример переписывания простой функции сложения чисел в сложную иерархию классов.

      3. Методы лечения:

        • Шоковая терапия (например, написание кода на чистом C или Go).

        • Введение в рацион функционального программирования (Haskell, Elixir).

        • Чтение кода известных программистов, которые ценят простоту.

        • Временный запрет на использование DI-контейнеров и фабрик.

        • Написание простых процедурных скриптов для осознания их эффективности.

      4. Прогноз:

        • В лёгких случаях пациенты могут вернуться к нормальному программированию.

        • В тяжёлых случаях остаются архитекторами на Java и требуют рефакторинга даже у домашнего ToDo-списка.

      5. Заключение:

        • Подчеркни, что "ООП головного мозга" – это опасное расстройство, приводящее к избыточной сложности кода.

        • Добавь шутку о том, что если коллега пишет адаптер для вывода "Hello, World!", то нужно срочно вызывать специалиста.

      6. P.S.:

        • Упомяни, что текст написан ChatGPT, но он настолько хорош, что им стоит поделиться.

      7. Опрос:

        • Добавь шуточный опрос в конце: "Действительно ли существует такая болезнь?" с вариантами ответов:

          • Да, иногда встречаюсь.

          • Я сам тяжело болен.

          • Автор просто не понимает ООП и не знает паттернов проектирования, пытаясь казаться умнее других!!!

      Этот промпт должен помочь сгенерировать статью в нужном стиле.


      1. tolyanski
        30.01.2025 07:33

        промпт размером почти как сама статья))


      1. stanislavskijvlad
        30.01.2025 07:33

        Получилось очень похоже.

        Отличия

        Симптомы болезни:

        1. Паттернизация всего и вся: ОГМ проявляется в виде маниакального стремления применить паттерны проектирования в каждой, даже самой простой задаче. Больной с ОГМ не напишет простой цикл – он реализует итератор. Ему не нужно условие if, ему нужна стратегия!

        2. ООП-фундаментализм: Наблюдается стойкое отрицание процедурного и функционального программирования. Любые попытки убедить пациента в преимуществах других подходов встречают категорическое сопротивление и аргумент “но это же не ООП!”.

        3. Методизация всего: Любая функция, даже предназначенная для единичного действия, автоматически становится методом класса. “Почему бы не сделать класс Printer с методом printMessage?” - спрашивает больной, в то время как простой print("message") был бы в разы лаконичнее.

        class AgeCheckStrategy:
        def check(self, age):
        pass

        class AdultStrategy(AgeCheckStrategy):
        def check(self, age):
        if age >= 18:
        return "Совершеннолетний"

        class MinorStrategy(AgeCheckStrategy):
        def check(self, age):
        if age < 18:
        return "Несовершеннолетний"

        class AgeChecker:
        def init(self, strategy):
        self._strategy = strategy

        def check_age(self, age):    return self._strategy.check(age)
        

        age_checker = AgeChecker(AdultStrategy()) # А если нужно будет для пенсионеров? А для школьников?
        result = age_checker.check_age(19)

        Хотелось бы увидеть результат этого промта от Deep Seek.