Вам бонус- начислено 1 монета за дневную активность. Сейчас у вас 1 монета

Абстракция - ООП (Объектно-Ориентированное Программирование) на примерах

Лекция



Это окончание невероятной информации про ооп.

...

(справа) нет ни слова про конкретные имплементации (там нет слов Radar, RocketLauncher, NuclearReactor и т. д.)

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

Утиная типизация


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

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

В отличие от иерархической типизации наследования, при утиной типизации трансформеру пофиг, какого класса пушку ему дали, и пушка ли это вообще. Главное, что эта штуковина умеет стрелять! Это не достоинство утиной типизации, а скорее компромисс. Может быть и обратная ситуация, как на этой картинке ниже:

ООП (Объектно-Ориентированное Программирование)  на  примерах

ISP

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

Абстракция


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

Уровень абстракции


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

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

Неверный выбор уровня абстракции ведет к одной из двух проблем:

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


ООП (Объектно-Ориентированное Программирование)  на  примерах

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

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

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

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

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

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

ООП (Объектно-Ориентированное Программирование)  на  примерах

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

Преимущества ООП

  1. Повышение уровня модульности: каждый объект представляет собой отдельный блок, что облегчает тестирование и модификацию кода.
  2. Повышенная повторяемость кода: наследование позволяет уменьшить дублирование кода.
  3. Улучшение гибкости и масштабируемости: благодаря полиморфизму и абстракции можно легко расширять систему.
  4. Простота поддержки: инкапсуляция способствует более легкому управлению изменениями.

Недостатки ООП

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

Примеры применения ООП

ООП применяется в разных областях программирования:

  • Игровая индустрия: для создания игровых объектов (персонажей, предметов).
  • Бизнес-приложения: для создания моделей реального мира (пользователей, продуктов, заказов).
  • Графический интерфейс пользователя (GUI): компоненты, такие как кнопки, окна и текстовые поля, реализуются как объекты.

Паттерны проектирования используемые в ООП


ООП (Объектно-Ориентированное Программирование)  на  примерах

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

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

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

Еще одна ценность от паттернов — формализации терминологии. Гораздо проще коллеге сказать, что в этом месте используется «цепочка обязанностей», чем полчаса рисовать поведение и отношения объектов на бумажке.

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

Паттерны проектирования часто делятся на три группы:

  1. Порождающие — связаны с созданием объектов.
  2. Структурные — связаны со структурой классов и объектов.
  3. Поведенческие — описывают взаимодействие между объектами.

Рассмотрим ключевые паттерны в каждой из этих категорий.

1. Порождающие паттерны

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

1.1 Фабричный метод (Factory Method)

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

Пример на Python:

from abc import ABC, abstractmethod class Product(ABC):  @abstractmethod def use(self): pass class ConcreteProductA(Product): def use(self): return "Using Product A" class ConcreteProductB(Product): def use(self): return "Using Product B" class Creator(ABC):  @abstractmethod def factory_method(self): pass def some_operation(self): product = self.factory_method() return product.use() class ConcreteCreatorA(Creator): def factory_method(self): return ConcreteProductA() class ConcreteCreatorB(Creator): def factory_method(self): return ConcreteProductB() creator_a = ConcreteCreatorA() print(creator_a.some_operation()) # "Using Product A" 

1.2 Абстрактная фабрика (Abstract Factory)

Описание: Предоставляет интерфейс для создания семейства взаимосвязанных объектов, не привязываясь к их конкретным классам.

2. Структурные паттерны

Эти паттерны помогают организовать классы и объекты в более крупные структуры, при этом сохраняя гибкость и эффективность.

2.1 Адаптер (Adapter)

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

Пример на Python:

class EuropeanPlug: def plug_in_europe(self): return "Plugged in Europe" class Adapter: def __init__(self, european_plug): self.european_plug = european_plug def plug_in_usa(self): return self.european_plug.plug_in_europe() plug = EuropeanPlug() adapter = Adapter(plug) print(adapter.plug_in_usa()) # "Plugged in Europe" 

2.2 Декоратор (Decorator)

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

3. Поведенческие паттерны

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

3.1 Наблюдатель (Observer)

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

Пример на Python:

class Publisher: def __init__(self): self.subscribers = [] def subscribe(self, subscriber): self.subscribers.append(subscriber) def notify_subscribers(self, data): for subscriber in self.subscribers: subscriber.update(data) class Subscriber: def update(self, data): print("Получено сообщение:", data) publisher = Publisher() subscriber_a = Subscriber() subscriber_b = Subscriber() publisher.subscribe(subscriber_a) publisher.subscribe(subscriber_b) publisher.notify_subscribers("Новое сообщение") 

3.2 Команда (Command)

Описание: Инкапсулирует запрос как объект, позволяя клиенту параметризовать объекты в зависимости от действия, запланировать выполнение команды или поддерживать отмену операций.

Примеры применения паттернов в реальных проектах

  1. Фабричный метод: Часто используется в приложениях с многими видами объектов, таких как обработка документов или работа с различными форматами файлов.
  2. Адаптер: Очень полезен при интеграции различных библиотек с несовместимыми интерфейсами.
  3. Наблюдатель: Широко используется для отслеживания изменений в системах GUI, где взаимодействие между элементами должно быть динамическим.

Заключение

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

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

Хочется закончить свою песнь важными словами. Любые описанные механизмы, принципы и паттерны, как и ООП в целом не стоит применять там, где это бессмысленно или может навредить. Это ведет к появлению статей со странными заголовками типа «Наследование — причина преждевременного старения» или «Синглтон может приводить к онкологическим заболеваниям».

Я серьезно. Если рассмотреть случай с синглтоном, то его повсеместное применение без знания дела, стало причиной серьезных архитектурных проблем во многих проектах. И любители забивать гвозди микроскопом любезно его нарекли антипаттерном. Будьте благоразумны.

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

Вау!! 😲 Ты еще не читал? Это зря!

Продолжение:


Часть 1 ООП (Объектно-Ориентированное Программирование) на примерах
Часть 2 Абстракция - ООП (Объектно-Ориентированное Программирование) на примерах

создано: 2021-03-13
обновлено: 2024-11-13
65



Рейтиг 9 of 10. count vote: 2
Вы довольны ?:


Поделиться:

Найди готовое или заработай

С нашими удобными сервисами без комиссии*

Как это работает? | Узнать цену?

Найти исполнителя
$0 / весь год.
  • У вас есть задание, но нет времени его делать
  • Вы хотите найти профессионала для выплнения задания
  • Возможно примерение функции гаранта на сделку
  • Приорететная поддержка
  • идеально подходит для студентов, у которых нет времени для решения заданий
Готовое решение
$0 / весь год.
  • Вы можите продать(исполнителем) или купить(заказчиком) готовое решение
  • Вам предоставят готовое решение
  • Будет предоставлено в минимальные сроки т.к. задание уже готовое
  • Вы получите базовую гарантию 8 дней
  • Вы можете заработать на материалах
  • подходит как для студентов так и для преподавателей
Я исполнитель
$0 / весь год.
  • Вы профессионал своего дела
  • У вас есть опыт и желание зарабатывать
  • Вы хотите помочь в решении задач или написании работ
  • Возможно примерение функции гаранта на сделку
  • подходит для опытных студентов так и для преподавателей

Комментарии


Оставить комментарий
Если у вас есть какое-либо предложение, идея, благодарность или комментарий, не стесняйтесь писать. Мы очень ценим отзывы и рады услышать ваше мнение.
To reply

Объектно-ориентированное программирование ООП

Термины: Объектно-ориентированное программирование ООП