Я не понимаю механику развала проекта, если пул-реквесты отвергаются без брани. Изменения не попали в код, пояснения даны, что произошло бы ужасного, если бы это просто сопровождалось словами "отвергаю по двум причинам: у этой функции такие-то пороки, а также нарушен срок подачи пр-ов"
Каким образом после этих слов развалится проект ядра линукса, не очень понятно
Нельзя прийти, к примеру, в гостиницу, и сказать: слушайте, у вас всё равно эти номера пустуют, я тут незаметно поживу бесплатно. Вы же ничего не потеряете!
Или подойти к гиду, который ведёт экскурсию, и сказать: ну мы тут рядом постоим послушаем, с вас не убудет, платить не будем, продолжайте, пожалуйста.
Да даже элементарный заяц в метро не может оправдаться тем, что он для поезда и инфраструктуры ничтожная нагрузка и фактически метро ничего не потеряет, провезя его бесплатно.
Разумеется, для нематериальных товаров физический переход от владельца к потребителю не происходит, и это очень легко эксплуатировать в свою пользу. Просто из этого не следует, что неоплаченное потребление нематериальных товаров чем-то отличается от неоплаченного потребления материальных товаров. А уж назвать это воровством или ровостмом, дело десятое.
Как только выяснится, что для вычисления рейтинга необходимо передать ещё один какой-нибудь параметр/зависимость, а выяснится это на этапе реализации алгоритма вычисления рейтинга, придётся бежать по всем тестам и править вызовы. А там уже и ещё какие-то новости в сигнатурах всплывут.
Чего принципиально не хватает в постановке задачи "написать программу, выигрывающую в шахматы"?
Принципиально то, что я не знаю хороших практик решения этой задачи, я никогда этим не занимался. Понятно, что надо как-то в глубину просчитывать ветви ходов и оценивать полученные позиции. Так ли это, может я что-то упускаю? Как отсекать? Как оценивать? Возможно, для оценки нужны ещё какие-то вспомогательные абстракции? Может быть, есть ещё какие-то стадии решения? Всего этого я не знаю. Нужна постановка задачи от эксперта.
И такая постановка позволит лучше декомпозировать решение. В том числе и в ООП-парадигме, почему нет.
А если предположить, что наш шахматный движок имеет какую-то степень абстракции и позволит дёшево реализовывать другие игры со схожим флоу, то ООП станет основной практикой. Реализовал, грубо говоря, интерфейс "правила игры" и "оценка позиции" для шашек - и ура, пользуйся, все эти доски и алгоритмы принятия решения будут автоматически переиспользованы.
Короче, ничего ужасного в уместном применении ООП нет. Если с ума не сходить.
Я ничего не знаю про программирование шахмат, так что дальше вольная фантазия. Очевидно, там существуют уже устоявшиеся методики, которые не сочинить в рамках сочинения случайного комментария на хабре
Но нет ничего невероятного, то в шахматах, написанных с использованием ООП, будут:
примитивный класс хранения состояния игры (доска), просто сохраняет инварианты, к примеру, не позволяет поставить две фигуры на одну клетку.
наверное, при реализации логики понадобится возможность итерироваться по дереву возможных вариантов ходов. Это удобно реализовать в виде класса, ведь это же просто контейнер, дерево положений доски со своими инвариантами. И, возможно, с какими-то дополнительными промежуточными данными, которые можно привязать к узлам.
Наверняка есть какие-то вспомогательные абстракции - например, оценка позиции. И наверняка их методики бывают разные, и у них есть состояние (например, кэш предыдущих рассуждений), поэтому они кандидаты на общий интерфейс и реализация в классах.
и, допустим, самый корневой класс, принимающий решение за игрока, строящий логику выбора следующего хода. Он через DI принимает предыдущие.
ну и так далее, нужна постановка задачи, это всё вольная фантазия, дело не в моих выдумках, а в том...
А в том, что вы сами выдумали себе какой-то свой ужасный ООП, в котором программисты моделируют не объекты предметной области, а объекты материального мира: класс для доски, потом класс для клетки, для белого и чёрного цвета, для пешек и ладей - и теперь с этим успешно боретесь.
Но так никто не делает, вы боретесь с демонами в своей голове. Классы для фигур не нужны. А для абстракций, участвующих в принятии решений - вполне могут оказаться полезны.
Как пример для статьи про ООП на хабре? Почему, собственно, нет? Речь не идёт про промышленную универсальную реализацию, вы даже не знаете, какие требования будут к такой очереди, но уже лезете в бутылку. Вполне можно навертеть ООП-абстракций для примера, начиная от иерархии самих типов сообщений и заканчивая какими-нибудь, я не знаю, подписчиками. Это иллюстративный материал для статьи, он не обязан летать на утюгах.
Ах да, я вспомнил, вы тот самый любитель общественного внимания, который обращается к собеседнику "тупой дегенерат", когда его самого макают в, назовём это так, чрезмерную широту обобщений на фоне ограниченнго кругозора. Тогда вопросов не имею.
Мы пишем класс (и прочими способами упрощаем поддержку кода), потому что писатель кода и читатель могут различаться, да (это может быть и один человек, но в разное время). Это действительно причина
Код, в котором никому никогда не надо будет разбираться и поддерживать, всё равно, в какой парадигме писать
Семантика владения и прочие детали важны при написании кода (и то в большинстве случаев компилятор не даст ошибиться).
Но код читается кратно больше, чем пишется. И когнитивная нагрузка - это про чтение, а не про написание. Здесь алиасы работают, как хорошее именование переменных и даже как конструирование типов - упрощает код.
Слушайте, если у вас всё надо заменить, чтобы вас правильно понять, может, вы уже признаете, что пример плохой? Задача организации очереди сообщений это другая задача и действительно служила бы лучше целям статьи.
Казалось бы, наоборот? Если я знаю, что FooPtr это некий уместный в данном контексте тип указателя, то я не думаю о нижележащем типе и когнитивная нагрузка падает?
Мне неважно, что он юник или шейред, мне важно, что он указывает на Foo и используется в заданной сигнатуре. Остаётся только нужная информация. Нагрузка падает.
Да господи, стандартная библиотека в 2025-м году от РХ у него хак. Как будто кто-то запрещает писать на плюсах в процедурном стиле. Ну возьмите раст, там enum из коробки - тот же вариант. Код ещё в три раза короче станет, кстати.
Вы по-прежнему не туда воюете, я уже сороковой комментарий подряд пытаюсь вам объяснить, что проблема не в ООП, а в вашей статье, в которой выбран неудачный подход демонстрации достоинств ООП. Ладно, это бесполезно.
зачем в коллекцию? В вашем примере коллекция никак не используется
но если есть какая-то ломовая необходимость в коллекции конкретно в этом микроскопическом примере, у вас есть стандартный std::vector<std::variant>
Понимаете, вы сейчас начнёте накручивать требования, которых нет в примере. Моё замечание было не про ООП (это мощный и полезный подход во множестве случаев), а про ваш пример. Он не иллюстрирует сильные стороны ООП. Поэтому идея соревнования в решении этой задачи в разных парадигмах не имеет смысла.
Это очень плохой пример, потому что для игрушечных задач ООП не нужен. Он нужен для сложных абстракций, для разделения когнитивной нагрузки между группами разработчиков. У вас никогда не будет отдельной группы разработчиков для кружочков, а отдельной - для треугольничков.
Давайте попробуем вернуться в реальность и представим, что эти квадратики - что-то более-менее сложное. Очевидно, функции draw() должны обращаться к каким-то связанным с рисованием зависимостям (как минимум, тянуть заголовочные файлы). Но сами прямоугольники могут использоваться в контекстах, которые не подразумевают никакой связи с рисованием. Например, я не знаю, библиотека, которая вычисляет пересечения прямоугольников. На кой ляд ей draw() и все её зависимости?
А значит, фигура у нас разбивается на две части: Rectangle и RectangleDrawer (если предположить, что у рисовальщика есть состояние, например, кэш, и просто функции недостаточно, то понадобится класс), а RectangleDrawer станет частью своей иерархии. Они будут связываться, к примеру, как визиторы, и тут...
И тут в помещение вбегают критики ООП и говорят, что вот наворотили дикий оверинжиниринг! И они правы, потому что для этой примера достаточно POD-структур, для их хранения - несколько векторов, а для рисования - перегруженных (и даже это необязательно) свободных функций. Плохой пример, негодный. Надо придумать пример реального размера, в котором ООП действительно нужно.
ООП, разумеется, не панацея, оно придумано, чтобы снимать когнитивную нагрузку. Её нужно снимать, если а) предметная область большая, не десятки, а сотни и тысячи разнородных сущностей со сложными связями. б) работает много программистов, которые увольняются и приходят на протяжении долглих лет
Ты смотришь на код первый и последний раз, тебе надо что-то сделать и не испортить. Использовать готовый объект, скрывающий состояние, а ещё лучше - реализующий известный интерфейс - идеальное для этого решение. Спасибо тому, кто его создал!
Если вы делаете магазин размером в два человеко-месяца, который никто не будет сопровождать, без ООП легко можно обойтись.
Методологическая проблема поста.
Типичная работа программиста в мало-мальски объёмном проекте это поиск компромиссов и оценка рисков. Сделал оптимально - плохо читается. Сделал читаемо - трудно расширять. Сделал расширяемо - бьют по голове за оверинжиниринг.
И так далее. Постоянный поиск компромиссов. Этой проблемы нет, только если ты пишешь в команде из трёх человек, в которой ты главный.
Отсюда следует, что если кто-то на голубом глазу пишет статью "Такой-то подход - скам" (не с кликбейтными целями, а от души), то он принципиально неспособен к этому поиску баланса, у него не развита ответственная за это часть профессионализма.
Знаете, очень крутой комментарий, им совершенно невозможно оскорбиться! Пытаясь сопоставить слово "диффамация" в вашем исполнении с его словарным значением, я не могу быть уверен, что и, к примеру, выражение "тупой дегенерат" для вас означает то же самое, что и для других носителей русского языка.
Это даже даёт какую-то надежду. Возможно, и прочие слова из вашего опуса также следует понимать в каком-то новом, одному вам ведомом поэтическом смысле. Возможно, под инкапсуляцией вы подразумеваете инсоляцию, а под типизацией пиритизацию. Тогда, конечно, никаких претензий быть не может.
Миллион мух, разумеется, имеют гораздо более разнообразный опыт, чем одна муха. Которая, к примеру, пишет, я цитирую:
"мы же как-то обходимся джейсоном для передачи «объектов» туда-сюда? "
Кто мы? Куда передаёт? Как обходимся? Много сотен тысяч из этого миллиона мух (за пределами любезной вашему сердцу предметной области) никогда в жизни не передают никаких объектов в джейсоне. У вас же претензия на некую общность, про "хорошо спроектированные языки общего назначения". Общего, вы компрене? Общего, а не специального языка для перекладывателей джейсонов.
Ну и остальные обобщения выдают приблизительно такой же масштаб кругозора у человека с тридцатилетним стажем в разработке, свободно пишущем на более дюжины языков.
Когнитивная нагрузка увеличивается не от свойств языка, а от удачных или неудачных инженерных решений.
Если у вас задача с развесистой предметной областью и миллионами строк кода, вы своими мапами вместо объектов не уменьшите, а бесконечно увеличите когнитивную нагрузку. А если вы в магазин на колене завезли иерархию менеджеров фабрик диспетчеров, то проблема не в языке.
Всё, что востребовано - нужно. Пояснения миллионам программистов самой различной квалификации и различных областей, что им нужно, а что нет, это не инженерный вопрос, а гордыня.
Я не понимаю механику развала проекта, если пул-реквесты отвергаются без брани. Изменения не попали в код, пояснения даны, что произошло бы ужасного, если бы это просто сопровождалось словами "отвергаю по двум причинам: у этой функции такие-то пороки, а также нарушен срок подачи пр-ов"
Каким образом после этих слов развалится проект ядра линукса, не очень понятно
Да хоть горшком назови.
Нельзя прийти, к примеру, в гостиницу, и сказать: слушайте, у вас всё равно эти номера пустуют, я тут незаметно поживу бесплатно. Вы же ничего не потеряете!
Или подойти к гиду, который ведёт экскурсию, и сказать: ну мы тут рядом постоим послушаем, с вас не убудет, платить не будем, продолжайте, пожалуйста.
Да даже элементарный заяц в метро не может оправдаться тем, что он для поезда и инфраструктуры ничтожная нагрузка и фактически метро ничего не потеряет, провезя его бесплатно.
Разумеется, для нематериальных товаров физический переход от владельца к потребителю не происходит, и это очень легко эксплуатировать в свою пользу. Просто из этого не следует, что неоплаченное потребление нематериальных товаров чем-то отличается от неоплаченного потребления материальных товаров. А уж назвать это воровством или ровостмом, дело десятое.
Как только выяснится, что для вычисления рейтинга необходимо передать ещё один какой-нибудь параметр/зависимость, а выяснится это на этапе реализации алгоритма вычисления рейтинга, придётся бежать по всем тестам и править вызовы. А там уже и ещё какие-то новости в сигнатурах всплывут.
Принципиально то, что я не знаю хороших практик решения этой задачи, я никогда этим не занимался. Понятно, что надо как-то в глубину просчитывать ветви ходов и оценивать полученные позиции. Так ли это, может я что-то упускаю? Как отсекать? Как оценивать? Возможно, для оценки нужны ещё какие-то вспомогательные абстракции? Может быть, есть ещё какие-то стадии решения? Всего этого я не знаю. Нужна постановка задачи от эксперта.
И такая постановка позволит лучше декомпозировать решение. В том числе и в ООП-парадигме, почему нет.
А если предположить, что наш шахматный движок имеет какую-то степень абстракции и позволит дёшево реализовывать другие игры со схожим флоу, то ООП станет основной практикой. Реализовал, грубо говоря, интерфейс "правила игры" и "оценка позиции" для шашек - и ура, пользуйся, все эти доски и алгоритмы принятия решения будут автоматически переиспользованы.
Короче, ничего ужасного в уместном применении ООП нет. Если с ума не сходить.
Я ничего не знаю про программирование шахмат, так что дальше вольная фантазия. Очевидно, там существуют уже устоявшиеся методики, которые не сочинить в рамках сочинения случайного комментария на хабре
Но нет ничего невероятного, то в шахматах, написанных с использованием ООП, будут:
примитивный класс хранения состояния игры (доска), просто сохраняет инварианты, к примеру, не позволяет поставить две фигуры на одну клетку.
наверное, при реализации логики понадобится возможность итерироваться по дереву возможных вариантов ходов. Это удобно реализовать в виде класса, ведь это же просто контейнер, дерево положений доски со своими инвариантами. И, возможно, с какими-то дополнительными промежуточными данными, которые можно привязать к узлам.
Наверняка есть какие-то вспомогательные абстракции - например, оценка позиции. И наверняка их методики бывают разные, и у них есть состояние (например, кэш предыдущих рассуждений), поэтому они кандидаты на общий интерфейс и реализация в классах.
и, допустим, самый корневой класс, принимающий решение за игрока, строящий логику выбора следующего хода. Он через DI принимает предыдущие.
ну и так далее, нужна постановка задачи, это всё вольная фантазия, дело не в моих выдумках, а в том...
А в том, что вы сами выдумали себе какой-то свой ужасный ООП, в котором программисты моделируют не объекты предметной области, а объекты материального мира: класс для доски, потом класс для клетки, для белого и чёрного цвета, для пешек и ладей - и теперь с этим успешно боретесь.
Но так никто не делает, вы боретесь с демонами в своей голове. Классы для фигур не нужны. А для абстракций, участвующих в принятии решений - вполне могут оказаться полезны.
Как пример для статьи про ООП на хабре? Почему, собственно, нет? Речь не идёт про промышленную универсальную реализацию, вы даже не знаете, какие требования будут к такой очереди, но уже лезете в бутылку. Вполне можно навертеть ООП-абстракций для примера, начиная от иерархии самих типов сообщений и заканчивая какими-нибудь, я не знаю, подписчиками. Это иллюстративный материал для статьи, он не обязан летать на утюгах.
Ах да, я вспомнил, вы тот самый любитель общественного внимания, который обращается к собеседнику "тупой дегенерат", когда его самого макают в, назовём это так, чрезмерную широту обобщений на фоне ограниченнго кругозора.
Тогда вопросов не имею.
Мы пишем класс (и прочими способами упрощаем поддержку кода), потому что писатель кода и читатель могут различаться, да (это может быть и один человек, но в разное время). Это действительно причина
Код, в котором никому никогда не надо будет разбираться и поддерживать, всё равно, в какой парадигме писать
Эвона чо
Семантика владения и прочие детали важны при написании кода (и то в большинстве случаев компилятор не даст ошибиться).
Но код читается кратно больше, чем пишется. И когнитивная нагрузка - это про чтение, а не про написание. Здесь алиасы работают, как хорошее именование переменных и даже как конструирование типов - упрощает код.
Слушайте, если у вас всё надо заменить, чтобы вас правильно понять, может, вы уже признаете, что пример плохой? Задача организации очереди сообщений это другая задача и действительно служила бы лучше целям статьи.
Зачем я буду заменять слово "статья" на слово "код", если я имею а виду не код, а всю статью? Т.е. контекст использования этого кода.
Код, конечно, тоже плохой, но речь не об этом.
Казалось бы, наоборот? Если я знаю, что FooPtr это некий уместный в данном контексте тип указателя, то я не думаю о нижележащем типе и когнитивная нагрузка падает?
Мне неважно, что он юник или шейред, мне важно, что он указывает на Foo и используется в заданной сигнатуре. Остаётся только нужная информация. Нагрузка падает.
Да господи, стандартная библиотека в 2025-м году от РХ у него хак. Как будто кто-то запрещает писать на плюсах в процедурном стиле. Ну возьмите раст, там enum из коробки - тот же вариант. Код ещё в три раза короче станет, кстати.
Вы по-прежнему не туда воюете, я уже сороковой комментарий подряд пытаюсь вам объяснить, что проблема не в ООП, а в вашей статье, в которой выбран неудачный подход демонстрации достоинств ООП. Ладно, это бесполезно.
зачем в коллекцию? В вашем примере коллекция никак не используется
но если есть какая-то ломовая необходимость в коллекции конкретно в этом микроскопическом примере, у вас есть стандартный std::vector<std::variant>
Понимаете, вы сейчас начнёте накручивать требования, которых нет в примере. Моё замечание было не про ООП (это мощный и полезный подход во множестве случаев), а про ваш пример. Он не иллюстрирует сильные стороны ООП. Поэтому идея соревнования в решении этой задачи в разных парадигмах не имеет смысла.
Да тут даже мр не нужен, вот вам код, выполняющий совершенно ту же задачу, что и ваш пример.
По сравнению с вашим у него масса достоинств, начиная с того, что он компилируется.
Ваш пример не убеждает, а разубеждает пользоваться ООП.
Он не подчёркивает его сильные стороны (разделение кода на изолированные куски с хорошо описанной изолированной ответственностью)
Но зато он отлично иллюстрирует аргументы критиков ООП: вы усложнили примитивную задачу.
(ну и плюс задача решена некорректно, рисование не является частью прямоугольника, как я уже выше и написал)
Это очень плохой пример, потому что для игрушечных задач ООП не нужен. Он нужен для сложных абстракций, для разделения когнитивной нагрузки между группами разработчиков. У вас никогда не будет отдельной группы разработчиков для кружочков, а отдельной - для треугольничков.
Давайте попробуем вернуться в реальность и представим, что эти квадратики - что-то более-менее сложное. Очевидно, функции draw() должны обращаться к каким-то связанным с рисованием зависимостям (как минимум, тянуть заголовочные файлы). Но сами прямоугольники могут использоваться в контекстах, которые не подразумевают никакой связи с рисованием. Например, я не знаю, библиотека, которая вычисляет пересечения прямоугольников. На кой ляд ей draw() и все её зависимости?
А значит, фигура у нас разбивается на две части: Rectangle и RectangleDrawer (если предположить, что у рисовальщика есть состояние, например, кэш, и просто функции недостаточно, то понадобится класс), а RectangleDrawer станет частью своей иерархии. Они будут связываться, к примеру, как визиторы, и тут...
И тут в помещение вбегают критики ООП и говорят, что вот наворотили дикий оверинжиниринг! И они правы, потому что для этой примера достаточно POD-структур, для их хранения - несколько векторов, а для рисования - перегруженных (и даже это необязательно) свободных функций. Плохой пример, негодный. Надо придумать пример реального размера, в котором ООП действительно нужно.
Две проблемы.
ООП, разумеется, не панацея, оно придумано, чтобы снимать когнитивную нагрузку. Её нужно снимать, если
а) предметная область большая, не десятки, а сотни и тысячи разнородных сущностей со сложными связями.
б) работает много программистов, которые увольняются и приходят на протяжении долглих лет
Ты смотришь на код первый и последний раз, тебе надо что-то сделать и не испортить. Использовать готовый объект, скрывающий состояние, а ещё лучше - реализующий известный интерфейс - идеальное для этого решение. Спасибо тому, кто его создал!
Если вы делаете магазин размером в два человеко-месяца, который никто не будет сопровождать, без ООП легко можно обойтись.
Методологическая проблема поста.
Типичная работа программиста в мало-мальски объёмном проекте это поиск компромиссов и оценка рисков.
Сделал оптимально - плохо читается.
Сделал читаемо - трудно расширять.
Сделал расширяемо - бьют по голове за оверинжиниринг.
И так далее. Постоянный поиск компромиссов. Этой проблемы нет, только если ты пишешь в команде из трёх человек, в которой ты главный.
Отсюда следует, что если кто-то на голубом глазу пишет статью "Такой-то подход - скам" (не с кликбейтными целями, а от души), то он принципиально неспособен к этому поиску баланса, у него не развита ответственная за это часть профессионализма.
Т.е. он недееспосбоен как инженер
Знаете, очень крутой комментарий, им совершенно невозможно оскорбиться! Пытаясь сопоставить слово "диффамация" в вашем исполнении с его словарным значением, я не могу быть уверен, что и, к примеру, выражение "тупой дегенерат" для вас означает то же самое, что и для других носителей русского языка.
Это даже даёт какую-то надежду. Возможно, и прочие слова из вашего опуса также следует понимать в каком-то новом, одному вам ведомом поэтическом смысле. Возможно, под инкапсуляцией вы подразумеваете инсоляцию, а под типизацией пиритизацию. Тогда, конечно, никаких претензий быть не может.
Миллион мух, разумеется, имеют гораздо более разнообразный опыт, чем одна муха. Которая, к примеру, пишет, я цитирую:
"мы же как-то обходимся джейсоном для передачи «объектов» туда-сюда? "
Кто мы? Куда передаёт? Как обходимся? Много сотен тысяч из этого миллиона мух (за пределами любезной вашему сердцу предметной области) никогда в жизни не передают никаких объектов в джейсоне. У вас же претензия на некую общность, про "хорошо спроектированные языки общего назначения". Общего, вы компрене? Общего, а не специального языка для перекладывателей джейсонов.
Ну и остальные обобщения выдают приблизительно такой же масштаб кругозора у человека с тридцатилетним стажем в разработке, свободно пишущем на более дюжины языков.
Когнитивная нагрузка увеличивается не от свойств языка, а от удачных или неудачных инженерных решений.
Если у вас задача с развесистой предметной областью и миллионами строк кода, вы своими мапами вместо объектов не уменьшите, а бесконечно увеличите когнитивную нагрузку. А если вы в магазин на колене завезли иерархию менеджеров фабрик диспетчеров, то проблема не в языке.
Всё, что востребовано - нужно. Пояснения миллионам программистов самой различной квалификации и различных областей, что им нужно, а что нет, это не инженерный вопрос, а гордыня.