Сегодня я хочу попробовать формат коллективных твиттеров у себя в твиттере. Потвичу пару часов о мифах вокруг ООП. Лайк, шер приветствуется. Задание на самопроверку:
Какой вид полиморфизма имеется ввиду когда речь идет про полиморфизм в ООП?
Перед тем как я буду выдавать какие-то утверждения и прикладывать пруфы. У меня есть десяток мифов, которые я бы хотел разобрать задав вопросы тут. Поэтому продолжаю спрашивать:
Нужно ли наследование для реализации полиморфизма подтипов?
Может ли язык называться ООП если в нем нет классов?
Инкапсуляция это:
Самое главное в ООП
Возможно ли моделирование предметной области за рамками ООП? (Сущности вот это все)
Принцип лисков про классы и наследование
Дисклеймер. ООП не слишком формальная штука, поэтому мы скорее говорим о общепризнанных и широко распространенных практиках и способах организации кода, по которым этот код отличается от остальных способов. Причем этот способ общий для разных языков, а не одного конкретного.
Начнем из далека. В понимании ООП, как минимум, существует две школы. Одна "последователи Алана Кея", вторая "последователи Страуструпа и Буча". Эти школы говорят о совершенно разных вещах и не смотря на то что Алан Кей начал раньше, мейнстримом стала вторая школа.
Алан Кей изобрел термин ООП, но он не изобретал слово "объекты", он взял его из языка Simula. ru.hexlet.io/blog/posts/poc… Он говорил:
ООП для меня это сообщения, локальное удержание и защита, скрытие состояния и позднее связывание всего. Это можно сделать в Smalltalk и в LISP.
Я тут по пути подумал, а че стесняться. Мы на Хекслете ищем наставников и программистов. Если кому интересно, пишите на job@hexlet.io) ru.hexlet.io/pages/careers
Ребят, щас на часик на собеседование и я вернусь. Расскажу историю ооп и дальше уже в кишки! Пока набрасывайте)
Про Алана Кея хотелось бы поговорить по больше, но не в этот раз. Рекомендую разобраться с теми идеями, которые он распространял. Пара материалов: ru.hexlet.io/blog/posts/Ala… (о нем самом и его жизни) habr.com/ru/company/hex… (про ооп лиспы и т.п.)
Но напомню что в 2016 году он отвечал на вопросы в тред хакер ньюза, где можно найти тонну интересных мыслей: news.ycombinator.com/item?id=119398…
Ему нравится self (из которого взята прототипная модель для js)
И он считает что erlang/elixir истинно ОО языки news.ycombinator.com/item?id=143379…
> Он утверждал, что идеальный компьютер должен работать по принципам живых существ, где каждая клетка — индивидуальна, однако вместе они образовывают единую большую систему, способную масштабироваться, изменяться и модифицироваться.
Можно сказать что интернет это ООП по Алану
Теперь переходим к мейнстриму. Кто такой буч? en.wikipedia.org/wiki/Grady_Boo…
Booch developed the Booch method of software development, which he presents in his 1991/94 book, Object Oriented Analysis and Design With Applications. He advises adding more classes to simplify complex code.
The Booch method is a technique used in software engineering. It is an object modeling language and methodology that was widely used in object-oriented analysis and design. It was developed by Booch while at Rational Software.
То есть это тот самый мужик, который привил нам =>
Полиморфизм наследование и инкапсуляцию. А так же натянул моделирование на ООП, так, что многие теперь думают что понятие "сущности" есть только там где есть классы. А без объектов нельзя размышлять о поведении. Между тем, книгу "ОО анализ и дизайн", почитать стоит.
Буч является отцом создателем UML. Но то что он имел ввиду и то чем оно стало – две большие разницы. Поэтому он послал комитет и ушел оттуда. Очень крутой мужик, занимается ИИ. Крайне рекомендую интервью с ним на эту тему infoq.com/articles/booch… Для тех кто хочет понять UML
А теперь поехали в мякотку. ООП приписывают много вещей, которые в нем конечно же есть, но появились они не благодаря ООП. Более того, существуют вне него и существовали задолго до него. (я все еще не даю определение ооп, к нему надо подобраться)
Давайте начнем с полиморфизма. Когда речь идет про ООП, то в первую очередь подразумевается полиморфизм подтипов. Его еще называют сабтайпинг en.wikipedia.org/wiki/Subtyping Этот полиморфизм появляется там, где мы можем подменить реализацию чего-либо.
Представьте что в приложении мы работаем с системой кеширования и вызываем код: cache.set(key, value), а дальше соответственно cache.get(key). Как можно отключить работу кешера в тестах (он там не нужен)? Можно конечно поставить иф, что делают почти всегда и нормально живут, но
Эталонное решение с точки зрения ООП это подмена реализации. То есть на этапе конфигурирования приложения создается другой объект cache (от другого класса например), но с тем же интерфейсом. Это значит что код работающий с кешем не поменяется. То есть иф уходит в конфигурацию.
Этот подход основан на том, что мы не работаем с классом Cache напрямую (new Cache()), мы получаем его в местах использования как параметр функции. Только в этом случае возможна подмена, а значит полиморфизм подтипов. Это называется инверсия зависимостей.
Фишка в том, что этот полиморфизм прекрасно живет за рамками ООП в тех же функциональных языках. И реализуется даже проще: medium.com/elixirlabs/pol…
Насколько сильно он влияет на код и его архитектуру?
Если коротко, то полиморфизм подтипов устраняет ифы, по крайней мере они перестают быть разбросаны по всему коду и уходят на этап конфигурирования. Нам не надо ставить иф в каждом месте где мы кешируем. Достаточно создать правильный кешер (по ифу например). Второй плюс =>
С другой стороны, он позволяет расширять поведение, без необходимости переписывать код, который использует его. Можно добавить новую реализацию и передать ее в полиморфную функцию, somefunction(<любй вид кешера>). В теории звучит прекрасно.
На практике это компромисс. Ничего не бывает бесплатно. Инвертирование зависимостей усложняет код. Он вроде бы становится гибче, но только в том направлении, которое в него было заложено. Но от ифов избавляет хорошо если правильно пользоваться.
Связан ли полиморфизм с наследованием? Если почитать статьи что были выше, то видно что там везде явно прослеживается разница между типами/подтипами и классами/наследованием. Применительно к ООП языкам типы и подтипы это про интерфейсы! Ни про классы, ни про наследование.
На эту тему огромное количество материалов в сети. Гуглите по запросу: Inheritance Is Not Subtyping
Полиморфизм подтипов существует без наследования и наследование ему не нужно. Наследование может участвовать, но просто как некоторая дополнительная фича языка, не более того.
Тогда что такое подтипы? В тех же ООП языках под этим подразумевается наследование интерфейсов:
wiki > Subtyping should not be confused with the notion of (class or object) inheritance from object-oriented languages =>
> subtyping is a relation between types (interfaces in object-oriented parlance) whereas inheritance is a relation between implementations stemming from a language feature that allows new objects to be created from existing ones. =>
> In a number of object-oriented languages, subtyping is called interface inheritance, with inheritance referred to as implementation inheritance.
А теперь можно перечитать принципов лисков и переосознать его. Вот что недавно у себя в блоге написал Роберт Мартин по поводу LSP:
People (including me) have made the mistake that this is about inheritance.
А вообще LSP про предусловия и постусловия.
Беру перерыв. Завтра могу продолжить если будет интересно. Мы где-то может быть в районе середины или даже трети от всего повествования. Что скажете ребят?
Share this Scrolly Tale with your friends.
A Scrolly Tale is a new way to read Twitter threads with a more visually immersive experience.
Discover more beautiful Scrolly Tales like this.
