Как стать автором
Обновить

Комментарии 380

Всего они выделил 23 паттерна. Ключевая особенность их в том, что почти все из них построены на наследовании.

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

Ок, готов признать ошибку про паттерны. Но это всё равно в итоге скорее аргумент в пользу моей позиции. В книге "Design Patterns: Elements of Reusable Object-Oriented Software" пишут, что нужно избегать наследования. Но тогда вообще не особо понятно, на чём строится ООП. То есть наследования нужно избегать, но через наследование достигается полиморфизм подтипов (ad-hoc и параметрический остаются). Итого из трёх столпов остаётся только инкапсуляция?

Да, только инкапсуляция. Без неё код получается солянкой функций. ООП - не религия, а всего лишь способ структурирования и группировки кода.

а всего лишь способ структурирования и группировки кода. 

А что тогда? Как раз, что религия, о чем автор всю статью и пишет.

Или вы считаете что христиане и буддисты одинаково структурируют и группируют код?

https://habr.com/ru/articles/907756/#comment_28274682

Причём инкапсуляция протекает)

Странно. Я открываю официальный FAQ по go. И там есть вопрос "Is Go an object-oriented language?", на который авторы отвечают: "Yes and no".

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

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

Это я всё к тому, что общепринятого определения ООП у сообщества нет. Каждый понимает его по-своему.

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

Любая формальная система

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

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

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

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

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

Классика это "Совершенный код" Стива МакКоннела. Стив был практиком когда ее писал.

Что самое интересное, программисты много лет интуитивно использовали эти "паттерны проектирования" даже не задумываясь, как их назовёт какой-нибудь баблоруб-бумагамарака в своём "труде-исследовании". И ещё столько же не знали бы... Но мужик молодец — срубил бабло на ровном месте!

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

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

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

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

Проблема в том, понятия напутали, терминологию.

Это цитаты из SICP

Святое писание?

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

🤣

в си нет "ключевого слова" external. Фактчек вам в помощь.

Я вот смотрю на исходный код игры Little Big Adventure 1 и там его по уши

Сорри, там extern

Есть volatile.

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

ООП - вовсе не скам, а заголовок этой статьи - скам.

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

Если бы мне кто-то до появления ООП предложил идею языка, где всё есть объект и где данные привязаны к поведению, то я не стал бы возражать. Но оценить идею полноценно смог бы только после реализации

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

Если бы мне кто-то до появления ООП предложил идею языка, где всё есть объект

...иии снова путаем объектно-ориентированное программирование и синтаксис произвольного языка "с классами".
А поддержка классов/объектов синтаксисом языка вовсе не обязательна, ООП могёт быть хоть на голых сях, хоть на ассемблере, и вообще это не синтаксис, а подход к программированию.
Для примера - WinAPI лохматых годов, где окно есть некая сущность с полями и методами (которые дёргают, посылая окну сообщения).
Из примеров посвежее (хотя и WinAPI живее всех живых) - GTK, писанное на голых сях, но при этом насквозь объектно-ориентированное.

WinAPI лохматых годов как раз живёт, а вот ООП библиотеки UI многие умерли

иии снова путаем объектно-ориентированное программирование и синтаксис произвольного языка "с классами".

Без иронии или негатива спрашиваю. Что тогда такое ООП?

  1. ООП это способ организации кода, в котором структура данных и методы/функции, которые с ней работают объединены в некую сущность, называемую классом. (Например, в С89: совокупность структуры FILE и функций типа fopen, fclose и т.д. это класс.)

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

  3. Можно писать код с ООП и на С89, но есть языки программирования, в которых для ООП предназначен специальный синтакс.

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

    Это то, что я объяснял бы студентам.

Тут должна быть картинка с профессором фортраном: делай хорошо и будет хорошо. Отличная теория, да.

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

что вам не понравилось в определении? в ваших программах нет предметной области и нет сущностей?

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

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

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

это не догма а принцип ddd, нужен для снижения когнитивной нагрузки

а в науке нет бизнес-логики и там нет места ооп

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

это не догма а принцип ddd

Для выражения которого ООП совершенно не нужен. DDD отлично делается на функциональных языках.

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

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

диалектика.. а чо не теория струн?

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

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

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

Ну, а теория струн к этой конкретной проблеме неприменима от слова совсем (и, к слову, непонятно, применима ли она к чему-нибудь вообще, но это уже совсем другая тема).

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

Почему? Там есть куча инструментов для этого, и они настолько естественны, что о них даже не задумываешься.

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

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

Почему? Там есть куча инструментов для этого

Правда что ли? Ну, скажите, как они называются.

Проблема с диалектикой в том, что она логически противоречива

Диалектика противоречива в той мере, в которой противоричивы явления объективной действительности: ещё древние греки осознали (приписывается это философу Протагору): "Каждая вещь имеет две стороны". Однако обсуждать диалектику здесь - это офтопик.

Правда что ли? Ну, скажите, как они называются.

Например, функции (конвертирующие одни типы в другие). Или, например, события и реакции на них.

Не, серьёзно, DDD настолько естественно, что когда я прочёл пару книжек про DDD, то выяснил только то, что именно так и называется то, чем я давно занимался в ФП. Там, конечно, дают явные названия для этих инструментов, но они естественные, и скорее отражают организационную структуру, чем код. Ну там, shared kernel для ограниченных контекстов, соответствующих тесно связанным бизнес-процессам, или upstream/downstream, когда одна команда (бизнес-процесс)не может влиять на язык другой команды, но другая команда (бизнес-процесс) всё равно DDD, или anticorruption layer, когда другая команда — не DDD.

Но на практике обо всём этом можно не думать, и всё будет норм. Вам не нужно знать аксиомы Пеано, чтобы посчитать сдачу в магазине.

Диалектика противоречива в той мере, в которой противоричивы явления объективной действительности

Явления объективной действительности не противоречивы. Диалектика по описательной силе сравнима со средней религией: можно сделать вид, что описываешь что угодно, но на самом деле не описывается ничего.

Однако обсуждать диалектику здесь - это офтопик.

Только когда речь заходит о том, что диалектика — так себе инструмент, конечно :]

Например, функции (конвертирующие одни типы в другие). Или, например, события и реакции на них.

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

Явления объективной действительности не противоречивы.

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

Только когда речь заходит о том, что диалектика — так себе инструмент, конечно.

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

Ключевых слов я не вижу

Я их дальше привёл. Можно попробовать прочитать следующий абзац.

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

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

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

Можно сделать s/диалектика/религия/g и получится примерно настолько же корректное высказывание.

Зачем здесь какие-то слова?

Зачем слова, когда на небе звезды

Вот какой кредит в реальности, такой он должен быть и в коде.

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

вся возня только затем чтобы однажды вы могли сделать lion.eat(antilope); легко и непринужденно

 lion.eat(antilope); легко и непринужденно

И тут плавно и весело влетаем в спор, почему не

antilope.be_eaten_by(lion)

Ну и еще - для коллекции - в проблему Double Dispatch, потому что у нас и lion - ссылка на один из возможных видов львов и antilope- это ссылка на один из возможных видов антилоп.

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

Время расставит все по своим местам

я люблю методы отдавать акторам

Если поведение каждого вида антилопы при поедании разное - большинство видов языков заставит сделать именно antilope.be_eaten_by, чтобы полиморфизм сработал.

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

В общем случае имеем матрицу деструкторов виды львов<->виды антилоп.

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

В общем случае имеем матрицу деструкторов виды львов<->виды антилоп.

Да. И эту матрицу можно разложить по объектам разным способами.

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

"Мертвая антилопа" vs "Труп антилопы" (с опциональными и запутанными "кто из этого чем является?")

Идем за консультациями, в общем, чего народу хочется видеть.

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

При таком подходе вас не поймут другие программисты и команда сфейлит

И тут плавно и весело влетаем в спор, почему не

antilope.be_eaten_by(lion)

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

Естественно, это если мы моделируем взаимодействие льва и антилопы вызовом методов классов. В качестве альтернативы вместо вызова eat и eating можно омуществлять передачу сообщений, выставление сигналов или любой другой вариант описания взаимодействия, который сможем придумать.

... получив null pointer exception из-за непроинициализированной антилопы во рту у льва.

Да. Помню как в одной игре корова жевала траву и потом подошла к дереву и дерево... Исчезло! Баг был как раз примерно в таком коде.

Аргумент в чем? Плохому танцору всегда будет что-то мешать вне зависимости от

Надо и так всегда делается.

Типичный пример: вы делаете сайт. С регистрацией. Юзеры у вас будут? Будут, вы создаете тип данных который обозначает... что? Понятное дело, что этого самого юзера. А если у вас есть еще различные сущности, к примеру, трек (допустим, юзеры загружают треки). Это просто набор байт? А как же остальные поля? Дата загрузки, жанр и тд. Это будет еще один тип данных.

И т.д.

Типичный пример: вы делаете сайт.

Дело в этом.

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

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

"Надо" тут слишком сильно. Просто иногда это очень удобно.

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

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

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

Объект это связанные данные, а не кошечка или собачка.

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

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

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

Надо - не надо. Все проще. Когда удобно - моделируем, когда неудобно - не моделируем. Если в программе потребуется иерархия объектов, отражающая объекты (даже реальные) предметной области, кто нам это запретит?

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

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

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

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

Вы тут перепутали отношения "супер-тип/под-тип" и "объект-родитель/объект-потомок".

В реальности отношения между обьектами гораздо сложнее, чем общее-частное.

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

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

Как минимум, у любого реального кота всегда есть два родителя, а не ноль, один или три.

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

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

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

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

Вот именно и так везде: в маркетинге, в кадровой методологии и в производстве — кто-то выдумал термин и понеслось.

Примеры? Окей: Секретарша — это нынче Офис менеджер, знакомьтесь… и так далее по списку.

Кумарит это все. Слава богу в Сетях хоть какие-то принципы работают, ибо разрабатывают протоколы в Иснтитутах и структурах Стандартизации (то есть под их контролем как минимум: iETF, ISO, etc). Поэтому есть эталонная стройная модель, где все понятно, а что не понятно — или читай стандарт)))

Поэтому есть эталонная стройная модель, где все понятно

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

Ответ у меня есть, если надо - прямо со ссылкой на пункт спецификации. Но не только лишь все его знают. Например, некогда широко известный в узких кругах Руслан Карманов (ныне - умаодановец, а тогда - борец за образованность в IT и с Linux) меня за этот вопрос просто забанил у себя в блоге.

Спасибо за вопрос, то ко подвоха не понял. Я как бы о том, что хоть какая-то организованость есть. То же консорциум Wi-Fi, казалось бы не является институтом, стандартизатором, но следует методикам принятыми Институтами. То есть маломаломальская регуляция отличного качества.

Теперь к вопросу. Вы задали простой вопрос и правильно на него ответили, ведь рутер был изобретен, что бы маршрутезировать пакеты/данные на специально для этого разработаном протоколе ( даже не уровне — уровень/слой, можно принять как абстракцию, точнее совокупность протоколов) IP. Но вам было мало, и вы почему-то решили запутать вопрос добавив в конце какую-то абстракцию, которая априори тут никуда. Я не читал спецификацию ни ФТП протокола ни АйПи, поэтому осознано не смогу ответить, но помечтать могу: ну что там фтп? Знает в айпи? Обладает похожими заголовками и методами? Я не знаю… зачем вы это намешали? АйПи протокол в сравнении с фтп, должен быть проще. Реализовано согласование с вышестоящими и нижестоящими протоколами, для основой своей деятельности требует два параметра, и несколько полей для обратной связи там, просчета ошибок. Он монолитный. А вот фтп, гораздо сложнее, может модернизироваться, так как может содержать новые типы шифрования (если оно там имеется, не помню, но логично если было бы), должен уметь наверно по новому сжимать данные, если они там сжимаются вообще.

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

Я не читал спецификацию ни ФТП протокола ни АйПи, поэтому осознано не смогу ответить, но помечтать могу: ну что там фтп? Знает в айпи? Обладает похожими заголовками и методами?

Да, FTP в своих сообщениях использует сущности более низких уровней - адреса IP и порты TCP - но модель OSI это делать не запрещает.
Расскажу ответ: специфкация сетевого уровня модели OSI требует использование единого адресного пространства на этом уровне (ему в модели Интернет соответствует уровень IP), а в сети, в которой работает домашний маршрутизатор, это требование, как известно, не выполняется - вот и приходится маршрутизатору не только транслировать адреса сетевого уровня, но и править сообщения протокола уровня приложений.

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

Да, FTP в своих сообщениях использует сущности более низких уровней - адреса IP и порты TCP - но модель OSI это делать не запрещает.

Это понятно, http тоже много чего требует, а некоторые и за мак-адресамм охотятся, но тогда вопрос, ибо я спеки не изучал, да и на практике не задумывался: от куда он тянет айпи например? Распаковывает пакет айпи, или эта инфа заложена в данные?

Что-то мне подсказывает, что он не смотрит в соответствующие поля заголовков протокола IP (что бы извлечь адрес), а смомтрит айпишник в данных своего протокола ФТП например.

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

Вы хотите сказать, свитч порты на рутере не сами анализируют фреймы, а есть универсальный контроллер на рутере, которые в зависимости от необходимости открывает и фреймы, и пакеты и все-все-все? Не верю. Это поотеверечит всем нормам безопасности. Я думаю на рутере есть отдельные контролеры, которые в отдельности были бы независимыми девайсами, но так не делают, а наоборот, все агрегированно под капотом, — сигналы напряжения (физ уровень) формирует какой-то ЦАП под контролем соответствующего контролера, и так до верху…

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

Блин, сложно я это все описываю, извините, плохо писал сочинения в школе)

Вы хотите сказать, свитч порты на рутере не сами анализируют фреймы, а есть универсальный контроллер на рутере, которые в зависимости от необходимости открывает и фреймы, и пакеты и все-все-все?

Да.

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

Эм. Да. (если я правильно понял вопрос)

Вы когда пишите ГЕТ запрос в ХТТП, что бы спросить айпи адрес клиента

Чего?

Скорее он приходит с данными в хттп-протоколе

Нажмите F12 в своём браузере, выберите Network, обновите страницу. Посмотрите http-запросы, заголовки запросов и ответов. Где там айпишник?

ибо я спеки не изучал

Изучите. Начните отсюда.

https://www.youtube.com/watch?v=Z-a7MNStFQs

Это, кстати, лекция с курса Skillfactory по сетям. Самая первая, вводная. Как иронично.

UPD: у вас в профиле написано Network Engineer. А чем именно вы занимаетесь, если не секрет?

Ну вы даете. Я понимаю что написал коряво, но я имел в виду вот что:

Сайт 2IP.ru, как вычисляет ваш айпи? Смотрит в протокол IP? Нет же, он его получает в поле DATA HTTP-протокола, через который он вежливо попросил систему клиента ему его представить.

Поэтому не надо мне рассказывать сказки, что рутер чего-то там куда-то лазеет.

Мой уровень знания сетей — циско начальный.

Вам бы все таки в более ранний уровень обучения вернуться. Потому как сайт 2ip.ru (как и все остальные) берет мой айпи именно из ip пакета. И говорит что он в условной Сербии.

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

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

Чего и вам советую

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

Я мастер до четвертого уровня модели OSI

X for doubt

Ребята, чего вы от меня хотите? Я работал с железом, проектировал и настраивал сети, но я никогда не задавался вопросом от куда сайт 2IP.ru например дергает белый АйПи за NAT-ом. Вот сейчас мне стало интересно, и я подумаю над этим, когда захочу, но сейчас я буду пить пиво и есть.

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

А в остальном, поверьте мне, что бы обслуживать огромный (страна) парк сетевого оборудования мне этого всего не надо было знать. Из программирования в моей деятельности было — настроить свитч третьего уровня, а как там уже пользователи свои АйПи сайту 2IP раскрывают, я просто не задумывался.

Спасибо за внимание.

от куда сайт 2IP.ru например дергает белый АйПи за NAT-ом.

Разве белый IP за NAT-ом? Я аж испугался и проверил. В локальной сети у моего компа стандартный 192.168..., а 2ip.ru как раз показывает не его, а белый, с которого от раутера этому сайту запрос и шёл. Вроде, всё логично.

Ааааа блин, - все понял. Я короче так сам себя запутал))))

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

Терь другой вопрос, как я себя завел в эту ловушку. На каком комментарии у меня щелкнуло не в ту сторону))))

в поле DATA HTTP-протокола

Ого.

Это где там такое поле?

Можете меня носом натыкать, как котёнка в ссаки? А то я сам не справляюсь. Пожалуйста.

А как вы данные передаете в пакете?

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

Вот, я тут в ветке пришел к мысли, что видимо , кажда «шалава» имеет доступ раскрывать пакет/фрейм и смотреть соотвествующие поля.

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

А как вы данные передаете в пакете?

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

Ещё раз.
Нажмите F12 в своём браузере, выберите Network, обновите страницу. Посмотрите http-запросы, заголовки запросов и ответов. Где там айпишник?

Вот, я тут в ветке пришел к мысли

Не надо никуда приходить. Надо открыть википедию и прочитать, как работает коммутатор и маршрутизатор.

Ещё раз.
Изучите. Начните отсюда.
https://www.youtube.com/watch?v=Z-a7MNStFQs
Это, кстати, лекция с курса Skillfactory по сетям. Самая первая, вводная. Как иронично.

 Надо открыть википедию и прочитать, как работает коммутатор и маршрутизатор.

При условии что это все еще так работает. Я могу совершенно просто представить, что современный домашний маршрутизатор - вообще на MAC-и не смотрит для определения порта 'куда кадр кидать', а сразу пользуется теми битами, где IP адрес должен лежать.

Еще раз извиняюсь.

Я вспомнил про TTL. Его бывает достаточно для определения белого адреса. Других методов я сей не припомню и вряд ли знаю.

Я оперирую WindShark-ом, и кнопки F12 на моем айпаде нема)

Обыкновенный домашний маршрутизатор

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

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

То есть, получается что модель OSI оказывается неприменимой к реальному современному Интернету. Это так, и в этом-то и состоит ехидство.

Да вполне применимо. Почему вещь, собранная в одном пластиковом корпусе, и продающаяся в магазине как одна позиция обязательно должна работать только на одном определённом уровне абстракции? Совсем не должна, не обязана.

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

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

btw, стек протоколов TCP/IP действительно не совпадает "пуля в пулю" с OSI. Он не касается физического уровня OSI, вообще никак, а прикладной уровень TCP/IP захватывает сразу три верхних уровня OSI. Это прям базовая база, с этого TCP/IP учить начинают, и спрашивают первым вопросом на всех собеседованиях.

Справедливости ради, модель OSI - это, действительно, академическая описательная абстракция, в которой мало практической ценности. Но вполне точная.

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

Тут противоречий нет. Противоречие - в том, что модель OSI основана на предположении, что каждый уровень скрывает от вышележащих детали реализации на нижележащих уровнях. Так вот, нельзя просто так взять и скрыть маршрутизатор с NAT: некоторые протоколы верхнего уровня работать не смогут. Кроме FTP это ещё и, к примеру, IPSec.

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

нельзя просто так взять и скрыть маршрутизатор с NAT: некоторые протоколы верхнего уровня работать не смогут

Skill issue.

Вы что-то неправильно настраивали.

некоторые протоколы верхнего уровня работать не смогут. Кроме FTP

Тогда бы фтп-сервер в докере не разворачивался

https://github.com/garethflowers/docker-ftp-server

Skill issue.

Постарайтесь выражаться вежливо. А то, я гляжу по вашей какрме, вы рискуете потерять возможность активно комментировать. Только из-за этого пограничного значения в ней я вам минус и не поставил, пока.

Вы что-то неправильно настраивали.

Учите матчасть. IPSec ESP и IPSec AH - которые напрямую помещаются в пакеты IP с номерами протокола 50 и 51 через NAT проходить не могут. Для прохождения через NAT есть режим NAT Traversal (NAT-T), в котором PDU IPSec помещаются в датаграммы UDP/4500. Так вот, я писал про первый вариант. Второй вариант появился исторически позже,

Тогда бы фтп-сервер в докере не разворачивался

Ключевой момент:

       	--env PUBLIC_IP=192.168.0.1 \
        --publish 20-21:20-21/tcp \
	--publish 40000-40009:40000-40009/tcp \

То есть, трансляции как таковой нет: порты отображаются 1:1, а сервер FTP знает, какой публичный IP увидят клиенты и подстраивается соответствующимм образом.
А вообще, проблема FTP с NAT, в основном, на клиентской стороне - в команде PORT, где клиент указывает, куда нужно установить соединение с ним для передачи данных (в активном режиме, по умолчанию, клиент принимает подключения от сервера. С пассивным режимом всё было сильно проще, иногда переключпение в него помогало.

То есть, трансляции как таковой нет: порты отображаются 1:1

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

Если он ничем другим не становится, у нас фтп за натом или не за натом? Или за натом, но не работает?

Только из-за этого пограничного значения в ней я вам минус и не поставил, пока.

Во-первых, это слив.

А во-вторых, кармодрочеры идут нахуй. А неграмотные кармодрочеры идут нахуй два раза.

Если он ничем другим не становится, у нас фтп за натом или не за натом?

Похоже, требуется высылать разъяснительную бригаду.
Насчет ответа на вопрос, то, как говорится в одном похабном анекдоте, "есть нюанс" В FTP есть клиент и сервер, и разница между ними - примерно как в анекдоте: нюанс в том, чей IP и чье соединение.

В FTP есть два режима передачи данных: активный и пассивный. В активном режиме (по умолчанию обычно используется он), клиент, при открытии данных передает серверу по управлющему соединению (по умолчанию оно - на порту 21 сервера) команду PORT и в ней - IP и порт в определенном в стандарте формате, на котором будет приниматься соединение от сервера для передачи данных. В ответ сервер устанавливает соединение TCP со своего порта данных (20 по умолчанию) на указанный адрес и порт.

Очевидно, что сервер не может просто так взять и установить соединение с клиентом за NAT. Поэтому ALG на маршрутизаторе (точнее сказать - шлюзе) с NAT, обнаружив команду PORT, устанавливает трансляцию с некоего выбранного им порта на внешнем IP на указанный в команде адрес и порт и подменяет содержимое данных в команде этим адресом и портом. То есть, шлюз обрабатывает проходящую команду PORT протокола уровня приложений (FTP), чтобы протокол мог работать. Если же за шлюзом с NAT находится сервер, то шлюзу в активном режиме ничего особого, кроме стандартной трансляции исходящего соединения, делать не приходится.

В пассивном режиме клиент в аналогичном случае посылает команду PASV, которой сообщает, что хочет установить соединение для передачи данных сам. Ответ сервера на эту команду в изначальных RFC не был стандартизирован (сейчас, вроде как, стандартизирован, но это неточно). Я знаю про два варианта ответа сервера: либо он возвращает IP и порт в том же формате, что и используется в команде PORT, либо возвращает что-то ещё. IP в первом варианте сервер может указать тот, который по его мнению имеет смысл - например, известный ему публичный IP шлюза NAT, а порт выбирается из некоего диапазона (который как раз может быть . И, соответственно, есть два варинта поведения клиента: либо он устанавливает исходящее подключение на порт порт данных сервера (20 по умолчанию), либо - на адрес и порт, полученный в ответе. Если за NAT находится клиент, то шлюзу ничего нестандартного делать не требуется - он просто обычным образом обрабатывает исходящее соединение.
Если за NAT находится сервер, то шлюз должен вести себя в зависимости от того, на какой ответ настроен сервер. Если сервер не шлет свой адрес и порт, или настроен на посылку публичного IP и порта из настроенного на шлюзе диапазона портов пробрасываемых один к одному, то шлюзу ничего особого делать не надо: он обрабатывает обычный проброс пакета для входящего соединения на пробрасываемый порт. Единственно, когда требуется помощь ALG - если адрес или порт в ответе надо преобразовать.
Мне по жизни попадалась обычно ситуация (это было давно, да), когда сервер на PASV не отвечает своим адресом/портом - и там всё было просто: проброс 20 порта TCP решал проблему. А что там в интимных взаимоотношениях vsftp с докером - это я не разбирался, подозреваю, что один тех самых двух вариантов, когда проброса порта один в один достаточно.
Короче, поставить сервер FTP за NAT проще чем клиент.

Я вам понятно всё разъяснил, надеюсь?

Подробно, понятно, без шуток - спасибо.

У меня осталось 2 вопроса:

  1. NAT требует настройки. FTP-сервер требует настройки. Как из этого следует, что "ftp не работает за nat'ом"?

  2. Где и в чём здесь нарушение модели OSI, с которого начали?

  1. Более полная форма утверждения "ftp не работает за nat'ом" - "клиент FTP в активном режиме не работает за шлюзом NAT, если на шлюзе NAT не реализован шлюз уровня приложений (ALG) специально для FTP", но так писать дольше поэтому написано было кратко. И, кстати, если нужного ALG нет, то и никакая настройка не поможет. Например, для IPSec ESP/AH ALG принципиально невозможен: там всё подписями да криптографическими контрольными суммами охвачено, менять ничего нельзя. Или, если взять древний протокол PPTP для VPN, то его поддержка в разнообразных устройствах с NAT появилась не везде и/или не сразу, и если поддержки не было, то пользователь за таким шлюзом, не мог подключиться к корпоративной сети.

  2. https://habr.com/ru/articles/907756/comments/#comment_28278326

  1. "ftp не работает за nat'ом, если их неправильно настроить". Skill issue, как я и говорил.

  2. Аааааа. Понятно, в чём дело.

    модель OSI основана на предположении, что каждый уровень скрывает от вышележащих детали реализации на нижележащих уровнях


    Нет, не основана.

    "Инкапсуляция" в сетях связи - это не ООП-шная инкапсуляция, не про ООП-шное "сокрытие".
    Это просто про нарезку и упаковку данных на разных уровнях.
    Класс "Сегмент" не наследует класс "Пакет", а класс "Пакет" не наследует класс "Кадр".

А то, что DNS подменяет IP-шники на человеческие имена или то, что веб-серверы в http-пакетах регулярно переклеивают заголовки (https://nginx.org/ru/docs/http/ngx_http_proxy_module.html#proxy_set_header) вас не смущает?
Никаких представлений не нарушает, всё нормально?

Ну, и вообще, само наличие заголовка Host в http-запросе - это ок или не ок?

Skill issue, как я и говорил.

Вы своим специфическим пониманием анекдот мне напомнили, который "Папа, а где море". Вы там про ALG прочитали, что я писал? Или вам так хочется оставаться правым, что вы захотели это проигнорировать?

Нет, не основана.

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

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

Ну слово "скрывает" не совсем уместно, так как смысл не в сокрытии.

Но FTP или IPSEC старше NATa, потому и конфликт. Хотя, в в фтп для того и добавили PASV режим, чтоб работало за натом в том числе.

И напротив, эта оффтоп ветка дополняет основную статью, ибо есть как сложилось, есть стандарты, есть общее понимание и есть мастера 4го уровня циско

;)

А разве модель OSI касается оборудования? Она вроде про токолы.

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

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

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

Это мелочи. Там TCP/IP в OSI не вписывается.

Вписывается, только в нем (имею в вилу модель Интернта) несколько уровней слиты в один, а потому уровней осталось четыре. Но идея - та же.

Как бы даже тут нет. Роутерами, обычно, производители называют именно роутеры. А то, что обзывают роутерами юзеры, по привычке, производители давно обзывают интернет-центрами, SOHO оборудованием или типа того

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

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

Посмотрите тему NAT и Application Level Gateway - тогда поймёте проблематику и в чём тут ехидство.


1) FTP - старый протокол и был внедрен до того как стали повсеместно использовать NAT и "домашние маршрутизаторы"
2) NAT работает на третьем уровне.
3) Есть Passive FTP - которому ничего лишненго не нужно.
4) FTPS по идее тоже умеет в активный режим, но я не встречал чтоб этим кто-то пользовался

Вообще не понимаю, о чём спор. NAT работает на сетевом уровне, FTP на прикладном.

И где хвалёное айтишное умение гуглить лучше всех, когда оно так нужно?

Вот это находится в картинках по запросу "osi tcp ip", на первом экране.

Как вы хотите этой картинкой ответить на изначальный вопрос?

Вопрос - на котором уровне OSI он должен работать, чтобы выполнять по минимуму свои функции - просто пересылать трафик, туда и обратно?

Картинка для иллюстрации, что вообще такое "модель OSI" и как она соотносится со стеком протоколов TCP/IP. И с распространенными программными и аппаратными протоколами. Ну, и она не для вас, а для топикстартера всё ж.

Вопрос изначально неправильно поставлен. Человек не понимает, о чём спрашивает.

на котором уровне OSI он (роутер) должен работать, чтобы выполнять по минимуму свои функции - просто пересылать трафик, туда и обратно?

На каждом. На любом.

Да ну его тот рутер. Детские загадки спрашивайте. Я хоть давно сетями не занимался, но начинаю вспомнюинать…

Протокол ICMP проявляет интересную природу работы, помните?

Он и на уровне маршрутизации и на уровне транспорта копашится.

Тоже интересная задачка для студентов.

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

По модели OSI получается, что на 3-м, сетевом. А по жизни получается, что и на верхнем 7-м, уровне приложений ему приходится работать тоже: иначе, например, FTP через него не пойдет. Почему так?

Да вы правы, я наконец пришел в себя после работы.

Конечно Вы правы. Он как тот трактор работает на всех уровнях OSI, что я Вам частично и сказал в своем ответе. Но там почему-то запутался (заработался), и меня понесло.

Простите.

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

Этот феменитив мне нравится, поэтому так и написал, а секретари они в ОПКоме))))

Но вы поняли о чем я…. И это главное.

Автор чем занимается? Маркеты? Тонна dto это про заказы, товары и быстро сложить в БД.
Предлагаю автору решить прикладную задачу от МЧС - матмодель поведения облака хлора в плотной городской застройке под действием различных погодных условиях.
Программа позволяла быстро "построить" город (указывались дома, этажность, подъездность), размещались на карте, указать откуда и с какой силой дует ветер и в какой точке собственно авария. Пилот проект строился на расчете облака хлора. В решении задачи надо было рассчитать движение масс воздуха, междомовых "сквозняков" и с учетом физических свойств визуализировать движение хлора. Движение воздуха, влага, хлор - все билось на метачастицы, им прописывалась физика поведения, это все обсчитывалось и визуализировалось.
И вся эта задачка призвана спасать жизни людям.
И в ней огромное количество именно ООП и практически полное отсутствие dto.

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

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

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

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

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

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

Java и C# - языки своего времени, где отменили "просто функции", да, это сомнительно по итогу оказалось. Параллельно существуют ObjectPascal и C++, где никто "процедурный подход" не отбирал. Да и новые ЯП процедурный подход разрешают.

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

Java и C# - языки своего времени, где отменили "просто функции", да, это сомнительно по итогу оказалось

Тут соглашусь. Сильный перекос в ФП тоже не одобряю, хотя не могу сказать, что где-то массово его наблюдаю в новых языках. В каких языках это заметно? Разве что ts со своей безумной системой типов, где есть вообще всё

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

Забавно, что в последних версиях C# разрешили-таки делать top-level statements, включая методы без класса, правда с ограничениями (внутри этого на самом деле нет и это просто еще одна ложка синтаксического сахара).

Используйте Typescript, rust, go

Можно и без классов. Но они не особо популярные.

Java и C# - языки своего времени

Старые, но обросли ФП приемами и типа норм

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

Проблема начинается когд на ООП языках, в которых должны быть объекты (Java), программисты пишут по-старому в стиле С (на Spring c DTO где ...Controller и ...Service которые по сути просто свалка процедур, обрабатывают структуры DTO). Потому что не хотят переучиваться на новое

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

Отвечу по порядку.

На данный момент пишу CRM и систему документооборота. Разрабатывал систему для деплоя, сайт для подбора банковских продуктов.

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


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

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

В целом, все ровно так же, как когда-то пихали везде ООП, сейчас пихают Анти-ООП, ФП, ECS, DDD, TDD, MVC, DTO и т.д.

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

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

Я открыл сорцы компилятора go. И он написан на go.

Какую серебряную пулю я продаю в статье? Нет ни слова про ФП или императивное программирование. И никакой конкретный язык я не рекламирую.

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

Я открыл сорцы компилятора go. И он написан на go.

А когда Go перестал поддерживать некоторые принципы ООП?

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

Или для вас ООП язык - этот тот где нельзя просто процедуры без класса писать? Ну тогда, лол, у вас крайне специфическое понимание ООП. В котором ObjectPascal и C++ - не ООП языки.

Какую серебряную пулю я продаю в статье?

ООП — это скам.

А вот условная java как раз пытается это сделать. Потому что всё есть объект

Нет в джаве не все есть объект, есть примитивные типы аля int.

пиши геттер и сеттер на каждое поле своего класса (даже если тебе это не нужно, а такое бывает часто)

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

И да - в Go - все есть interface{} - пихай куда угодно, что угодно, если обсыпал interface{}. Строгость отвалилась, ой. А в джаве кста, не выйдет так.

А когда Go перестал поддерживать некоторые принципы ООП?

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

Командующий правой фалангой Анекий Великий был кучерявым а копье держал левой рукой. Так как принципы нашей религии предполагают что все последователи должны быть кучерявыми левшами, отец Деонис сделал вывод что Анекий Великий определённо веровал в наш культ еще до 100 лет до его появления.

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

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

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

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

Какую серебряную пулю я продаю в статье?

ООП — это скам.

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

И да - в Go - все есть interface{} - пихай куда угодно, что угодно, если обсыпал interface{}. Строгость отвалилась, ой. А в джаве кста, не выйдет так.

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

Или для вас ООП язык - этот тот где нельзя просто процедуры без класса писать?

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

И да - в Go - все есть interface{} - пихай куда угодно, что угодно

С появлением дженериков возможность абьюзить interface{} практически исчезла

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

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

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

И да, инкапсуляция в том же C заканчивается на "LINKER ERROR: DUPLICATED SYMBOL".

С появлением дженериков возможность абьюзить interface{} практически исчезла

Никуда не исчезла, просто теперь, еще вчера, крутой код стал не желательной практикой.

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

Каким образом отсутствие ООП и реактивное программирование связано с качеством интерфейса?

А вы действительно сейчас в своей CRM клиента через функции (ну или, что там вам сейчас более подходящим кажется) описываете, а не через объекты?

Мне вот, в CRM, объекты очень даже походят.

Я пишу на go. Классического ООП там нет. Есть типы, к которым можно присобачить методы. Типа такого:

type User struct {
  Name string
}

func (u User) Say() {
  fmt.Println(u.Name)
}


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

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

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

А то выходит, что даже в C есть классы и у них есть методы

Не совсем так, в C возможно использование классов и методов.

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

Не совсем так

Почему? Вот я беру код выше на go и портирую его на C, с точностью до синтаксиса:

typedef struct User
{
  char *name;
} User;

void say(User *u)
{
  printf("%s", u->name);
}

Если гошный User — класс, а Say — его метод, то и здесь User — класс, а say — его метод.

Пропозал на uniform call syntax в C++ сделал бы это менее глупым вопросом, чем кажется, к слову.

Ну так о том и речь. В самом языке (на уровне синтаксиса) классов и методов нет, но это не мешает написать код с использованием классов и методов.

Пропозал на uniform call syntax в C++ сделал бы это менее глупым вопросом, чем кажется, к слову

Я не думаю, что наличие UCS что-то меняет, это по сути просто синтаксический сахар.

Суть в том, что между

void user_say(User* self) { printf("%s\n", self->name); }
void User::Say() { std::println("{}", Name); }
func (self User) Say() { fmt.Println(self.Name); }

Буквально нет никакой смысловой разницы.

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

Буквально нет никакой смысловой разницы.

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

утверждение «классического ООП там нет» (с которым вы изначально спорили)

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

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

"Классическое ООП" я вообще не трогал, потому что никто не знает что это такое.

можете привести пример наиболее популярного, на ваш взгляд, типизированного языка, для которого верно утверждение «классического ООП там нет»

Что такое классическое ООП? Что значит его там нет?

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

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

Что такое классическое ООП? Что значит его там нет?

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

  1. легко инкапсулировать данные на уровне класса, а не модуля (в коде выше на go нигде не написано, что только функция Say может дёргать name)

  2. легко описывать наследование (а не как в C, где можно обмазаться агрегированием и ЕМНИП явными кастами, конечно, но это больно и нетипобезопасно)

  3. легко описывать полиморфизм подтипов (а не снова как в C, где всё опять на кастах и закате vtbl солнца руками)

По этой логике в любом языке есть «элементы ООП», и выражение «пишу с использованием ООП» <...> перестаёт иметь какую-либо описательную силу

Странная какая-то у вас логика.

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

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

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

Это сахар, который может кому-то нравиться, кому-то нет. Но концептуально разницы нет никакой. По факту мы имеем sealed/final классы, все.

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

Ха, еще один адепт со своей серебряной пулькой прибежал - на этот раз с ECS.

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

Я не программист, но вот читаю это всё и не понимаю, что в парадигме ООП собествено является объектом, ну и куда мы ориентируемся? Не сарказм

Наверное потому игры практически всегда имеют закрытый код и не лежат на гитхабе? :)

ECS - методология для тех случаев, когда даже скорости ООП из С++ не хватает, а совсем уж далеко от объектной модели отходить не хочется. К чему тут серебрянные пули?

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

И что, кто-то производил натурный эксперимент и сравнивал с результатами такого моделирования?

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

С ходу - решение системы уравнений Навье-Стокса с использованием MFEM (библиотеки для решения задач методом конечных элементов)

А в этом самом MFEM под капотом ООП во все поля:

class FiniteElement
{
...
   virtual void CalcShape(const IntegrationPoint &ip,
                          Vector &shape) const = 0;
...
   virtual void CalcDShape(const IntegrationPoint &ip,
                           DenseMatrix &dshape) const = 0;
...
   virtual void CalcVShape(ElementTransformation &Trans,
                           DenseMatrix &shape) const;
/* ну и так далее в том же духе */
}

Не подходит MFEM - берем тот же deal.ii и опять видим кучу полиморфных объектов и виртуальных функций.

Ну и так далее. Как раз массовая замена в академических кругах софта на Fortran и C на C++ примерно на рубеже 90х и 2000х (а местами и раньше) случилась по причине плюшек, которые дает именно ООП.

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

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

Это, однако, не значит, что в расчёте вот прямо будут домики на улицах в виде объектов

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

Если Вы хотите "домики" - сначала надо построить физическую модель, в которой вместо температуры, плотности и давления (как в уравнениях гидродинамики) будут эти самые "домики". Мы же изначально про уравнения Навье-Стокса говорим, правильно? Так нет там домиков, там есть физические величины, векторные и скалярные.

А если надо про "домики" - пожалуйста, можно взять любой симулятор систем автономного вождения. Например, Open-Car-Dynamics от TUMFTM.Там автомобиль ("домик") - это объект со своей аэродинамикой, динамикой движения, набором сенсоров и системой управления. Смотрим под капот - опять видим полиморфные классы:

class VehicleModelBase
{
public:
  VehicleModelBase() = default;
  virtual ~VehicleModelBase() = default;

  // Model step function
  virtual void step() = 0;

  // Setter
  virtual void set_driver_input(const tam::types::DriverInput & input) = 0;
  virtual void set_external_influences(const tam::types::ExternalInfluences & input) = 0;

  // Vehicle dynamic state:
  virtual tam::types::VehicleModelOutput get_output() const = 0;

  // Debug Output
  virtual tam::types::common::TUMDebugContainer::SharedPtr get_debug_out() const = 0;

  // Parameter handling
  virtual ParamManagerBase * get_param_manager() = 0;

  virtual void reset() = 0;
};

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

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

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

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

"Домики" в данном случае у нас выступают как геометрия и граничные условия среды, в которой движутся "метачастицы".

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

Но поскольку в ответ на "метачастицы" последовало утверждение

Решение уравнения Навье-Стокса – очень уважаемая и интересная задача, но я никогда не слышал, чтобы кто-то это сделал путём ООП

я привел примеры, как эти самые уравнения решаются именно с применением ООП.

Что не так?

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

Причём тут метачастицы?

Обычно матмодель таких явлений как массоперенос это дифуры, а решение в виде СЛАУ, например.

А вы сделали какой-то велосипед

Любое решение - велосипед, просто некоторые постарше

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

Без матаппарата в столкнетесь с неустойчивостью решения, например.

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

волюметрик clouds с параметрами на ветер, солнце, распространение света, и чутька наполнителя как я понял, поидее

пока волюметрик сделаешь и разберешься с scatering уже будет пофиг на это

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

Как раз заказы товары и быстро сложить в БД это про ООП дальше некуда, поскольку эти штуки простые пока маркеты маленькие, потом у корзина, заказ, отгрузка, приемка, приход и все это непрерывно растет и меняется вслед за бизнесом. Потом пойдет документооборот, CRP, ERP, налоги, отчеты. И, если автор спокойно с этим всем справляется не порождая родительские объекты типо AbstractShipmentDocument, AbstractDocument. И ли же любит писать, как он выражается "просто функции", вместо того чтобы сложить эти функции прямо в объекты, то ради бога, давайте пожелаем удачи. Я вот выяснил что даже очень опытные и талантливые разработчики часто начинают ошибаться и путаться в этих всех штуках.

PS к тому же автор сильно сильно путает классы и ООП.

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

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

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

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

Из-за чего поднялись такие слои

dto <-> domain pojo <-> entity

Но потом ничего втянулся.

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

На самом деле это самая близкая к DDD архитектура что я когда-либо видел. Даже тесты и документация всё в одном формате и на понятном языке. Красивое.

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

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

Да, для тестов

У вас DTO, скорее всего, появляются просто потому что вы машинально свой опыт с многослойной архитектурой переносите на гексагональную - я сам первое время с этим столкнулся. На самом деле они там вообще не нужны. В многослойной их задача это просто переносить данные со слоя на слой, со всеми вытекающими - наличие кучи классов/объектов, по сути, несущих никакого функционала (так называемая "архитектурная воронка"). В гексагональной нет "слоев", поэтому не нужны и DTO. Например, "порт" БД может/должен просто мепить объекты домена напрямую в POJO/POCO объекты БД/ORM, а "порт" Web API точно также мепить объекты домена на объекты моделей Web API. Когда к этому приходишь, то оказывается, что гексагональная архитектура, на самом деле, намного проще чем многослойная из-за отсутствия кучи "лишних" сущностей в виде тех же DTO или "сервисов BL", большая часть которых ничего кроме передачи данных со слоя на слой на самом деле не делает.

Из трех видов моделей обязателен только domain pojo.

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

dto нужны для сериализации в json или какой-нибудь protobuf, опять таки если у вас server-side рендеринг и возвращается html то dto не пишем

Вижу пост про ООП - копирую стандартную портянку:

  • Единственный ООП язык - это SmallTalk

  • Объяснение ООП через собак, кошек и машины не имеет смысла

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

  • В enterprice программах для разных задач одновременно используются все популярные парадигмы (Struct, FP, OOP)

  • Используйте объекты как границы транзакций (DDD-Агрегаты), инкапсуляцию машин состояний (паттерн State из GoF) или абстрагирование над устойчивыми понятиями (Инкапсуляция доступа к сторонним сервисам / Классы по типу Collection)

Как говорится, it's not much but it's honest work. Спасибо за ваше терпение

Единственный ООП язык - это SmallTalk

Трушный ООП это акторная система. С блекджеком асинхронностью, безопасной многопоточностью, очередями и back pressure

Но оно редко нужно в полном объёме

Я не программист, и всегда думал, что объект это объект, а не то, что я вот тут все это читаю)

Актор и есть объект.

А не то, что в ООП.

Но актор сложный

Потому, актор это скорее микросервис внутри монолита

Вооо, теперь все стало на свои места:)))

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

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

Нет, слишком упрощаете

Не просто так прилепили, это разрешенные/ допустимые операции над данными, не ломающие правила/инварианты.

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

Ну это уже для меня сложная материя, но благодарю). Лайки закончились))))

Лайки закончились, но спасибо за ответ.

Прикольно они это выдумали, а в универе я эту идею не уловили, прогуливал много;)

enterprice

Хорошая оговорочка )

Объяснение ООП через собак, кошек и машины не имеет смысла

Да в натуре. Каждый раз, когда вижу очередную статью про ООП с void Say(){…}, вспоминаю Футураму:

Лошадка говорит [дёргает за верёвку]: «…В докторской отказано!»

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

…вы можете развернуть последний пункт?

Конечно.

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

Реализация машины состояний (State) через объекты помогает абстрагироваться от текущего состояния машины + её данных, и использовать общие для каждого состояния методы. Например мы составляем заказ. Он может быть в работе (корзина наполняется), а может быть оплачен. Пользователь инициировал useCase "Добавить товар в заказ". Мы вытащили из базы объект заказа и вызвали метод "добавить товар". Объект заказа знает о своём состоянии. Если он в состоянии наполнения - то он добавит товар и пересчитает сумму. Если он уже оплачен, то он выбросит исключение. Клиентский код не знает о состоянии объекта, и работает с ним как с целой машиной. Это разделяет "Что/Как" и "Что/Почему". Объекты дают возможность удобно реализовать такое поведение в коде.

На счёт сторонних сервисов. Представьте, что ваше приложение использует банковский сервис. Вы можете отправлять туда платежи и получать список платежей со статусами. Для доступа к этому сервису по сети нужно отправлять API-ключи + знать, на какой url стучать. Вы можете создать объект, который будет представлять в вашем приложении банковский сервис. Сделать в нём приватные поля с ключами и url. И написать туда 2 метода: "Отправить платёж" и "Получить платежи". Клиентскому коду не нужно знать о вещах, связанных с HTTP. Только методы. Это разделяет "Что/Как", а так же позволяет тестировать клиентский код без отправки сообщений на реальный банковский сервис, используя test doubles.

DDD-Агрегаты - это набор объектов из предметной области с единой границей транзакции. Тот же пример с заказом. Когда вы добавляете в заказ новый товар - должно произойти 2 действия: создаётся OrderItem с ссылкой на товар, и пересчитывается общая сумма заказа. Нельзя создать OrderItem, и не пересчитать сумму заказа. Это одна транзакция. Объекты позволяют объединить всё, что связано с заказом, в одно место и работать с несколькими структурами данных как с одной сущностью.

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

Понятно. Спасибо.

Я на эти вещи смотрю проще и выработал что-то типа правила большого пальца. Не очень научный критерий, но очень полезный в быту. Например, есть известная статья Эрика Липперта… та, где он сошёл с ума и критикует OOP/DDD… Когда мне её показывают, я говорю: а вы давно последний раз видели волшебный меч? Вообще ни разу не видели? Тогда кто вам сказал, что class Sword : Weapon { } это моделирование предметной области? Предметная область — это class ItemCard, пачка которых идёт в коробке с D&D-подобной настолкой. Короче, надо чтобы декомпозиция не вызывала ощущения, что автор приехал к нам из мира грибных эльфов. Как-то так )

DDD-Агрегаты - это набор объектов из предметной области с единой границей транзакции

Не так жестко. Иногда приходится идти на распределенные транзакции и согласованность когда нибудь.

Агрегат как граница СТРОГОЙ согласованности (Strong Consistency Boundary)

Какая функция оптимизации, если это не жесткое правило?

Стремимся к:

  • Более точному моделированию

  • Упрощению модели отдельного агрегата

  • Снижению связности

  • Повышению масштабируемости и отказоустойчивости

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

Если у вас нету объектов и наследования в реальном проекте, значит у всех нету?

Вот у меня их полно, да и так совпало, что композицию я ненавижу.

Вот именно. Наследование в ООП самая мощная фича. Если у кого-то трудности с наследованием, это не проблема парадигмы.

Если вы для всех задач выбираете один и тот же инструмент, значит вы ещё не достигли просветления.

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

Хейтерам предлагаю показать миру хоть немного крупный backend или gamedev проект без ООП, пусть все оценят

А почему только бэкенд или геймдев? Вот есть у нас docker, tarantool, prometheus, lazygit, cockroach. Они все написаны на go. На нём же было написан бэк для дискорда, пока авторы не переехали на rust из-за ограничений GC.

Для чистого С уже сложнее, навскидку вспомнил vim, neovim, redis. Хотя там мешанина языков, а в neovim даже C++ есть.

Чем не крупный список проектов, которые написаны на языках, у которых нет встроенной поддержки ООП?

А еще есть GTK/GNOME, где из-за использования языка без ООП - C, программирование похоже на ад. Причем ад и для самих разрабов GNOME, поэтому, по итогу, они в него js встроили (в виде огромного C++ браузерного движка).

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

А еще есть GTK/GNOME, где из-за использования языка без ООП - C, программирование похоже на ад.

GTK опирается на GObject. Там буквально все ООП, просто написано на С и поэтому не так удобно как в других языках.

Любой сколь-нибудь крупный проект на С рано или поздно приходит к использованию элементов ООП.

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

Автор зачем-то предлагает все ЯП превратить в языки для крудошлепства

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

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

Да я пока все комменты перечитал, будто семь раз родился:)

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

Я поэтому Хабр и читаю, хоть и не программирую, шо бы хоть немного в трендах не теряться.

docker это обёртка вокруг linux namespaces, остальное, всё что вы назвали, из написанного на go, считать хоть сколько-нибудь надёжным при масштабировании сомнительно

А можно я покажу вам одну веточку? Может вам так чуть понятней будет, что именно вам хотят донести

Первые три части Quake.

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

Мне в голову просто приходит пример ядра линукса, который написан на чистом C

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

Да собственно так с любой догмой будет, фанатичный отказ от ООП тоже до добра не доведёт

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

А давайте MapStrategy сделаем не классом (от которого надо наследоваться) а интерфейсом - которому надо соответствовать. А в MapFunction вместо вашего ToOut сделаем функцию Map которая принимает параметром MapStrategy?

class Mapper<InType, OutType> { func Map(data[] InType, mapper MapStrategy) []OutType { ... } }

ну и далее

doubled_ints_array = new Mapper<Integer, Integer>().Map(int_array, new DoubleFunc())

nonempty_string_list = new Filter< string >().Filter(string_list, new NotEmptyStringFunc())

ООП это "несколько больше и гибче" чем вы себе представляете

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

Так на кой черт вы всю статью перед этим пытаетесь абсолютно все проблемы решать только этими инструментами?

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

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

Мне в голову просто приходит пример ядра линукса, который написан на чистом C

Я вам сейчас наверное весь шаблон сломаю:

typedef unsigned long int pthread_t;

int pthread_create(pthread_t* thread, ...);
int pthread_setschedparam(pthread_t thread, int policy, const sched_param* param);
int pthread_join(pthread_t thread, void** retval);
...

Объект, методы, инкапсуляция. На чистейшем С.

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

В ядре Linux даже лучше пример есть это структура fops с указателями на методы read, write, flush, ioctl.

Так на кой черт вы всю статью перед этим пытаетесь абсолютно все проблемы решать только этими инструментами?

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

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

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

Я вам сейчас наверное весь шаблон сломаю:

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

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

Мне кажется вы несколько путаете причину и следствие.

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

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

начинаем писать обычный сишный код, но завёрнут он не в функции и типы, а в классы и методы <...> Я вижу набор функций, которые принимают аналог джавовского "интерфейса" в качестве первого аргумента.

Вы излишне концентируетесь на синтаксисе. Главное смысл написанного, а не как это записано.

Выходит, C - это язык с полноценной поддержкой ООП?

Нет, в С нет поддержки ООП на уровне языка. Но это не мешает писать на нем с использованием ООП.

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

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

Звучит довольно размыто. Можно ли сказать, что в C реализована инкапсуляция через ключевые слова static и external? Ну вроде да.

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

Ок, такого в C точно нет. К структурам невозможно добавить метод.

Однако к структуре можно добавить поле - указатель на функцию, которая принимает параметр - структуру этого типа. И ещё одно поле - с указателем на другую подобную функцию, А можно все эти указатели на функции вынести в отдельную структуру, а в самой структуре оставить только указатель на эту структуру - вот вам vtable из С++. В Visual Studio в комплекте есть (по крайней мере, были раньше) заголовочные файлы для работы с COM (штукой глубоко ООПной) из C: там именно эта техника используется.

Но по какой-то неизвестной причине большая часть стандартной библиотеки C# написана на статических классах и статических методах.

Далеко не большая - а та, где надо взаимодействовать с ОС и прочим native кодом: там иначе не получится, потому что в ОС ООП нет, а в сторонних библиотеках если и есть, то к ним нет стандартного ABI (ну, не завезли его в C++). А всякие чисто managed вещи, типа той же TPL (Task и пр.) - они на классах с экземплярами и их методах.

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

Полиморфизма пока что нигде нет.
Когда придёт пора возвращать результат из метода действия - он появится. Результат имеет тип ActionResult<TVаlue> который един в двух лицах - либо возвращаемое значение (типа TValue), либо необощенный ActionResult. Это пока что не полиморфизм. Полиморфизм начинается, когда возвращается не значение, а этот самый ActionResult: он - базовый класс некоей иерархии, на основе которой мы можем вернуть не значение, а ещё что-то (чаще - код статуса, но там и другие варианты есть). Но в MVC API Controllers полиморфизма действительно немного: там основная работа по привязки метода действия к маршруту идет через отражение. Но если вам вдруг понадобится в методе действия доступиться к контексту запроса (HttpContext), то полиморфизма там будет много: этот контекст - абстрактный класс, большая часть функциональности которого реализована в его наследниках.

Это не шутка. Это эталонное решение в ООП-стиле.

Это - реализация шаблона проектирования "Стратегия". Который не совсем ООП - там используется аггрегирование, а не наследование с полиморфизмом. Наследование с полиморфизмом используется в другом шаблоне, решающем аналогичную задачу реализации разного поведения - "Шаблонном методе". Но для типично ФП-шной задачи - отображения одного множества на другое (что, собственно, делает Map), - использование этого шаблона проектирования нецелесообразно.

Ну то есть когда появилась возможность просто описать функцию как аргумент через ключевое слово Func, то жизнь стала проще.

Жизнь стала проще значительно раньше. Ещё в C с нещапамятных времен были указатели на функции. И не могли не быть, потому что многие низкоуровневые вещи без такого типа данных не делаются. В C++ к ним добавились (и в середине 90-х они уже были) указатели на члены класса - т.е. поля и методы. В C# изначально были делегаты (т.е. ссылки на методы объединенные с ссылкой на объект, для которого эти методы вызываются) - и без них нельзя было бы сделать конструкцию языка C# event - которая необходима для работы с тем же GUI. И так далее.

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

Тут автор просто не понимает: IEnumerable не описывает коллекцию. Он описывает последовательность элементов, получаемых по одному. Длина этой последовательности заранее неизвестна, вплоть до того, что эта последовательность даже не обязательно конечна, так что свойства Count у нее быть не может. А вот у коллекции, которая содержит определенное (пусть и переменное) количество элементов, это свойство есть. Но для нее нет понятия номера элемента и возможности получить элемент по его номеру. Такая возможнсть есть у списка (IList), И так далее. Короче, это - разные абстракции, а автор эту разницу не понимает.

В целом, к автору и статье вполне применимы слегка перефразированные слова Альфа про кошек: "Вы не любите кошекпринципы ООП. Да вы просто не умеете их готовить." У меня тут на Хабре есть статья, которая описывает решение задачи (тестовой, естественно, ибо на задачи с боя никакой статьи не хватит, даже если NDA про нее написать позволит), которая решена методами старого доброго ООП - с инкапсуляцией, наследованием и полиморфизмом. Не то, чтобы я считал это каким-то особо полезным образцом, но, думаю, тем, кто не умеет готовить ООП, прочесть ее может оказаться полезным (ссылка).

Ну, а статье автора плюс поставить не могу.

"...который официально и считается автором термина "Объективно-ориентированное программирование"

Исправьте, пожалуйста, очепятку)

Поправил, спасибо

И вот что говорит Алан Кей про C++:

Я изобрёл термин “объектно-ориентированный”. И я точно не имел в виду C++

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

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

За несколько лет до появления "того самого Smalltalk" в Simula уже были объекты, классы, и наследование.

https://en.wikipedia.org/wiki/Simula

Begin
   Class Glyph;
      Virtual: Procedure print Is Procedure print;;
   Begin
   End;
   
   Glyph Class Char (c);
      Character c;
   Begin
      Procedure print;
        OutChar(c);
   End;
   
   Glyph Class Line (elements);
      Ref (Glyph) Array elements;
   Begin
      Procedure print;
      Begin
         Integer i;
         For i:= 1 Step 1 Until UpperBound (elements, 1) Do
            elements (i).print;
         OutImage;
      End;
   End;
   
   Ref (Glyph) rg;
   Ref (Glyph) Array rgs (1 : 4);
   
   ! Main program;
   rgs (1):- New Char ('A');
   rgs (2):- New Char ('b');
   rgs (3):- New Char ('b');
   rgs (4):- New Char ('a');
   rg:- New Line (rgs);
   rg.print;
End;

Живите теперь с этим фактом "скама на первый ООП" от Алана Кея.

Цитата из моей же статьи

Удобнее и проще говорить про характерные признаки ООП. И они есть, что не может не радовать. Их озвучил программист и учёный Алан Кэй, который официально и считается автором термина "Объектно-ориентированное программирование". В последствии его идеи были реализованы в языке Simula. Алану реализация не совсем пришлась по вкусу, поэтому он пошёл делать свой язык - так и появился Smalltalk.

В последствии его идеи были реализованы в языке Simula.

А с чего такая уверенность, что это его идеи были реализованы в языке Simula, а не Smalltalk их взял из Simula?

По годам выходя языков - все равно так, сначала в Simula реализовали ООП, потом Алан Кэй реализовал свое "True ООП" в Smalltalk, и стал рассказывать что все остальное ООП не трушное. Вот только в народ ушло появившееся ранее ООП из Simula.

По статьям все тоже самое:

Самым значительным практическим результатом работы Алана Кэя в Xerox PARC стало создание языка Smalltalk. Существовавшие в то время языки программирования в основном были ориентированы на решение вычислительных задач. Они обладали необходимыми средствами для работы с символами, но были слишком сложны и не соответствовали проекту Dynabook. Поэтому разработке нового языка был отдан высокий приоритет. Некоторые его идеи были заимствованы из Simula и у Пайперта, который создавал язык Logo на основе работ французского психолога Жана Пиаже.

В википедии тоже самое: Smalltalk вдохновлялся Simula, а не наоборот.

Инкапсуляция - это сокрытие внутреннего состояния и функций объекта и предоставление доступа только через открытый набор функций

НАРОД! Давайте зафиксируем - инкапсуляция нужна для сокрытия работы объекта, вот вам и АБСТРАКЦИЯ. Вы прячете свойства и методы объекта, от КЛИЕНТСКОГО КОДА, что-бы нельзя было поменять его свойства (фиксируете при создании и строго настраиваете взаимодесйтвие с ними). А функции нужны что-бы, опять же КЛИЕНТСКИЙ КОД, был в контексте, когда вы открываете файл с объектом, у вас есть внутрення логика (приватные функции) и логика работы с объектом (публичные методы). Вижу опять лайки хейтерам ООП летят, фронтендеры, хватит)

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

Да, насмотренность на разных языках рулит

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

ООП на уровне языка со своими тремя китами (инкапсуляция, наследование, полиморфизм) очень удобно для описания НЕКОТОРЫХ абстракций. И существенно менее удобно для других. Собственно, в этом и ответ на вопрос, когда и кому нужно ООП.

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

К слову, значительная часть даже стандартной библиотеки C++ -- это не вполне ООП, иногда даже вообще не ООП.

Если ООП понимать как обязательное к исполнению везде и во всём -- это кандалы. Зачем себя ограничивать раз и навсегда? Если как инструмент, очень неплохо решающий свои задачи удобного описания НЕКОТОРЫХ абстракций -- это совсем другое дело.

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

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

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

Чем функция не обьект с оператором вызова?
Это деталь реализации, сильно зависящая от языка.

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

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

Например, для той же сортировки стратегия UserSort может содержать не только метод Compare, но и метод Prepare, который вызывается для каждого элемента ровно один раз сколько бы ни было с ним сравнений, и метод Swap, который вызывается только при inplace сортировке. Места же выбора стратегии, выбора типа сортировки и вызова сортировки могут находиться в совершенно разных слоях приложения.

Условного класса User с методом Save для сохранения данных в БД тоже не будет.

А можно узнать, почему? Я уже более 10 лет пишу на php и в последние 8 лет у меня в каждом проекте есть класс User с методом save для сохранения данных в БД.

Такое поведение сущностей, а именно Active Record, считается антипаттерном по ddd, также противоречит философии большинства orm, но имхо если число хранилищ не превышает 1, то городить что то сверх простейшего ar не имеет смысла

Сущность тем и отличается от DTO, что для неё должны быть определены CRUD-операции, где 3 буквы из четырёх подразумевают запись в хранилище. У каждого типа сущности может быть только одно хранилище. Хранилище - это не база данных, а сервис, отвечающий за запись и чтение сущностей. Сущность того же юзера может собираться из данных, хранящихся одновременно в нескольких базах, удалённых API и т.д. Но рулит всем этим одно хранилище. И тут мы, кстати, приходим к тому, что в общем смысле понятие сущности значительно шире, чем просто обёртка над ORM.

Возвращаясь к моим проектам, где сущность User имеет метод save. Все другие типы сущностей, например Product, Notification, ImageStyle и т.д. тоже имеют метод Save, т.к. этого требует интерфейс.

Возвращаясь к этим вашим DDD, на самом деле логика непосредственно записи сущности в хранилище не инкапсулирована в саму сущность. В методе save происходит что-то вроде

$entityTypeManager->getStorage($entity->getEnetitTypeId())->save($entity);

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

$entity->save();

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

В чём я вижу проблему автора, многих комментаторов, да и в целом IT индустрии: вместо того, чтобы писать эффективный, понятный и удобный в использовании код, начинаются споры "какое правильное определение ООП", "а вполне ли этот код ООП" и прочий бред. Вы, ребята, вообще не тем занимаетесь. Если сегодня я создам класс User с методом Save, а завтра на всемирном съезде информатиков примут новое определение ООП, поменяется ли логика работы моего кода от этого? Все эти термины и аббревиатуры - это теория, а любая теория - это выдумка. Это лишь словесная попытка описания сути вещей. Яблоки падали на головы людям и до Ньютона, и скорость света была неизменной во все времена. Многие просто не понимают, что программа - это не текст, смысл которого может меняться в зависимости от того, что мы понимаем под каждым словом. Программа - это физический набор битов и байтов, выполняемый на процессоре, который вообще по сути высечен в камне. Программа - это яблоко, а определения и принципы - это формулы Ньютона. Если бы Ньютон поменял свою формулу, яблоки от этого не стали бы падать быстрее, просто формула перестала бы быть верной. Точно так же с определением ООП - оно может быть верным или неверным, но это никак не влияет на работу кода.

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

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

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

А есть противоположная ситуация: вы пишите огромную многосоставную систему, которая реализует логину для сотен подразделений какого-то энтерпрайза. У вас 4 архитектора, 7 изолированных команд и под 40 разработчиков. И вот тут начинаются танцы вокруг принципов SOLID (которые в значительной мере применимы не только к ООП). Вы начинаете бороться за минимизацию каскадных изменений и за минимизацию ответственности. Вы хотите отдавать разработчикам написание отдельных минимальных компонент.

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

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

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

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

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

Да

А есть противоположная ситуация: вы пишите огромную многосоставную систему, которая реализует логину для сотен подразделений какого-то энтерпрайза. У вас 4 архитектора, 7 изолированных команд и под 40 разработчиков. И вот тут начинаются танцы вокруг принципов SOLID (которые в значительной мере применимы не только к ООП). Вы начинаете бороться за минимизацию каскадных изменений и за минимизацию ответственности. Вы хотите отдавать разработчикам написание отдельных минимальных компонент

И в ФП всё это получается лучше. А в ООП придуманы костыли. Причем, паттерны банды 4х это ещё и устаревшие костыли

У ООП есть свои проблемы это правда, но какая альтернатива? Функциональный подход, который всегда скатывается в файлы с 1000 строк кода несвязанных по логике функций. Лично я не хочу, чтобы программирование скатывалось в условный реакт, потому что код в проектах на нём очень сложно читаем из-за мешанины. По итогу, те же компоненты становятся подобием классов, если грамотно разделять логику.

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

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

Если использовать ООП не переусложняя его, то он, не станет головной болью.

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

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

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

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

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

А надо делать как в Сетях: есть ряд институтов, которые разрабатывают и определяют стандарты, на основе которых, всегда понятно, где Инкапсуляция, а где протокол, и что за что отвечает….

Чао

Ещё одна статья нытья человека, который не осилил простую концепцию. Доводы высосаны из пальца, что что-то непонятно. Люди кучу книг написали, но автору всё ещё непонятно.

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

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

И стоило ради этого интернет марать?)

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

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

• Командная работа: интерфейсы/абстрактные классы — естественные «стыки» между командами.

• Рынок: вокруг ООП-языков выросли гигантские экосистемы, их проще адаптировать, чем учить всех писать на чистом FP или DOD

Как только появляется сложность композиции и, не дай бог, необходимость паттернов банды 4х я в ужасе сбегаю в ФП где мне тепло и уютно. Как только начинаешь лепить «фабричные абстрактные декоратора-стратегии» на вершину наследуемого зоопарка, действительно хочется открыть Haskell / F# / Scala / Rust и забыть о «GOF-цирке».

Паттерны GoF сворачиваются до одной-двух строк:

• Strategy = «передай другую функцию»

• Decorator = decorated = log ∘ validate ∘ original

• Visitor = fold / cata по ADT

• Command = «значение = описание эффекта», исполни позже (IO, Task)

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

А вот и мой телеграмм канал статья про ООП

https://habr.com/ru/articles/902634/

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

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

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

Проблема 3: Абстрагирование. Если я хочу нарисовать на канве список элементов разного типа мне проще держать их в одном массиве и вызвать одну и ту же процедуру рисования абстрагируясь от вопроса что это конкретно за объекты. Внутри эта процедура могла бы делать switch/case, мир бы от этого не рухнул, и расширять списко объектов было бы не так уж и сложно, но если компилятор умеет это делать за нас в автоматическом режиме, это удобно.

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

Еще мы можем использовать ООП во всякого рода интерактивных редакторах или для построения библиотек UI. И там он как раз просто замечательно заходит, если не увлекаться. Например, коллективное поведение объектов при редактировании нет смысла пихать в объекты, но всегда есть что-то что в объектах сделать очень удобно, начиная с процедуры рисования объекта на канвасе.

ООП конечно не панацея, оно хорошо подходит для задач, когда нужно моделировать объекты реального мира. Для этого оно и создавалось. А большинство современных IT проектов - это перекладывание данных из JSON'ов в базу и обратно. Тут действительно можно и без ООП.

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

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

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

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

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

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

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

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

Здесь нет никакой философии, все просто. Когда вы пишете библиотеку UI или игру, то объекты полностью виртуальны их поведение первично. Когда объекты отражат объекты из реального мира, все становится гораздо менее конкретно и стабильно. Даже в пределах одного баундед контекста DDD такие модели могут вести себя очень по разному в разных задачах. В этом случае пихать поведение в методы самих объектов становится слишком сложно и без смысла. Я об этом.

Не, в сознаии модель как раз "анемичная", не в духе ООП. 

"А потом посылка уезжает по адресу" vs "А потом посылка отправляется по адресу"

Бывает и так и так. Оборотов (и соответственно, когда так и мыслится) когда физический объект обладает собственным поведением - масса.

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

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

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

варианты_ходов = сстояние_доски.живые_фигуры.собрать( фигура => фигура.куда_ты_можешь_пойти() )
выбрать_лучший_ход( варианты_ходов ).сделать()

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

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

А что это даст? Если фигура бы работала только со своими данными, преимущество было бы очевидным. А так ей надо знать про всю доску. Ну ок, вы передали фигуре указатель на доску. Фигура знает свои правила и может вычислить общаяясь с доской куда она может идти. Тут возникает вопрос об интерфейсе доски, с которым будет взаимодействовать фигура. Он должен быть достаточным для анализа ходов и он должен быть продуман так, чтобы не уронить производительность с другой стороны. Допустим мы придумали такой интерфейс. Теперь всмоминаем, что есть король. Фигура не должна ходить так, чтобы подставить его под шах. Значит список ходов нужно снаружи алгоритма фигуры дополнительно ограничивать. Этот внешний алгоритм вероятно опять должен использовать интерфейс доски. Дальше есть рокировка. Рокировка, это ход какой фигуры? Но мы уже придумали правила: запрашиваем ходы у каждой фигуры и анализируем их. Тут надо придумывать некий обходной путь чтобы впереть рокировку в эту нашу "стройную" систему.

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

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

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

Функция выбрать_лучший_ход фильтрует возможные ходы по этому правилу.

Рокировка, это ход какой фигуры?

Короля. Состоит из 3 шагов: сначала 2 раза перемещается король, потом ладья. На каждом шаге идёт фильтрация как сказано выше.

Какие весомые преимуществ мы получили от ООП кроме того, что простую задачу превратили в нетривиальную?

Мы разбили одну сложную задачу на множество простых.

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

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

Короля. Состоит из 3 шагов: сначала 2 раза перемещается король, потом ладья. На каждом шаге идёт фильтрация как сказано выше.

Так вроде предполагалось, что фигура возвращает куда она может переместиться. А в данном случае фигура должна вернуть куда перемещать ладью. Тут уж совсем никакой инкапсуляции.

Мы разбили одну сложную задачу на множество простых.

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

Удачи вам реализовать это в одной большой процедуре.

Почему в одной? Процедуры и функции вызывают друг друга.

Добавить новую фигуру или поменять правила для старой будет крайне просто и не придётся переписывать груду лапшекода. 

А в чем разница в переделывании кода? Что нужно добавить примерно один элемент в switch/case вместо автоматического virtual/override?

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

Не будет там десятка свитчей. Это миф из книжек про ООП.

А что ж там будет для сотен фигур?

Свитч в одном месте, а не в десятках

  • Получение возможных ходов

  • Оценка стоимости фигур

  • Влияния фигур на поле

  • Спец способности фигур

  • Представление фигур в шахматной нотации

  • Рендеринг фигур

  • Анимация фигур

  • Физические модели фигур

  • Озвучка фигур

И так далее.

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

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

Разделяя общий алгоритм поведения объектов на куски и пакуя эти куски в методы объектов мы почти никогда на практике не достигнем цели упрощения задачи за счет разбиения большой задачи на мелкие. Это миф. Обычное разделение кода на функции дает гораздо более естественную декомпозицию задачи и всегда проще.

У сообщества точно есть понимание, что такое это ваше ООП?

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

Кто-то скажет, что это было неправильное ООП (а какое тогда правильное?). Что не надо слепо следовать всем заветам ООП (а каким тогда надо?) и пр. Что ж, надеюсь в этот раз в комментариях мы раз и навсегда решим, что же такое настоящее и правильное ООП!

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

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

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

Музыка для комментария: Accept \ 1996-Predator \ Crossroads

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

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

Вот как раз про браузеры чувак даёт доклад с говорящим названием OOP Is Dead, Long Live Data-oriented Design.

Зачем вам ООП для XML-парсера?

Зачем вам ООП для XML-парсера?

Распарсенный XML (nodes), в ОЗУ нужно хранить в объектах

Вот как раз про браузеры чувак даёт доклад..

А в этой статье автор пишет, что ООП скам. Нужно всему верить?

Распарсенный XML (nodes), в ОЗУ нужно хранить в объектах

Зачем? Вот вам описание типа для XML-узлов на хаскеле (который вот совсем не ООП-язык):

data XmlNode
  = TagNode { name :: String, attrs :: [Attribute], children :: [XmlNode] }
  | TextNode { text :: String }

А в этой статье автор пишет, что ООП скам. Нужно всему верить?

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

Впрочем, видеть вопрос «нужно всему верить?» от человека, до того пишущего «я не копал, но уверен» смешно.

можно не читать статью целиком - вся суть в этих двух абзацах:

Может, у меня не так много опыта, но за всю жизнь я встретил буквально 3 проекта, которые были написаны по всем заветам ООП. С абстрактными фабриками, соблюдением SOLID и тремя слоями наследования. Читать такой код было невозможно. Менять тоже. Не подумайте, что я намеренно преувеличиваю, но когда мой тимлид передавал мне один из таких проектов, он с сочувствием посмотрел на меня и похлопал по плечу.

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

  1. расскажите, сколько у вас опыта в разработке после универа

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

  3. почему вы пишете только про достоинства функционального программирования и только про недостатки SOLID?

  4. вы пишете, что недостаток паттернов в использовании наследования. В чем проблема сделать аналогичное без наследования? То, что в учебнике это не написано - проблемы конкретного учебника, а не языка. Я когда-то читал книги по C# (печатные, на русском) - большинство написаны как под копирку по одному и тому же шаблону - введение, hello world, разобрать базовые типы (которые и так очевидны) и в конце толстой книжки пару страниц про ООП.

и т.д.

Так много вопросов и так мало ответов...

  1. Я начал зарабатывать программированием на третьем курсе университета, работая на половину ставки. Если считать этот опыт, то 7 лет

  2. Потому что SOLID придумали в первую очередь для ООП. Как и те самые паттерны от банды четырёх.

  3. Я не пишу про достоинства функционального программирования. Я пишу про недостатки ООП и не предлагаю людям массово уходить в Haskell или F#.

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

...и не предлагаю людям массово уходить в Haskell...

А зря ;)

Потому что SOLID придумали в первую очередь для ООП. Как и те самые паттерны от банды четырёх.

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

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

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

Я не пишу про достоинства функционального программирования. Я пишу про недостатки ООП и не предлагаю людям массово уходить в Haskell или F#.

Сейчас пишу на Swift. Там и функциональное программирование, и ООП, и много чего еще, чего нет в C#. ООП там от этого хуже или лучше не стало.

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

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

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

Потому что SOLID придумали в первую очередь для ООП. Как и те самые паттерны от банды четырёх.

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

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

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

Были гига-монолиты на ООП, теперь мега-микросервисы на Go, размазанные по тоннам нод, потому как так принято.

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

А что такое классный "классный" тоже определение не нужно? Ну слово красивое этого же достаточно.

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

Как мне видится это общий корень множества человеческих проблем. С организацией кода и созданием сложных программ. Управления жизни общества путём создания законов (которые имеют кучу проблем с применимостью и толкованием), психологические проблемы отдельных людей, всякие ложные идеи и дихотомии: типа, деления на настоящее искусство и имитацию, как должен себя вести "настоящий мужчина", что такое добро и зло, бессмысленные вопросы типа поиска смысла и т.п. Разум строит внутри себя модель окружающего мира из словесных костылей и каждый раз эта модель терпит крах или разваливается, так как не согласуется с реальностью.

Могу ошибаться.

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

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

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

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

Интересное дополнение. Не думал над этим.

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

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

По мнению Л. С. Выготского, центральную роль в построении высших психических функций играют речь и речевое мышление...

https://cyberleninka.ru/article/n/ponyatie-interiorizatsii-i-protsesc-interiorizatsii-rechi/viewer

Да почему, считается что мышление это проговариваемая про себя речь.

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

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

Да, давайте наконец вспомним про диджиталов, визуалов, кинестетиков и прочих

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

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

Ошибка понятий.

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

А вот кто или что заложил эти законы?. Это конечно трудный вопрос. возможно суперсущество, возможно наша Система (Вселенная в которой мы существуем) вложена в другую Систему которая и генерирует правила/заклны по которым развивается уже наша Система - я не-зна-ю.

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

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

Есть просто шикарная по накалу научных страстей книга - "The Origin of Consciousness in the Breakdown of the Bicameral Mind". Автор Julian Jaynes был американским психологом, исследующим проблематику сознания. Он пришёл к выводу, что несколько тысяч лет назад у людей в массе не было сознания, а их ум представлял "двухкамерную" систему, базирующуюся на двух полушариях мозга - и человек с таким умом сегодня был бы диагностирован нами, как человек с острым шизофреничеким расстройством личности. В книге он приводит массу увлекательнейших доводов, в том числе археологических из разных эпох, что вся история цивилизации подтверждает его теорию. Люди буквально видели и слышали "богов", умерших предков и кучу всякого разного. При этом у них не было того "внутреннего пространства", в котором бы происходила рефлексия и внутренний произвольный диалог. И при этом умудрялись организовываться и даже создавать цивилизации. Но продолжительные периоды особенно массовых и песецовых катаклизмов постепенно (но быстро в рамках исторической перспективы) сделали массовым появление сознания, которое оказалось куда эффективней в плане взаимодействия с разнообразными бедами - как на индивидуальном уровне, так и на цивилизационном. Причём, обладатели сознания отличались особенной жестокостью и часто буквально истребляли бикамеральных (которые в литературе тех времён часто называются пророками или оракулами). В общем, это словами не передать - редчайшей пример научной, в принципе, работы, которая читается взапой покруче любого боевика/триллера/дедектива/sci-fi. Правда, не знаю, как сегодня, в своё время не нашёл перевода на русский. Но если есть хоть какая-то возможность читать на английском - в высшей степени рекомендую. Вне зависимости от истинности теории - масса удовольствия, интересных идей и историческо-психологических ретроспектив.

В ообщем, книга - торт!

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

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

Jaynes introduces the concept of the "bicameral mind", a non-conscious mentality prevalent in early humans that relied on auditory hallucinations.

Прямо как современные системы из двух LLM агентов: где один генерирует ответы, а другой их критикует - провоцируя первого на дополнительную рефлексию. При этом ни тот не другой по сути не отражают смысла вопроса. Логи их переписки в самом деле напоминают записки шизофреника.

Разница, что в бикамеральном уме есть квалитативное, субъектвное содержание. Но да, чем-то похоже. Правда, в теории Джейнса бикамеральный человек беспрекословно подчинялся галлюцинируемым голосам. Кстати, есть сериал Westworld - там в первых, кажется, двух сезонах подробно обыгрывается способ производства сознания у машин именно по теории Джейнса. Для этого ИИ каждой машины структурируется по бикамеральной модели, и путём локальных катаклизмов инициируется как бы "зажигание" сознания. Ничем хорошим это, правда, не закончилось... :)

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

Можно ли сказать, что в C реализована инкапсуляция через ключевые слова static и external? Ну вроде да.

Довольно прикольно читать статью о вредности ООП от человека, настолько не понимающего его основы. Наоборот: инкапсуляция – это private, protected. И не в С – в нём к инкапсуляции можно отнести разве что локальную видимость переменных.

инкапсуляция – это private, protected

Я же привёл несколько определений инкапсуляции. И они все разные. И это одна из моих претензий

Я же привёл несколько определений инкапсуляции.

Привели. Совершенно не понимая, что в них написано. Вот это, в частности:

Инкапсуляция - это сокрытие внутреннего состояния и функций объекта и предоставление доступа только через открытый набор функций

Каким боком вообще к этому определению относится static, extern? Что с их помощью можно скрыть? Всё тут правильно написано, и ничуть не противоречит следующим двум определениям – которые расширяют, а не заменяют первое.

Особо доставляет, что Вы спорите с определениями, относящимися к ООП в контексте синтаксиса С – который вообще-то всегда был процедурным языком и к ООП относится примерно никак.

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

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

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

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

Кто познал жизнь, тот больше не спорит об ООП, а применяет его только там, где он полезен. Как и все остальное, в общем.

Две темы никогда не уйдут из Хабра - Линукс вот вот захватит десктопы и ООП это обман :)

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

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

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

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

Когда-то я был прямо фанат ООП. Страуструп был вычитан до дыр, С++ победили паскаль и стал любимым языком. Ведь там есть перегрузка операций и множественное наследование! Позже меня затянуло сначала в 1С, а потом и вовсе в PL/SQL лет на 15 (считай паскаль для БД Oracle). В 1С я поругивался на отсутствие нормального SQL и ООП, при работе с Oracle ERP подбешивала денормалищация.

Потом были весёлые истории с асинхронностью, облаками и т. д.

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

вот и я говорю граффика в документ через вижуал бейсик достаточно )

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

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

Это был сарказм.

общий пример проблемы есть 5(ой намного больше порядка 20 мегабайт) тыщ строк кода его надо и рисовать и вводить, тоесть не только создавать на момент компиляции из другой программы, это хорошо может отразить где надо функциональное, а где ООП возможно, я сейчас с этим столкнулся, емакс открывает долго некоторые тексты большого текста, так же и браузер если там большая svg(20 мегабайт), а например редактор на яве у меня и емакс шустро открывает исходный код с 4 тысячей текста

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

за счет браузера я могу открывать и на телефоне такой код )

https://developer.chrome.com/blog/colrv1-fonts/

https://simoncozens.github.io/colrv1-rocks/

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

Когда я изучал ООП, то в книжке был вполне жизненный пример TComponent <- TControl <- TButton, не повезло с книжкой вам, бывает.

А уж в ФП книжках, абстракция на абстракции чаще встречается.

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

Незнание не является аргументом. Автор об этом очевидно не знает.

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

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

Алгоритм чаще всего не разрабатывается вообще. Код как-бы накидывается полуинтуитивно из хотелок бизнеса и субстанции с палками.

Если не возводить в абсолют, то использовать там где это удобно - можно и иногда даже нужно.

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

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

Ну и конечно тут должна быть эта ссылка прямиком из 2013 :) SimplePHPEasyPlus: Складываем числа на PHP

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

ООП нужно и полезно тем, кто проектирует и пишет фреймворки.

Лучший.

Осталось понять, зачем нужны фреймворки.

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

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

По-моему, вы что-то попутали. Как это человек - оператор фреймворка - может оказаться бойлерплейтом?

Ну а стопятьсот CRUD идут от стапятисот форм, которые идут от UI/UX: конечно лучше было бы обойтись одной кнопкой, но по одной кнопке обычно только вода из бачка сливается, а требования к приложению чаще всего шире.

Но логика-то обычно не привязана к UI/UX. Поэтому функционально большинство приложений управляются командной строкой или её аналогом в виде HTTP соединения и т.п.

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

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

Бэкенд и фронтенд - это, в типичном случае, для пользователя две части единого приложения. Даже сели фронтенд - это пассивный HTML (в случае браузера), бэкенд управляется сущностями из UI фронтенда (полями формы, к примеру). Делать

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

Приложения Windows управляются формами, но сама Windows управляется сообщениями оконной системы. В данном случае Windows можно рассматривать, как бекэнд своих приложений.

Приложения Windows управляются формами,

Какими, к черту, формами? Нет в Windows никаких форм. А есть разнообразные окна: окна общего назначения, диалоговые окна, окна элементов управления...

В данном случае Windows можно рассматривать, как бекэнд своих приложений.

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

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

Ваш браузер тоже на стороне бекенда?

В каком-то смысле да. Логика работы самого браузера не управляется формами.

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

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

Если опереться на определения отсюда:

Фронтенд (англ. front end, frontend) — презентационная часть информационной или программной системы, её пользовательский интерфейс и связанные с ним компоненты; бэкенд (англ. back end, backend) — базисная часть системы, её внутренняя реализация (простым языком, серверная часть программы, что не видит пользователь).

Браузер же работает не в вакууме, а в контексте операционной системы, и он пользуется системными вызовами, которые реализованы на базе ОС. Т.е., получается, что ОС - это бэкенд для браузера, а браузер, получается, фронтенд. :) Можно, конечно, утверждать, что пара <ОС, браузер> это не программная система. Но так ли это?

Хотя мне, вообще, всё равно, только не бейте...

В мире бекенда так да, но сорян, ваш девайс спроектирован в десктопном приложении.

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

В Paint тоже логика от выкидывания GUI не пострадает? Вы код подобных программ видели вообще? Нет там никакого слоя форм и слоя ядро, вся программа, это единая сущность, все.

Опередил )

Осталось понять, зачем нужны фреймворки.

Что бы ограничивать слишком буйную фантазию.

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

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

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

Монолит, возможно, получился в противовес микросервисам. До них такого понятия не было?

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

Условного класса User с методом Save для сохранения данных в БД тоже не будет.

Будет

Будут сотни DTO без каких-либо методов,

Методы в DTO тоже будут.

Можете открыть окно, сейчас будет немного душно.

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

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

Пока выглядит как забастовочная речь без явных для нас читателей целей. Чистый скам.

Будет

Где будет? Будет репозиторий с методами Save/Read, который этого юзера принимает в качестве аргумента. Ну по крайней мере в 99% проектах на ООП-языках (и не только на них).

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

Реакция зала и комментарии на ютубе были ожидаемые. Мало кто поддержал такой подход

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

Реакция зала и комментарии на ютубе были ожидаемые. Мало кто поддержал такой подход

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

Очередное поколение зумеров борется с дидами )

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

А если визуальность понимать как метафору то воображаемая сущность (смоделированный объект) тоже подходит сюда. И без графики вовсе. То есть, оно как-бы естественно, как образы в уме.

Зашёл написать/увидеть этот комментарий. GUI это возможно лучший домен для применения ООП. В свое время поработал с Qt, Windows Forms, Swing, Delphi - везде ООП чувствовался очень уместным, а опыт с одной технологии переносимым в другую. Как минимум из-за этого не хочется называть ООП скамом, ибо каждому инструменту свое применение 🙂

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

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

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

👍

Две проблемы.

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

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

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

  2. Методологическая проблема поста.

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

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

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

    Т.е. он недееспосбоен как инженер

Её нужно снимать, если

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

Тут требуется уточнение. Совсем наоборот когда есть взаимосвязи между сущностями тогда ООП не нужно исключать, но если эти сущности всего лишь Data class без поведения, то тогда ООП можно снимать. Это в моём понимании и могу ошибаться.

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

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

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

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

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

Против такого подхода я не имею ничего против. Но я сомневаюсь, что все понимают под ООП именно это

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

Скажите пример ООП на всеми "любимом" PHP? В моем понимании это движки вроде Ларавел и прочие или я дожил до 35 и сильно заблуждался?

Вы по-моему немного запутались в определениях.
1) Интервейсы тоже наследуются, но при этом классы обязаны реализовывать весь его функционал. Наследования в плане классов практически нет потому что это банально дорого.
2) Паттерный существуют не для каких-то высших целей, а для того чтобы вернувшись к проекту через пол года можно было абсолютно спокойно понять что откуда было взято, а не сваливать все в одну кучу
3) Кей рассматривал ООП как систему обмена сообщениями, где объекты взаимодействуют путём отправки и получения сообщений. При этом он делал акцент на динамичной и гибкой природе взаимодействия объектов, а не на статической структуре, которая часто ассоциируется с ООП (классы и наследование). (Гугл в помощь). Зачем выдергивать слова из контекста если контекст предельно ясен.
4) Опять таки ООП это не религия. Это паттерн программирования. Вы что-нибудь слышали о ГОСТах например?
5) Если "Торт - это ложь" что с АОП, Процедурным, структурным и декларативными языками. Они тоже не существуют как явление

Я просто вам скажу, не читая тонну комментариев - что идеального кода не существует

ООП, по оригинальному определению, OOA&D - Object Oriented Analysis and Design, то есть анализ предметной области и проектирование сложной системы, исходя из идеи, что практически любую систему можно абстрактно представить как целенаправленную коллаборацию взаимодействующих между собой специализированных объектов, самостоятельно выполняющих возложенные на них обязанности и предоставляющих другим объектам контролируемый доступ к наборам своих интерфесов для обеспечения межобъектного взаимодействия в соответствии с определенными протоколами.

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

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

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

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

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

https://habr.com/ru/articles/885980/comments/#comment_27974176

ООП на концептуальном уровне это всего два положения:

  • все моделируемые сущности суть объекты

  • объекты взаимодействуют пересылкой сообщений

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

Создание первых ООП-языков - середина 1960-х годов (Симула-67 - "Алгол с классами"), как следует из названия, они предназначались для имитационного моделирования (объекты активны), а не для пассивных сущностей вроде счетов и накладных. Второе удачное применение - целиком искусственные миры, вроде элементов графического интерфейса пользователя.

Основные критерии эффективности подходов:

  • степень связности компонентов (модулей)

  • степень повторного использования кода

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

Есть тут несколько подводящих базу комментариев. Объектность - это фундаментальное свойство нашего мира, поэтому от ОО подхода никуда не деться. Автор правильно заметил, что всё - объекты: "Можно ли сказать, что в C реализована инкапсуляция через ключевые слова static и extern? Ну вроде да." и т. п. В функциональном ЯП связь функций через аргумент определённого типа создаёт объектность. Остаётся только сгруппировать их в класс...

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

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

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

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

Короче, сначала модель надо ещё как следует смоделировать.

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

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

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

Но не существует никакой базы по ООП. Я загуглил "основные понятия ООП" и кликнул по первым трём сайтам. И что я нашёл:

https://zinvapel.github.io/it/prog/oop/2017/10/30/oop-base/ - очень много правил. Условный закон Деметры, который тоже есть в списке, считается столпом ООП?

https://practicum.yandex.ru/blog/obektno-orientirovannoe-programmirovanie/#principy-oop - здесь просто инкапсуляция, наследование и полиморфизм

https://blog.skillfactory.ru/glossary/oop-obektno-orientirovannoe-programmirovanie/ - здесь инкапсуляция, наследование, полиморфизм и абстрагирование

Ещё и определение инкапсуляции на этих сайтах отличается.

Вы можете ответить, что надо читать первоисточник. Но автор термина ООП не считает, что в C++ есть то самое ООП. Так где читать ту самую базу по ООП?

Так где читать ту самую базу по ООП?

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

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

Без ООП некоторые вещи неудобны. Например, можете рассматривать инкапсуляцию как определённый синтаксический сахар. Если мы работаем с переменной типа FooBar, и есть операции open и close, чтобы не создавать путаницы, соответствующие функции могут называть вроде foobar_open и foobar_close, а при использовании объектно-ориентированного программирования open и close — это уникальные имена в пределах класса, не конфликтующие с именами open и close из других классов, то есть, вместо того, чтобы писать foobar_open(foobar), foobar_close(foobar), можно писать foobar.open(), foobar.close().

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

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

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

ООП — это мощная вещь, которая может помочь настроить правильную архитектуру проекта и тем самым даже сократить строки кода, просто кто-то не умеет её использовать

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

Ну как последний? А различные персонажи в играх? Например, противники с разными статами

Занимательное чтиво у вас тут.

Я искренне хочу услышать эти истории успеха в комментариях

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

Я для себя определился с двумя определениям ООП:

  1. Это объекты, наследования, интерфейсы, полиморфизм, инкапсуляция

  2. Это объекты + инкапсуляция + обмен сообщениями

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

Вторая попытка - UI-движок-генератор. Я подсмотрел идею на одном из реальных бизнес-проектов и захотел сделать такое же сам. Суть - берем классы с атрибутами (модели и контроллеры из MVC) и генерим view на vue / react / angular. Я использовал ООП, у меня вышла развесистая структура объектов с наследованиями, инкапсуляцией и интерфейсам - по сути полная модель М* и C* в памяти компьютера, с необходимыми мне свойствами. Поверх этого я наложил генератор, который проходился по этой модели от общего к частному и на выходе генерировал js / vue файлы.

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

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

В самом начале у меня были очень простые бизнес-приложения. По сути CRUD с отчетами. Я тогда писал на WinForms и у меня весь код был размещен в обработчиках button1_Click и в конструкторах форм. Тут был чистый процедурный подход - взять строку данных из БД, показать на UI, сохранить. Не было никакой бизнес-логики. Никаких domain / DI / слоеных архитектур - я тогда об этом еще не знал.

Так продолжалось довольно долго, лет 10. Я узнал про паттерны / DI / DDD / слои и так далее и стал все (ну кроме DDD) это применять. Мне казалось, что все шло гладко. Видимо позволяла сложность проектов. Они все еще по прежнему были CRUD, только теперь перекладывали json из БД во внешнюю систему и обратно. Хорошо лег паттерн адаптер (для взаимодействия с внешними системами). Иногда были очереди и местами кое-какая нагрузка. В какой-то момент я даже сделал микросервисы. Только тогда, я еще не знал что это так называется и, как выяснилось позже, я применил "анти-паттерн" - одна БД на всех. Зато с транзакциями у меня был полный порядок. Бизнес-логика если и была - то довольно простая и укладывалась в пределах IMyService.

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

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

Все эти фичи, опции, и уникальные обработчики размазываются тонким слоем по всей кодовой базе. Это просто ад. Тут я начинаю думать, что процедурный подход с анемичной моделью дал сбой. Пытался как-то реорганизовывать код. Но по сути все это было просто перекладыванием проблем из одного места в другое. Попробовать кардинально другое (полноценное DDD / функциональные языки) я не решался, потому что это долго почти с нуля туда заходить. А для DDD, к тому же, нужны были ресурсы на нормальный бизнес-анализ, которых не было.

Ну допустим. А что если действительно было бы лучше DDD / ООП? Тем более, что к тому моменту я прошел Route 256 в озоне и там дали какие-то базовые вещи о том, как проектировать предметную область и затем перекладывать это в программный код.

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

А как вы параллельно обработаете обновление остатков на складе? Никак. Там по любому где-то должно быть в один поток или откат лишнего резерва на границе перехода от "еще есть" и "уже закончилось". То есть нужны транзакции / блокировки. И что в этом случае предлагает ООП / DDD? Самому на коленке закодить распределенный ACID? Нет спасибо. Давайте лучше по старинке - например БД + хранимка + read committed (на крайняк serializable) + встроенные средства блокировок на строку в таблице - это точно работает, до определенной нагрузки и пока можем поднимать мощность сервера в условном AWS Cloud.

Но ведь хранимка в БД - это уже не ООП, правда ведь?

---

В итоге:

  1. Когда ты делаешь CPU bound - алгоритмы, расчеты, моделирование - ООП тут работает четко

  2. Когда ты делаешь простой I/O bound - процедурный поход позволяет с этим жить, при наличии нормального бизнес/системного анализа немного дольше

  3. Когда делаешь сложный, но локальный / малонагруженный, I/O data bound - пожалуй это можно осилить с помощью ООП / DDD. Ну будешь из IRepository на каждый запрос доставать полную модель, валидировать по ее правилам и потом сохранять обратно. В данном случае не страшно, пусть весь мир подождет

  4. Но вот как делать сложный облачный / распределенный / высоконагруженный I/O data bound - я пока не представляю. Совокупность требований и возможных оптимизаций начинают выводить из контекста ООП / DDD, которые могли бы помочь не размазывать фичи по всей кодовой базе.

А можно мне не выбирать между лямбдой и наследованием, а использовать нужный инструмент в нужной ситуации? Спасибо

Публикации