0

Принцип Open/Closed SOLID в Unity

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

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

ЧТО ТАКОЕ OCP

Что такое OCP - Программные сущности (классы, модули, функции и т.п.) должны быть открыты для расширения, но закрыты для изменения.

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

Принцип Open/Closed SOLID в Unity Программирование, IT, Unity, Solid, Чистый код, Разработка, Длиннопост

Реализация принципа Open/Closed в Unity

Прежде чем рассмотреть, реализацию принципа в Юнити, предлагаю посмотреть на то, как этот принцип нарушается. Часто разработчики нарушают принцип Open/Closed, добавляя новый функционал непосредственно в существующие классы. Например, рассмотрим сценарий игры, где игрок должен управлять своим кораблем. Изначально логика управления реализована следующим образом:

Принцип Open/Closed SOLID в Unity Программирование, IT, Unity, Solid, Чистый код, Разработка, Длиннопост

Теперь представьте ситуацию, когда нам нужно добавить некоторый дополнительный функционал, который должен работать по другому принципу. Например стрельбу.

Принцип Open/Closed SOLID в Unity Программирование, IT, Unity, Solid, Чистый код, Разработка, Длиннопост

Мы бы написали что-то вроде этого, и после добавили бы переменную Weapons в класс Player и вызвали бы в методе Update метод стрелять.

Принцип Open/Closed SOLID в Unity Программирование, IT, Unity, Solid, Чистый код, Разработка, Длиннопост

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

СОЗДАНИЕ ЕДИНОГО КЛАССА ДЛЯ ВСЕХ СУЩНОСТЕЙ

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

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

Принцип Open/Closed SOLID в Unity Программирование, IT, Unity, Solid, Чистый код, Разработка, Длиннопост

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

Принцип Open/Closed SOLID в Unity Программирование, IT, Unity, Solid, Чистый код, Разработка, Длиннопост

Но мы с тобой не дураки, и понимаем.. Что нам нужно реализовать массив типа List который будет содержать в себе все поведенческие типы которые нужны для работы той или иной сущности. Модифицируем наш класс Actor под наши задачи, а задача у нас простая. Реализовать контейнер поведений которые обрабатываются все в одном месте.

Принцип Open/Closed SOLID в Unity Программирование, IT, Unity, Solid, Чистый код, Разработка, Длиннопост

Теперь давайте посмотрим, на реализацию классов EnemyMovement и PlayerMovement.

Отлично, и теперь по такому же принципу мы можем изменить наш класс Weapons.

Принцип Open/Closed SOLID в Unity Программирование, IT, Unity, Solid, Чистый код, Разработка, Длиннопост

Итог

За счет того, что мы сделали методы OnEnable и OnDisable, у нас с вами появилась гибкость.

  • В методе OnEnable - мы спокойно получаем доступ к нашему Actor и добавляем себя в массив.

  • В методе OnDisable- мы спокойно получаем доступ к нашему Actor и убираем себя в массив.

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

Теги: #unitydev #gamedev #разработкаигр #unitycommunity #игрынасоздание #создайигру #учисьделатьигры #геймдев #индиразработчики #programming #design #graphics #gameart #unitylearning #beginnerswelcome #unitygames #unityengine #vkgamedev #русскоязычныеразработчики

#OpenClosedPrinciple #SOLID #SoftwareDesign #ProgrammingConcepts #Encapsulation #Extensibility #CodeMaintenance #Refactoring #OOP #CleanCode