🧐

2.1. Вы не знаете что такое ООП

Однажды я осознал, что не понимаю что такое “настоящий ООП”, тогда я начал раскопки, во время которых поразился открытиям, о которых практически ни разу не слышал ни от одного автора.
 
И чтобы вы могли пройти мой путь и понять как я пришел к достаточно уникальному, но всеобъемлющему определению ООП, давайте перечислим то, что мы точно знаем про ООП:
 
  1. Есть определение от создателя ООП Алана Кея “ООП это ‘объекты’, скрывающее (инкапсулирующее) данные и поведение и общающиеся сообщениями” Если визуализировать, получится граф, где ребрами будут сообщения, а узлами “объекты”:
    1. notion image
       
      И да, Алан Кей, будучи молекулярным биологом по образованию, вдохновлялся тем, как взаимодействуют клетки организмов.
       
  1. Есть 4 столпа ООП:
    1. Объектная Инкапсуляция – не путать просто с термином “инкапсуляция”, который означает “сокрытие” и используется в разных областях информатики, а “объектная инкапсуляция” предполагает сокрытие свойств и методов сущности “объект” в коде
    2. Наследование – тут все понятно
    3. Объектный Полиморфизм – тоже самое с полиморфизмом, потому что это общее для информатики понятие и существуют разные его варианты (например интерфейсный полиморфизм)
    4. Абстракция – тоже не буду комментировать
    5.  
  1. Есть ООП паттерны и принципы: Singleton, Factory, Builder, Prototype, Decorator, Facade, SOLID, GRASP, Rich Domain Model, etc.
    1.  
  1. И есть синтаксис ООП с такими операторами как class, inherit, implements, etc.
 
Собрав эти “улики”, я задался вопросами:
 
  1. Относится ли это определение Алана Кея только к кодовой базе?
  1. Могу ли я написать ООП программу, НЕ используя паттерны и принципы?
  1. Могу ли я написать ООП программу НЕ прибегая ни к одному из 4-х столпов?
  1. И конечно же, могу ли я написать программу, которая следует принципу Алана Кея, столпам, принципам и паттернам НЕ используя ООП синтаксиса?
 
Давайте разбираться.
 

1. Относится ли это определение Алана Кея только к кодовой базе?

 
 
“ООП это ‘объекты’, скрывающее (инкапсулирующее) данные и поведение и общающиеся сообщениями”
 
Задумайтесь на секунду, разве такая вещь, как «микросервис» не является тем самым «объектом» из его определения?
 
  1. Микросервисы самодостаточны и инкапсулируют под собой всю логику
  1. Микросервисы общаются друг с другом сериализуемыми сообщениями (API)
 
То есть, визуализируя, мы получаем тоже самое ООП:
 
notion image
Если же мы пойдем на уровень ниже, то обнаржим, что и Процессы, обрабатываемые на уровне ядер CPU тоже являются “объектами”, которые не делят память друг с другом (инкапсулируют) и могут общаться, используя внешний транспорт и сериализуемые сообщения.
 
Получается, абсолютно любое приложение или части системы можно рассматривать как примеры реализации “ООП”. И это данность лишь потому что так устроено железо и операционные системы.
 
Но также существуют подходы, которые используют “ООП” и при этом могут быть добавлены по нашему личному желанию, например, Actor Model.
 
А еще, поразительно и крайне смешно то, что практически единственным языком, который на максимум использует “ООП” – Erlang один из самых каноничных функциональных языков программирования…
 
Просто суть Erlang в том, что каждая отдельная функция является «миниприложением», которое общается с другими функциями через очередь сообщений.
 
Опять же, визуализируем и у нас получится “ООП”:
 
notion image
 
Получается ответ на вопрос: определение “ООП” от Алана Кея, является как неотъемлемой частью любой системы, так и возможностью строить свои собственный паттерны.
 

2. Могу ли я написать ООП программу, не используя паттерны и принципы?

 
SOLID, DRY, KISS, Singleton, Abstract Fabric и так далее, все это лишь инструменты, которые мы можем, а можем не использовать для создания своей программы.
 
Да, скорее всего, пока вы будете ее делать и пытаться сохранить принципы ООП, вы столкнетесь с тем, что переизобретете эти паттерны и принципы, потому что столконетесь с такими же проблемами, что и их авторы.
 
Но при этом, никто не обязывает им следовать и вы можете написать программу вообще не разу их не применив.
 
Ответ: да, можно написать ООП программу, не используя паттерны и принципы.
 

3. Могу ли я написать ООП программу не прибегая ни к одному из 4-х столпов?

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

4. Могу ли я написать программу, которая следует принципу Алана Кея, столпам, принципам и паттернам НЕ используя ООП синтаксиса?

 
Выше, мы выяснили, что пока мы придерживаемся “Объектной Инкапсуляции” наша программа придерживается ООП.
 
Соответственно, вот вам пример, использующий синтаксис ООП:
 
class HashedPassword { public password: string; constructor( password: string; ) { this.password = hash(password) } } class User { constructor( private HashedPassword: HashedPassword | null; private activated: boolean; ) {} setPassword(password: string) { user.password = new HashedPassword(password); user.activated = true; } }
 
И такой же код, но без ООП синтаксиса:
 
type HashedPassword = ReturnType<typeof HashedPassword> function HashedPassword (password: string) { const state = { password: hash(password) } return { state } } password: string; constructor( password: string; ) { this.password = hash(password) } } type User = ReturnType<typeof User> function User ( password: HashedPassword | null, activated: boolean; ) { const state = { password, activated, } return { setPassword: (password: string) => { state.password = HashedPassword(password); state.activated = true; } } }
 
И получается, что с точки зрения ООП, это абсолютно одинаковый код, потому что User и HashedPassword инкапсулируют данные и поведение, единственное, нам пришлось добавить чуть больше нотации типов, которая создается автоматически в случае использования ООП синтаксиса.
 
Получается ответ: да, мы можем написать программу по всем столпам, определению Алана Кея, принципам и паттернам ООП, при этом НЕ использовать ООП синтаксис.
 

Подытожим

 
  1. Относится ли это определение Алана Кея только к кодовой базе?
    1. Нет.
  1. Могу ли я написать ООП программу, не используя паттерны и принципы?
    1. Да.
  1. Могу ли я написать ООП программу не прибегая ни к одному из 4-х столпов?
    1. Нет, Объектная Инкапсуляция обязательна.
  1. И конечно же, могу ли я написать программу, которая следует принципу Алана Кея, столпам, принципам и паттернам НЕ используя ООП синтаксиса?
    1. Да.
 
Получается, что ООП многогранен, вы выделяя эти грани, я пришел к тому, что сущенствует 3 вида ООП.

3 вида ООП

 
  1. ООП синтаксис – синтаксис, данный нам языком программирования, с такими операторами как class, inherit, implements, etc.
  1. ООП архитектура – разделение системы на отдельные “объекты”, инкапсулирующих логику и поведение и общающихся друг с другом сообщениями.
  1. ООП методология – те самые 4 столпа и, как следствие, все паттерны и приципы, призванные “облегчить” работу с ООП методологией.
 
На самом деле 4, но это неважно
Оригинальное определение Алана Кея включает еще механизмы, которые обязаны быть доступны в самом языке программирования, чтобы достичь того самого “идеального ООП”, но они настолько специфичны, что ему пришлось написать свой собственный (SmallTalk) и больше ниодин ЯП не стал использовать эти механизмы, поэтому мы опустим “ООП как устройство языка программирования” за нерелевантностью.
 

ООП синтаксис

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

Созидательная ООП архитектура

Как мы увидели выше, определение Алана Кея является частью любой системы (микросервисы, устройство процессов, etc.), но при этом может быть использована, как архитектурный подход (Actor Model, Erlang runtime, etc.)
 
Поэтому Архитектура ООП – или неизбежность, или крайне полезный подход к определенным задачам.
 

Губительная ООП методология

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

👈 Предыдущая глава

 
 
💡
Подписывайтесь на телеграм канал 🦾 IT-Качалка Давида Шекунца 💪, где будут выходить анонсы новых глав и обновления существующих. Спасибо за внимание и мощной вам прокачки 💪