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

Многим конечно здесь будет этот вопрос довольно таки тривиальным. Но всё же я прошу помощи и совета. Первый мой проект был просто ужасом и повсеместным использованием Singleton-а.

В общем у меня 'типа' клон тетриса. Сверху падает объект и дел там больше нету) Суть в том что объект то разный. Может быть другой скин, форма и так далее. В этом моменте я отметил что нужно какой-то автомат который выдаёт эти объекты. Выбор пал на паттерн фабрика. Но стал вопрос. Как мне добавлять новые объекты, через ScriptableObject или Prefab. Мне понравилось работать с ScriptableObject, но при этом я не знаю как реализовать это всё через этот паттерн. В прошлом проекте я использовал шаблон объекта и подтягивал данные с ScriptableObject в новосозданный префаб. И мне это было комфортно, и паттернами там не пахло, лишь enum через switch. К тому же постоянное вмешательство во внутрь кода, что существенно нарушает принцип открытости/закрытости. Прошу пояснить этот момент. Что мне делать и какой паттерн использовать?

Это был первый момент. Второе! На объект будут применены разные силы(типа ветра, землетрясение и так далее). В этом моменте я отметил паттерн состояние. Стоить мне его реализовывать в этом контексте?

Ко всему этому хотел спросить, какие паттерны используете больше всего? Как правильно выбрать?

P.S. Прошу отнестись с пониманием к неопытному маслёнку, который стремится улучшить свои навыки в программировании. Закончив первый проект я довольно таки сильно понял что нужно писать код который можно будет потом с легкостью поддержывать.


Ответы (2 шт):

Автор решения: Andrew_STOP_RU_AGRESSION_IN_UA

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

То есть буквально делают противоположное к их предназначению - упростить жизнь.

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

Паттерн должен применяться только тогда, когда ты ПОНИМАЕШЬ ДЛЯ ЧЕГО тот или иной паттерн нужен вот той конкретной ситуации. И ты понимаешь чем он здесь вот в этом месте упростит жизнь.

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

Больше программируй и получай больше опыта - тогда прийдет понимание когда применять какие паттерны нужно в какой ситуации.

А применять паттерн только потому что ты его знаешь - это тупиковое направление.

→ Ссылка
Автор решения: Yaroslav

Забудь про паттерны! Бывают случаи когда люди пытаются подогнать задачу под паттерн надевая сову на глобус и штаны через голову. Паттерны это не палочка выручалочка, не измь есмь ответ на все вопросы.


Учись писать код опираясь на принципы SOLID. Начни с Single responsibility principle (принцип единственной ответственности), а там и выстраивать зависимости между ними научишься, dependency injection principles, что бы не сосать соску Singletona. А затем руки тянутся к интерфейсам и Interface segregation principle и ты уже отличный программист. В Open close principle, самое важное close! это тоже нужно сразу, никаких public полей в классах.

На примере тетриса. Фигару на игровой доске это просто модель данных из 1) Формы фигуры 2) Поворота этой фигуры 3) положения на доске и ВСЕ!, в ней больше ничего нет и не должно быть, доска работает ТОЛЬКО с этими данными. Форма фигуры это набор тайлов и якорный тайл вокруг которого фигура крутится, они отдельно от игровой фигуры и содержатся в какой небудь списке. Уже есть пару сущьностей: игровая доска, игровая фигура, форма фигуры, список форм фигур, все это можно написать без MonoBehaviour, обычными C# классами. Описанное является набором абстрактных сущностей, где можно примерно оценить их количество и члены, которые +/- можно было бы описать на уровне интерфейсов без реализации, речи о паттернах пока даже нет.

Про визуализацию пока даже речи не шло, потому что это ВАЩЕ другая ответственность. По хорошему визуализировать нужно так что написанный код можно было визуализировать хоть одной генерящейся текстурой из пикселей, хоть в 3D, написанная бизнес логика и модели данных не меняется ни на символ.


Данные зачастую делятся на два типа, статические данные (не static, а тех которые не меняются в билде) и переменные данные, которые нужно сохранять и загружать. К примеру у нас есть меч, это предмет, у него есть ItemData: id, name, discription, icon, viewModel, level, rarity, atkDmg, atkSpd и это никогда не меняется, и есть сокеты, вставки в сокеты, количество заточек/энчантов, какие именно бонусные статы заролились, которые уникальны для каждого экземпляра одного и того же меча в инвинторе и их нужно сохранять, что прямо говорит о том что это две разные сущности. ScriptableObject это очень удобный инструмент для хранения статических данных в проекте.

У нас есть скины, ассет объектов для разных фигур и список ассетов, тут удобно хранить их в ScriptableObject. Но список разблокированных/купленных ассетов скинов и id выбранного это другая история, это храниться отдельно и удобно сохранять и загружать поскольку суп и мухи не смешаны.


Есть даже такой паттерн MVC (Model View Controller), который гласит что модель данных, визуализация и бизнес логика отделены друг от друга. Модель ничего не знает о логике и визуализации, а бизнес логика ничего не знает о визуализации и только визуализация отображает данные реагируя на логику. Но следуя принципам, существование этого паттерна не имеет никакого значения. С паттерном "стратегия" и "фабрика" примерно тоже самое, если владеешь абстракцией, они скорее не инструмент а термин того, что это, для общения. Memento для сохранения/загрузки в ту-же корзину. Из полезных могу отметить разве что State Mashine и Visitor, ну и Singleton, несмотря на все, собирать игровую статистику/события и делать миссии/ачивки которые на них основаны, без него трудно и ряд других глобальных данных, но все-же с ним нужно быть аккуратным.


Как писал @Andrew, нужно набивать руку, дорога длинная и вся из кочек и выбоин. Пока есть ощущение что с кодом что-то не то, он не отвечает требованиям и создает проблемы, а так-же есть ориентир, то все хорошо, двигаешься в правильном направлении.

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

→ Ссылка