Как лучше организовать архитектуру проекта в Unity?
Я сейчас делаю один проект на Unity
. Вкратце, это игра про космос, где игрок управляет планетой, которая "вращается" вокруг своей звезды и защищает её от разных опасностей.
У меня в проекте есть абстрактный класс AbstractMovementSystem
, от которого наследуются классы PlanetMovementSystem
и MoveToTargetSystem
. Сделано это потому, что в вышеуказанных классах всё равно был бы метод Move
и поля _maxSpeed
и _currentSpeed
, а создание абстрактного класса позволяет соблюдать принцип DRY
.
Эти классы ответственны исключительно за то, чтобы "передвинуть" объект на новую позицию. При этом вычисление этой новой позиции происходит в классах PlanetMovementCalc
и MoveToTargetCalc
, которые реализуют интерфейс IMoveCalculator
. И вот на этом месте начинаются проблемы:
Для расчёта новой позиции MoveToTargetCalc
нужны два вектора и скорость, а PlanetMovementCalc
— input
в виде значения типа float
, радиус орбиты и скорость. Как вы понимаете, если я добавлю оба метода для расчёта новой позиции в IMoveCalculator
, то мне придётся реализовать метод, предназначенный для MoveToTargetCalc
, в PlanetMovementCalc
и наоборот. Что PlanetMovementCalc
, что MoveToTargetCalc
— это, понятное дело, не нужно. Если реализовать методы пустыми, то это будет нарушением принципа Лисков, а если реализовать методы по-нормальному, то это будет просто куча лишнего кода, который не будет использоваться.
Вопрос: что же делать? Вообще убрать интерфейс из проекта, так как PlanetMovementCalc
и MoveToTargetCalc
по задумке и не должны быть взаимозаменяемыми? Или есть смысл в использовании интерфейсов? Если да, то как их использовать правильно?
(Извиняюсь за глупый вопрос, просто у меня мало опыта, и сам я "докумекать" не могу)
Ответы (1 шт):
Архитектура, как не странно начинается с нейминга! Если твоя архитектура начинается к класса GameManager
, любой скажет, что твоя архитектура ShinimaHuina, даже не уточняя, чем именно этот класс занимается.
abstract
, private
, public
и т.д. это модификаторы доступа, а не члены имён! Manager
или System
это слова паразиты в 99% случаях, когда человек не может сформулировать, чем именно сущность занимается. Аббревиатуры абсолютное зло, но сокращения допустимы, как общепринятые в конкретных областях, как например Str
, Agi
и Int
в видеоиграх, хотя когда в один случаях слово сокращают, а в других нет, это грязь и беспорядок.
Кроме того, что у AbstractMovementSystem
есть два поля, ты ни слова не написал, о его бизнес процессах. Почему называется AbstractMovementSystem
? Потому, что абстрактное хрен знает что, но что-то связанное с движением! Если разные сущности объединены только именами свойств и методов, то это их объединяет общий интерфейс, потому что никакой логики они не наследуют, как юнит и разрушаемая декорация, которые оба IDamagable
, но получаемый урон, каждый обрабатывает по своему. По двум свойствам Speed
и MaxSpeed
, можно разве что выделить интерфейс ISpeed
, хотя дико странно, что планеты у тебя двигаются с переменной скоростью и имеют потолок скорости.
В этих случаях, я честно именовал класс аля... XXX
и уже реализовав нужный мне функционал, давал имя отражающее этот функционал в контексте названий методов или разделял сущность на несколько в виду множественной ответственности.
Я не особо понял, зачем логика движения выделена в классы, почему движение планеты описано не к кассе планеты? В некоторых случаях мы выносим логику из классов, как например в паттерне State
, потому что оно меняется, но тут это зачем?
Если бы все тела в твоей солнечной системе двигались согласно Ньютоновской механике, был бы класс типа CelestialBody
, от которого наследовались все объекты и обработкой этих тел занимался бы какой-нибудь NewtonPhysics
. У тебя это не так, реальная физика игре не нужна, звезда не двигается, планеты перемещаются строго по кругу а корабли летят куда хотят, у них буквально нет ни хрена общего между собой.
Твоя проблема не в интерфейсах и вообще не в абстракции, а в том, что ты не можешь сформулировать, чё те надо то... и чё делать то... и просто бежишь впереди паровоза, что бы бежать и не думать, потому что думать это больно!