Как стать автором
Обновить

Singleton в Unity3D

Время на прочтение 4 мин
Количество просмотров 13K

Предисловие


Здравия желаю, уважаемые пользователи Хабра. В этой публикации речь пойдёт не столько о правилах использования Singleton'а, сколько о моём видении этого паттерна.

Хочу предупредить, что человек я совершенно зелёный. Я не гуру программирования, не сеньор и возможно, что даже не middle. Адекватный опыт разработки имею исключительно в Unity, по сему затрагиваю только данную среду. Изначально было страшно делиться своими мыслями, но вспомнив, что порой тут публикуют серьёзные дяди, решил попытаться. Я люблю пользователей данного сайта, и даже если моя карма уйдёт в Марианскую впадину, то комментарии всегда помогут мне понять то, чего не смог понять ранее и найти ту самую истину!

За что же ненавидят паттерн Singleton


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

Давайте разберём некоторые из них!

Нарушение принципа единственной ответственности. Простите, что? По какой же причине наш Одиночка со 100% вероятностью нарушает этот принцип? То, что класс имеет глобальную точку доступа, не переносит его в разряд GOD-класса. SoundManager? NetworkManager? SceneManager? Даже в официальном уроке Unity3D SoundManager создан именно Singleton'ом. Видимо, данный пункт отпадает.

Singleton невозможно тестировать. Иными словами, аргумент людей заключается в том, что Одиночка сильно связан с объектом, изначально хранится в памяти и невозможно запустить тест, исключив его из работы приложения. Возможно, для людей не понимающих жизненного цикла класса MonoBehaviour всё так и будет. Но давайте поговорим на чистоту. То, что наш единственный instance создаётся в методе Awake(), не означает, что это обязательное условие для создания Singleton'а. Вы можете завернуть его инициализацию в любой другой метод и создать его только тогда, когда он вам впервые понадобится. Кроме того, люди почему-то говорят о том, что Singleton чудесным образом передаётся сквозь сцены. Для чего же тогда используется DontDestroyOnLoad? Загадка.

Тесная связь. Написав тысячи строк ужасно связанного кода, я как никто понимаю что такое страдать от багов, появляющихся в каком-то классе, при изменении другого. Но как вы считаете, является ли Singleton источником этой проблемы? Я — нет. Проектирование, и ещё раз проектирование. В одной из статей (простите, не смогу указать ссылку, ибо читал её невероятно давно) говорилось о том, что нужно уделять до 80% времени на проектирование структуры приложения, после чего дело пойдёт как по маслу. Я абсолютно согласен с этим.

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

Сегодня я посмотрел невероятно информативную презентацию об использовании Scriptable Objects. Она называется «Unite Austin 2017 — Game Architecture with Scriptable Objects». Материал будет полезен каждому Unity-разработчику. Выступающий приравнивал Singleton к стихийным бедствия, ядерной войне, говорил о том, что их студия старается создавать в играх prefab'ы, которые были бы самодостаточными и не имели тесных связей. Повторюсь, на мой взгляд — решение превосходное. Но что если наша игра требует связей?

Один из основных примеров использования Scriptable Objects — это игра Heart Stone, которая, как вы возможно знаете, частично сделана на Unity3D. Круто. Прекрасно. Восхитительно. Только беспокоит одно большое «НО». Создание карточек для Heart Stone может ограничиться табличкой в Excel, где мы забиваем имя карты, её описание, ману, атаку и конечно же хит-поинты. Готово. А вам потребовалось вот создать игру в которой всё завязано на генерации. Генерируется ландшафт, генерируются предметы, генерируются персонажи, генерируется даже то, что отвечает за генерацию. Паттерн одной из фабрик? Строитель? Ну, возможно. Наши сенсеи вряд ли станут врать. Минусами этих паттернов является загруженность лишним кодом и его общее усложнение. Я ни в коем случае не говорю о том, что нужно отказаться от использования любых паттернов кроме Singleton'а, я лишь хочу призвать людей не бояться Одиночек и не плодить паттерны там, где они не нужны, что может привести к неуместному усложнению архитектуры.

Немного дополнений


Зачастую мы можем видеть решения, которые выглядят совсем как «не синглтоны». Разработчики извращаются любыми методами. Делают public переменную для класса, перетаскивая в инспекторе единственный объект с нужным классом на другие сотни объектов, которым нужна эта ссылка. Вызывают в методе Start() GameObject.Find(). Зато не Singleton, здорово, правда? Связанность есть, Антипаттерна нет. Чудеса.

Основной проблемой Singleton'а среди начинающих разработчиков является то, что не нужно сильно задумываться о структуре. Из-за чего весь код обрастает Одиночками. Доступ к любому методу без ссылок, монолитность архитектуры. Всё это плохо, но каждый пишет код в меру своей грамотности. Будем честны. Программирование — это не просто вид деятельности, это полная смена образа мышления. Невозможно прочесть книгу на 700 страниц, сесть и сделать идеальную архитектуру. Всё приходит с опытом. И если ваш путь начался с монолитов — это совсем не повод отчаиваться. Понимание наличия проблемы — первый шаг к её решению!

Also, чрезмерное использование Singleton'ов абсолютно идентично чрезмерному использованию любого другого паттерна. Никто не даст вам печеньку за то, что вы сделаете абстрактную фабрику и 30 интерфейсов для класса, единственным назначением которого будет смена фонового изображения.

Семь раз отмерь, один раз отрежь!

Возможно, если комментарии будут очень насыщенными, я смогу дополнить эту статью или даже сделать 2 часть. Буду надеяться на критику моей писанины. Всем спасибо за внимание!
Теги:
Хабы:
+4
Комментарии 29
Комментарии Комментарии 29

Публикации

Истории

Работа

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн