Wild Russian GameDev Mentor
98 subscribers
116 photos
5 videos
60 links
Обучаю созданию игр на Unity и программированию на C#.

Запись на занятия – сообщения канала
Лайвкодинг/игры – twitch.tv/ko1ba5er
Бустануть канал – t.me/boost/WRGDM

Please, be patient, я не умею пользоваться отложкой.
Download Telegram
SOLIDное программирование #3

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

Оглавление:
S – Single Responsibility
O – Open-Closed
L – Liskov Substitution
📍
I – Interface Segregation
D – Dependency Inversion
(Bonus) DRY – Don`t repeat yourself

📯L – Liskov Substitution

Пропустим матан от Лисков👩‍🔬, давая определение от любимца публики Боба Мартина😎:

– функции, которые используют базовый тип, должны иметь возможность использовать подтипы базового типа, не зная об этом🤷‍♀️.


Ну, вроде, базированная база, но давайте разберем подробнее✍️.

📯Почему это важно?

Все очень просто. Вот, к примеру, есть у нас класс Enemy😈 с методами ближней⚔️ и дальней🔫 атаки. И, прописывая партизана-снайпера🔭, мы поленились и кинули ему в метод ближнего боя NotImplementedException – один хрен, он за три километра стихарился🥷, и его никто никогда не найдет🔍. Вот тут-то и вылезает г-жа Лисков, и толстенный том вышмата приземляется нам на затылок🔨. Потому что как бы далеко в лесу снайпер ни сидел, все равно какая-нибудь собака подойдет и его за жопу схватит😈. А потом и нас схватит. А все потому что сказано было:

В любое место, куда впихуется базовый класс, должен впихиваться и наследник. Без любых условий🙅‍♂️.


И ладно бы Exception, его мы на Unit-тестах отловим🕸 или, хотя бы, QA нам по роже надает👊. Хуже, когда объект, вроде бы, работает, но возвращает null или другую опасную белиберду. Потому что эти гады🐍 могут притвориться нормальными, а потом выскочить в самом неожиданном месте, а концов уже не найти👻.

📯Звоночки со дна (колодца)

И в заключение вот несколько подсказок, которые помогут распознать в себе нехорошего человека🤬:

1. Возникает необходимость (или просто интуиция подсказывает) некоторые места использования базового класса завернуть в try-catch.

Не надо🙅‍♂️. Лучше подумай, в чем причина. Потому что все места, которые следует обезопасить🛡 ты никогда не найдешь🔍.

2. if (Obj is Subclass)

Это просто пиздец😁. Переделывай все. Скорее всего, вся архитектура у тебя через жопу🍑. Звони начальнику и выбивай 3-4 недели на рефакторинг📞.

3. Наследник не использует функции базового класса.

В принципе, с этим можно жить👌. До поры до времени🕙. Потому что даже если мы не кидаем Exception или null🎯, отсутствие использования – это часто отсутствие адекватного ответа, потому что класс его просто не знает😐. Это не обязательно приведет к проблемам, но это узкое место, которое может привести к проблемам🚨. Домашнее задание – подумать, почему нельзя наследовать квадрат от прямоугольника (загуглите, если сдаетесь).

🤡 – щас секундочку, щас я позвоню уточню, она че-то не сказала мне, блин...
Подставила меня опять. Блин, не берет еще и...
🍾Подставляйте стаканы, у нас тут разливают базу
🪕 – В моем сердце дырка, мне нужна таблетка💊🫦
Please open Telegram to view this post
VIEW IN TELEGRAM
421🍾1
Wild Russian GameDev Mentor
ОТЧЕТ ПО НЕЙРОСЕТИ СО СТРИМА #5 Для начала, вкратце напомню, что изменилось за прошлый стрим🆕: 📯Добавил новый вид препятствия: летающие ящеры🐥. Проблем они вообще не доставили. Сетка обучилась за пару поколений по-разному реагировать на разные препятствия🏃‍♂️.…
ОТЧЕТ ПО НЕЙРОСЕТИ СО СТРИМА #6

📯Для начала, вкратце напомню, что изменилось за прошлый стрим🆕

1. Создали новую игру для тестирования возможностей нашей нейросети: Flappy Dino🐔.

Сделал это для тестирования скорости переноса существующей нейросети на другой проект🚜. Получилось даже лучше, чем я рассчитывал😎.

2. Попробовал увеличить дистанцию, на которой появляются препятствия🔭.

Теория была в том, что на максимальной достигнутой скорости (~5200 очков) динозавры🦕 должны прыгнуть раньше, чем объект появляется на экране. Прорыва не произошло🚱. Видимо, одного этого недостаточно😔.

3. Добавил график сходимости – зависимости результата от времени📈.

Это ключевой показатель в оценке окружения нейросети🔑. И чем он ровнее, тем лучше – это значит, что на каждой итерации приспособленность увеличивается📈. Ну и иногда неровный график может значить, что сама сетка сбоит, но это видно и по другим параметрам (у меня такого нет)👍.

Пока что грешу на случайность🎲 игры и плохую физику, которая вносит погрешности, но разброс значений какой-то слишком огромный🎯.

📯Результаты ночного прогона

Переходим к картинкам. Огромному числу в таймере не удивляйтесь, в этот раз Unity решила не жрать🍬 всю память и позволила мне увеличить скорость в 100 раз💨. Тем не менее, уже после девяти часов сетка в обоих вариантах упирается в потолок. Что указывает на проблемы с игрой: либо там непреодолимое препятствие🌳, либо слишком узкое горлышко🍾.

📯Что будет через неделю

1. Хочется добить идею с простой интеграцией в любое окружение⚙️.

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

2. Будем опять разбираться в том, что же тормозит эволюцию🧬.

Наверное, поковыряемся с механизмом отбора👁 и условиями игры.

3. Попробуем написать игру с кардинально другими условиями.

Наверное, что-то головоломко-образное, чтобы проверить ее интеллектуальные способности🤪.

Хочется попробовать какую-нибудь пошаговую тактику или даже стратегию🗺, но для этого надо будет прикручивать сетке память, так что, думаю, пока ограничимся аркадами🕹.


А вы все еще пишите свои идеи для новой игры в комментариях⬇️

P.S.
Потрогать проект своими руками можно на гите!
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👀2💅11
ПРОЩАНИЕ С ИДЕАЛИЗМОМ или КАК Я ПОЛЮБИЛ ГОВНОКОД

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

📯Только ситхи все возводят в абсолют.

Если вы читаете мои статьи📖, то знаете, что некоторые положения т.н. "чистого кода" в абсолютной форме противоречат друг другу, здравому смыслу и даже сами себе🏥.

Как ветеран срачей в интернете🫡 и обладатель десятка проектов👍 (выпущенных и нет🎓), я вам авторитетно заявляю: чистый код недостижим🙅‍♂️. Он как скорость света: чем ближе мы находимся, тем сложнее следующее продвижение🏎.


И вот мы убили на это свое здоровье👨‍⚕️, все бабки заказчика💵, возможность жить в социуме🌚... А все равно какой-нибудь душнила🤓 скажет нам, что наш код говно. И, что самое удивительное, будет прав😎.
Потому что чистота в глазах смотрящего👁.

Программирование, как и архитектура – это искусство👨‍🎨, тут можно достичь одного и того же результата кардинально разными способами, у каждого из которых есть свои плюсы и минусы🤨.


Нельзя сказать, что арочный мост однозначного лучше подвесного🌉. Так и у нас.
Конечно, это не разрешение вам писать монолит🧐 – границы-то знать надо! Отличайте, пожалуйста, выбор архитектурного решения от выбора насрать себе в штаны💩.

📯Это просто непрактично

Я вот иногда сплю🥱, и вижу всегда один и тот же сон☁️: каждый продукт, который я создаю, имеет бесконечный жизненный цикл, заказчик не закроет его через месяц🍌, условия рынка не меняются🎉... А еще бюджет бесконечный💰...... А потом я просыпаюсь и вспоминаю, что

На самом деле задача программиста: написать за три копейки😭 то, что будет кое-как работать💻. Но чтобы можно было масштабировать🙈, ЕСЛИ тестовый запуск покажет хорошие результаты😉.


В таких условиях не до белых перчаток🧤. В таких условиях чистый код – это роскошь💎, мы можем иметь его ровно столько, сколько необходимо для функционирования проекта, ни граммом больше🤏.

📯Чистый код как анкап – не точка назначения, а моральный компас.

Следовать правилам хорошего кода необходимо процентов на 60-80😉, в зависимости от ситуации. И только если это необходимо + если это не слишком дорого (по времени, хотя это то же самое).


А в остальном, вы должны примерно представлять, в какую сторону🧭 вы будете потом рефакторить🖥. Делать же что-то для этого можно только в том случае, если это не отвлекает вас от настоящей работы – пилить фичи🪚 и фиксить баги🐛.

🪕 – За три сотенных к/наносек на селе возил говяшки, ой-ой-ой
🤡 – Писать говнокод – это милосердие
Please open Telegram to view this post
VIEW IN TELEGRAM
53🔥1💅1
SOLIDное программирование #4

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

Оглавление:
S – Single Responsibility
O – Open-Closed
L – Liskov Substitution
I – Interface Segregation
📍
D – Dependency Inversion
(Bonus) DRY – Don`t repeat yourself

📯I – Interface Segregation

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


Или в формулировке Немчинского:

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


Или, как бы сказал я:

– Интерфейс делается ОТ и ДЛЯ клиента


Выбирайте любимчика🥰.

📯Интерфейс, клиент.. Статья для фронтендеров, что-ли?

Под клиентом в программировании подразумевается клиентский код👩‍💻 – тот код👩‍💻, который потом будет использовать наш код👩‍💻. Это важно не только при написании библиотек📚, но и для грамотного распределения обязанностей и ролей🎭.


Рассмотрим пример с моим проектом по ИИ🤖:
Класс самой нейросети довольно огромный🐖. При том в клиентах – динозаврике🦕 или котике😼 – нужны только три метода: конструктор, мутатор и обработчик. Все остальное используется для дебага🐛, наглядности👀 и вообще красоты.

А, следуя ISP, я бы мог:
1. Легко заменить класс под интерфейсом на другой🔄 (допустим, украл бы чужую более удачную реализацию🥷).
2. Не видеть лишних членов класса там, где они не нужны🙈.
3. Снизить количество классов, через которые проходит ось изменений.
4. Да и вообще отделить мультиответственное чудовище🦍 от нормального SOLID-friendly кода🐱.


📯Так стоп, мультиответственный класс.. А ЧТО ТАМ С SRP?!

Поздравляю, вы нашли первое противоречие в словах всеотцов программирования👁. Сначала немного пощиплет🩸, зато можете взять шоколадку на выходе🍫.

Да, ISP нужен исключительно при нарушении SRP💔. Что немного нормализует нарушение SRP, не правда ли🤭? И действительно, кому в голову придет разделять интерфейсы, если идеальный класс содержит не больше одного метода🤔?


Даже в моем примере можно упаковать📦 класс чистой нейросети в отдельный класс-дебаггер.
Но.. зачем? В общем, на мой взгляд это паттернодрочерство🤓.

📯И все-таки, ISP полезный

В моем примере можно сказать, что просто я рукожоп, и надо было вообще все по-другому сделать (напишите это на бумажке и съешьте👏). Но зачастую ситуация в том, что есть огромные Фасады, код бюрократии или просто 20-летний энтерпрайс, с которым так или иначе придется работать💩.

Говно не исчезнет и не перестанет быть говном, если его (даже очень громко) осуждать в интернете💻. С говном нужно уметь работать и, по возможности, рефакторить💩. И ISP говорит, как.


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

🤡 – пост про сегрегацию, ОСУЖДАЮ
🤬 – интерфейсы как туалеты. Клиентно-нейтральных не должно быть.
Please open Telegram to view this post
VIEW IN TELEGRAM
32💅2🤬1
А в честь традиционного русского весеннего снегопада весь апрель скидка на занятия 15%
Пишите промокод "СНЕЖИНКА" или пересылайте этот пост при записи💌
Писать в ДМ канала👀
👀7
НИКОГДА НЕ ВОЗВРАЩАЙ NULL

В нашем любимом Си Хэштег-чике, как и во многих других ООП-языках😛, есть такие понятия как значимые⚙️ и ссылочные🫵 типы. И все ссылочные хранят (наберите воздуха в грудь😂) ссылку на данные. Так вот, эта ссылка может куда-то вести – тогда все нормально👍 – а может и не вести – это-то и называется null👎.

📯Как дьявол нас искушает

Написали метод, который возвращает самого сочного трапика🏳️‍⚧️ в стране. А потом что-то случилось🤨, и трапиков в стране не стало🧐. И что надо тогда вернуть🤔? Стандартное решение – null.

Иными словами, null чаще всего отдают🫳, когда метод не может правильно выполнить свою функцию🤔.


📯Чем придется заплатить

Null – это диверсант-смертник💣, который притворяется обычным гражданином. Null – это отсутствие несущего кирпичика🧱. Null – это арматура на дне мутного озера🦑.


Вам уже страшно? Так и должно быть👹. Корень🌳 проблемы в том, что null можно положить вместо любой ссылки🤲, то есть почти куда угодно, без каких-либо трудностей💨. И будет он тихонечко себе лежать🤭, а на другом конце, где ты захочешь использовать данные, которые должны бы быть в этой переменной, ОПА😐! А данных-то нету! И хрен ты свяжешь место, где null появился и место, где он вылез🧶.

В итоге получаем плавающую ошибку🏊‍♂️, которая не отслеживается по цепочке вызовов, и вообще не сразу понятно, кем и чем вызвана🤨.

Вы скажете, так делай проверку на null🤓. Да хренушки! Беда в том, что эта проверка сама по себе не гарантирует ничего🤪. (Если не делать ее перед КАЖДЫМ использованием любого объекта, конечно...) Ведь мы никогда не знаем, откуда может прилететь null✈️.

📯Что делать?

1. Как сказано в названиии, никогда не возвращай null.
Простой совет, не правда ли? Если твой метод не может отработать правильно, кинь Exception⚠️, пусть программист сразу знает, что есть проблема, а не пребывает в счастливом неведении😋. Хорошим примером будет First и FirstOrDefault из LINQ: один возвращает MyClass, а другой – MyClass?.

2. Если ты рукожоп и не можешь следовать первому пункту, хотя бы используй Nullable.
Тип Nullable<MyClass> – декоратор🥹 над MyClass, который указывает "🚨АХТУНГ!!! ТУТ МОЖЕТ БЫТЬ NULL!🚨". Сокращенно записывается как MyClass?. Таким образом мы пометим потенциального террориста👉, и перед тем как пускать его в работу, можем дополнительно проверить🛂.

😭 – Заглянул в переменную MyCareer, а там null😭...
🤣 – Ааа, nullевой пациент – это пациент дурки😂
Please open Telegram to view this post
VIEW IN TELEGRAM
🤣3😭2💅21
SOLIDное программирование #5

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

Оглавление:
S – Single Responsibility
O – Open-Closed
L – Liskov Substitution
I – Interface Segregation
D – Dependency Inversion
📍
(Bonus) DRY – Don`t repeat yourself

📯D – Dependency Inversion

– Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.


📯В принципе, тут все очевидно

Давайте немного откатимся назад, к основам🔙. Нам вообще зачем нужно наследование🤱? Очевидно, чтобы сделать базовое поведение, от которого мы будем расширяться при необходимости.


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

И, помня об LSP, мы рассуждаем🤔: "Ага, значит, везде, где всовывается базовый класс👵, должен всовываться дочерний👧. Ну, значит, нужно их привести к одному интерфейсу♊️... К наследнику🤡 (ведь строить проще, чем ломать)!"

📯А вот и нихренашеньки!

Во-первых, тогда у нас количество нарушений LSP не уменьшится, а скорее всего, даже увеличится😱.


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

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


Цель ООП как раз состоит в том, чтобы ввести разные уровни "глобальности" мышления🧠, потому что человеческий мозг не может одновременно думать о вечном😇 и о насущном🍞. А когда мы перемешиваем частное с общим, наше красивое разделение на слои сыпется в момент💔.

📯Вывод

DI дополняет LSP, делает следование соседнему принципу осмысленным🧠. Да и сам по себе он полезный и важный. Любите DI❤️.

🤔 – Слои абстракции какие-то были упомянуты, а можно поподробнее?
🤣 – Я тоже зависимый (от написания кода)
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔2🤣22💅11
This media is not supported in your browser
VIEW IN TELEGRAM
531
Wild Russian GameDev Mentor
Video message
По дороге с пляжа еще и подобрал пачку сухариков🍀🦋🦋
Любите природу, мать вашу😡!!!
Please open Telegram to view this post
VIEW IN TELEGRAM
🤩5🗿3
А ССЫЛОЧКУ МОЖНО? СПАСИБО, БЛЯТЬ...

Давайте немного отойдем от высокопарных метаний умными словами🧘 про архитектуру и всякие абстрактные эфемерности, а поговорим сегодня о таких твердо-измеримых понятиях📐, как reference types и value types.

📯Кто есть кто

Value types (Типы значений) – те, переменные которых содержат непосредственно данные📦.


К ним относятся:

Integers (в т.ч. byte, long и т.п.)
Floats (аналогично, double, decimal и пр.)
bool
char
enums
structs (это как классы, только value type)
value tuples (это как Tuple, только value type)
string

Reference types (ссылочные типы) – те, переменные которых содержат рисунок ключика ссылку на данные.


К ним относятся:
class (и другие варианты его объявления, типа, record, interface).
dynamic
object
string

📯Ну и в чем разница?

Ключевое различие проявляется, когда мы копируем значение переменной👯‍♀️. Так, для value types мы копируем то, что в ней лежит – само значение📦. А вот для reference types мы копируем то, что в ней лежит – ссылку на значение➡️.


Заметили? Получается, для ссылочных типов объект по ссылке один и тот же☝️.

В результате, когда мы пишем
int a = 10;
int b = a;
b = 5;

, в a останется 10, так как мы скопировали 10.

А вот когда мы пишем
List<string> names = new ();
List<string> names_copy = names;
names_copy.Add("Albert");

, в оригинальный names будет добавлен "Albert", потому что список-то один и тот же!

📯А что там со стрингами👙?

Вообще-то, string относится к reference types, однако его операторы (+, = и т.д.) определены так, что внешне он выглядит почти как value type. Такие пироги🥮.


Кстати, помните пост про null? Так вот, его мы можем положить только в reference types, потому что он, в сущности – пустая ссылка0️⃣. А в string можно положить null. Что и требовалось доказать🤓.

📯Модификаторы параметров

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

ref – передает в качестве аргумента не значение переменной, а ссылку на эту переменную🫵. Можно в нее будет, что-то записать, но не обязательно🤷‍♀️.
out – похоже на ref, однако метод обязан🤨 что-то положить в эту переменную. Используется, если метод возвращает два объекта разных типов💕. Пожалуйста, пользуйтесь out, а не Tuple😐...
ref readonly – то же, что и ref, но теперь изменить значение по ссылке нельзя🔐. Используется, чтобы избежать копирования большой и тяжелой структуры при передаче в метод🪨.
in – то же, что и ref readonly, но туда можно передать как значение📦, так и ссылку на значение.


Эти модификаторы пишутся при объявлении метода, а также при его вызове📞:
int x = 7;
void ChangeMyNumber(ref int n)
{
n = 42;
}
Console.WriteLine(ChangeMyNumber(x));
//Вывод: 42


Боевой👊 пример можно посмотреть в Physics.Raycast в Unity📱 (там используется out).

📯А еще есть object

Он reference type и является родительским классом для вообще всех классов в C#👵. Да, даже для тех, которые value types😧. Нужен он для предоставления базовых интерфейсов, таких как Equals, ToString и др.💻

А еще с value types можно делать прикольный boxing-unboxing🥊. Пожалуйста, никогда его не делайте, он генерирует путаницу и не дает никаких выгод🌟.

❤️ – Хочу еще таких постов про механизмы конкретно C#
🤡 – Я не разговариваю на вашем языке C#, давай что-то про 1С
Please open Telegram to view this post
VIEW IN TELEGRAM
7💅321
SOLIDное программирование #6

А мы продолжаем разбирать принципы проектирования. В прошлый раз решили, кто тут от чего зависимый🚬, а сегодня поедим сушек😗.

Да, DRY не входит в SOLID, но давайте его бонусом разберем💝. Этот принцип является в определенной степени дополнением и повторением всех прошлых, так что я выбрал его для завершения нашего цикла🏁.

Оглавление:
S – Single Responsibility
O – Open-Closed
L – Liskov Substitution
I – Interface Segregation
D – Dependency Inversion
(Bonus) DRY – Don`t repeat yourself📍

📯DRY – Don`t repeat yourself

– Каждая часть знания должна иметь единственное, непротиворечивое и авторитетное представление в рамках системы.


В этом коротком определении совмещаются SRP, LSP и DI.

📯SRP

Помните Single Responsibility Principle? О том, что одна ответственность = один класс = один фю. Так вот и здесь что-то похожее, но с другой стороны: если у нас ответственность уже реализована, мы не имеем права ее повторять где-то еще👯‍♀️.


Но как тогда сделать похожий, но немного другой функционал🤔?

📯Наследование (LSP и DI)

Тут мы подходим к ООП🤱. Код должен быть непротиворечивым: если B -> A, то B делает все то, что и A. Ничего не напоминает?


Ну, это если по самому очевидному пройтись🤓. А если отойти от параллелей с другими принципами и посмотреть внимательно на DRY, там главная идея💡

ни в коем случае не повторять то, что уже написано👎. Если все же нужно сделать что-то похожее, но другое, то надо добавить над ними общего предка👵, и все общее вынести в него☝️.


А при вынесении предка с ноги мы внимательно смотрим в DI, который нам помогает не ошибиться😑, особенно, когда мы строим иерархию наследования снизу вверх🙃.

В общем, идея почти во всем хорошая, и с ней даже сложно переусердствовать💻. Но, теоретически, возможно, так что вы все равно там поосторожней🖥.

📯Подводя итог

Самое главное🚨, что я хотел, чтобы вы поняли после прочтения цикла СОЛИДНОЕ ПРОГРАММИРОВАНИЕ – это то, что все эти паттерны суть – волчьи цитаты🐺 уровня "Если волк молчит, то его лучше не перебивать". Вроде бы, ух, сука, сос мыслом👺, но, если задуматься, то возникает куча вопросов🐺.


А вот если волк молчит, потому что он спросил и ждет ответа? Или если волк умер от кринжа💀? То есть, о применимости такого принципа повсеместно. Также как и куча вопросов о совместимости🧐 отдельно взятого принципа с другими умными словами легендарных дядек🤓.

🤡 – фух, наконец-то месяц Clean Code`а закончился, можно снова писать монолит😁
🪕 – Я уже говорил тебе, что такое безумие?
Please open Telegram to view this post
VIEW IN TELEGRAM
53💅2
Вы у меня часто спрашиваете, какая погода на море "Привет, можно с вами🥺?" И теперь у нас наконец-то будет ответ, который вас удовлетворит: ДА, МОЖНО😦!

Ведь мы c @BO3bMAK открываем СЕРВЕР ПО МАЙНКРАФТУ🌎!!!
Survival + 1.21.5 + BlazeandCave's.

📱 Как зайти 📱

А как я сам играю
📱 смотрим тут 📱.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5🎉22💅1
ПИШЕМ КОД СТИЛЬНО

Мы уже разбирались с жестким кодом💪, решили, что такого добра нам не надо🙅‍♂️. Давайте теперь поговорим о том, как правильно ставить скобочки)))

📯Мы живем в сосаети

Над современными продуктами редко трудится только один человек. Даже микростартап с коленки🦵 может внезапно выстрелить🔫 так, что придется собирать целых трех програмистов (космические цифры🚀)! А может, даже и пять...

И, работая, над одним проектом, необходимо сделать код унифицированным🏭 настолько, чтобы кусок, написанный одним разработчиком не отличался от куска, написанного другим💕. В таких условиях, вашим котикам программистам🐈 придется тратить меньше умственных усилий на чтение кода📖. А у них и так мозг бо-бо🧠, бедняжки(


И как же нам поможет этот ваш кодстайл🤔? А он как раз определяет внешний вид написанной программы💅, являя собой набор правил оформления кода📜. Где мы расставляем переносы↩️, как называем классы и их члены👉, даже как раскидывать файлы проекта по папкам📂.

📯Где его взять?

Если компания крупная и душная🪟, вам скинут ссылку на документ в локальной базе знаний🖥, поставят задачу изучить, а потом устроят тестирование по материалу. И все это до первого собеса😂. Короче, расскажут.

А вот в наколеночных🤡 стартапах, дело обстоит иначе. Так как соотношение программисты/задачи там намного хуже🚣, этим всегда некому заниматься🤷‍♀️. И стиль кода определяется либо самым настойчивым программистом😬, либо никак😶.


В первом случае, смотрите в рот и повторяйте👄. Если сложно, то спрашивайте💬, но только по важным поводам❗️. Иногда можно и забить, если выглядит достаточно похоже.

Во втором же... бегите оттуда🏃. Серьезно. Если в компании код пишется абы-как, значит, и все остальное в ней работает абы-как🤬. И даже если Божьей помощью они допинают проект до релиза🚀, что с ним будет дальше? Верно, он превратится в легаси👨‍🦳 с уходом любого разработчика. А учитывая, что команда небольшая, легаси займет значительную часть проекта👁.

📯Ну какая разница, главное же, что работает!

Вся эта статья про поддерживаемость, а зачем она вообще😕?

Да, прямо сейчас работает👍. Но, как и мы сами, наш код не всегда будет молодой и здоровый😣. Тут внешний API отвалится💔, там библиотека устареет👵, тут бизнес-требования изменятся🔄... И каждое из этих действий заставляет нас залезать в, казалось бы, готовый функционал🤪. Все же мы хотим, чтобы это залезание было прогулкой по широкому проспекту с указателями🛣, а не продиранием сквозь азиатские трущобы🙅‍♂️?


Для этого надо построить широкий проспект, а не как попало🧱. Что посеешь, то и пожнешь🤮, получается🧐.
Да и вообще, я частенько повторяю, что программист тратит бóльшую часть времени не на написание кода✍️, а на его чтение📕 – соответственно, уменьшить сложность этого действия будет, безусловно, благом😇.

📯И что, для каждого проекта учить новый кодстайл?

Совсем нет🙅! Общие принципы устоялись довольно давно👴. Во многих IDE даже встроено форматирование, чтобы малыши не уляпывались👶 и сразу смотрели на красивое. Потом, гляньте крупные проекты, в определенный момент поймете, что они во многом одинаковые👯‍♀️.


Это с одной стороны.
С другой, да, кодстайл, бывает, сильно меняется от компании к компании и даже от проекта к проекту🔄. Тут (разумеется, если он адекватный) стоит просто смириться и принять😮‍💨. Не стоит начинать холивары👊 из-за того, что вам просто не нравится, положение скобочки.


P.S. если хотите углубиться сильнее, то вот еще приятный лонгрид.

🪕 – Я против плохого стиля — я денди, мама
Стиль — основа, без стиля, мама, пиздец
А стиль — не обои, мама, хотя и обои тоже
Стиль — это жить на стиле, и весь холодец
🔥 – Хочу, чтобы половина поста сгорела, тогда я осилю прочитать половину от оставшегося...
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4💅111
Первое место, куда я иду в Питере🪆
222💅1
Я сегодня old money🍃🏠🫖
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
6💅5💯21🔥1🤔11
ТВОЙ ПЕРВЫЙ РАЗ #1

По долгу службы мне приходится видеть довольно много первых проектов начинающих разработчиков🧑‍💻, и.. они все неправильные. Не в смысле кода, там понятно, что ошибка на ошибке🪲, и это нормально. А в смысле как ступенька🪜 на пути к становлению настоящим разработчиком🧑‍💻.

Поясняю в следующем порядке:
• Размер имеет значение📍
Важно кончить
Первый раз всегда неловкий
Каждый раз как в первый

📯Размер имеет значение

После того, как мы научились более-менее шкодить, попробовали реализовать две микро-механики😨, мы садимся в горделивую позу, исполнившись уверенности🤓, и думаем: "Вот теперь я готов, сейчас как сделаю свою игру мечты! В ней можно будет грабить корованы🛒, NPC будут через нейронку общаться с персонажем на любые темы💭, а еще будет глобальная система репутации, коллекционные карточки💳, эль и эльфийки в откровенных доспехах👙!"

Ясен хрен, такая игра никогда не выйдет😭. Зато ты потратишь на нее год-два, выгоришь😕, урежешь до того, что она будет похожа на обрубок шаблонной рпг-поделки👨‍🦽, решишь, что программирование – не твое и грустный пойдешь на завод к восьми утра🏭.


Но дело не в том, что тебе не дано🤲, тебя просто никто не научил, что первое и самое главное для создания игры❗️ – это умение оценить ее размер📐. Идеально для первого проекта – 3-6 месяцев. Тогда, с одной стороны, ты узнаешь достаточно🤯, чтобы начинать свой первый настоящий проект, а с другой – не будешь слишком долго торчать на обучении🧠.

📯Почему столько?

По причине отсутствия опыта, твоя игра будет сломана во множестве мест🫠. И, как назло, это будут самые критические места🎯. То есть, те, чтобы исправить которые, нужно переделывать игру полностью🚜. И как раз через 3-6 месяцев их накапливается, в среднем, уже неподъемное количество🏋️.

Это значит, что разработка начинает экспоненциально замедляться🐢, а ты не растешь, потому что не можешь попробовать новую архитектуру🏗. Чем меньше уровень знаний, тем реще рост специалиста📈, это везде так. И, опять же, через примерно такое время ты начнешь ненавидеть себя из прошлого🤬. Так что столкновение с собой только-только начинающим лучше не затягивать👀.


📯Вы не понимаете время

Оценке времени можно научиться, но для этого нашей головной нейросети🧠 нужно скормить кучу размеченных данных👋. А как мы их получим? Правильно, делая кучу неверных предположений🙅‍♂️. И я догадываюсь, что перед началом первого проекта ты не делал других проектов, так что та самая куча у тебя пустая🔍.

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


Я, например, со своим ошибся раз в тридцать, со вторым уже всего в восемь👍. В третьем, надеюсь, будет в два, и это уже уровень профессионалов🤓.

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


📯Окей, где референс?

Для того, чтобы вы могли хотя бы отдаленно сопоставить свой проект с реальностью👍, вот вам небольшой список подходящих по размеру примеров:

• Простая визуальная новелла (не учитывая текст)
• Копия почти любой настолки (морской бой там, монополия)
Простой платформер уровня Марио
Hyper-casual головоломки типа Cut the rope или найди кота

Но помните, это не список игр, которые я вам предлагаю сделать. Я вам ЗАПРЕЩАЮ🩺 делать что-то из этого списка Ну, может быть, кроме платформера🆗, если он оригинальный.
Во-первых, вы ничему не научитесь, повторяя чужие готовые решения📖, а во-вторых, такое нельзя будет ни выложить куда-то, ни в портфолио показать💼.


😭 – мой первый раз был с другом бати, поэтому я и пошел в программисты...
🤡 – хочется стереть себе память и снова сделать свой первый Flappy Bird🤤
Please open Telegram to view this post
VIEW IN TELEGRAM
😭2💅2🤷22👏11
ОДИН КЛАСС, ЧТОБЫ ПРАВИТЬ ВСЕМИ

Пересматривая Властелина Колец💍 на праздниках, решил пояснить🙄, почему Темный Властелин Саурон был бы плохим программистом💻.

📯Твой класс божественный, и это плохо

God object⚡️ – класс, который хранит в себе основной функционал программы.


По определению, думаю, понятно, почему мы должны этого избегать👀. Но для тех, кто не знает, будем пояснять📖.

📯ООП – круто

Вся суть Объектно-Ориентированного Программирования заключается в разделении кода на блоки🌎, отвечающие за разные функции. Это позволяет нам вводить, как минимум, один уровень абстракции в программе🔡. Пренебрегать этим не следует👎.


Когда же мы пишем god object😇, мы лишаемся возможности думать отдельно на низком уровне⌨️ (как пересылаются байтики) и на высоком🧠 (об архитектуре).

Вся наша программа превращается в один большой ком💩 функционального программирования с хаотично😱 разбросанными по нему функциями ВСЕГО👁. Соответственно, чтобы ориентироваться в такой программе, нужно знать всю эту программу и держать всю ее в голове одновременно😨. А такое возможно только в крошечном продукте до 300 строк🐈‍⬛.


📯God object поменьше

Есть еще один вариант god objecta👼, который обычно пишут люди, чуть более сведующие🤓. Однако он тоже очень фу🤢.

Чаще его называют менеджер или контроллер🪪.
Такой класс управляет общим состоянием программы🛂 (бой/пауза/отдых, например), хранит глобальные переменные🌍, запускает различные сценарии работы🎬 и много чего еще.


Тут уже запах ООП присутствует🐽, но есть и много проблем💥.

Во-первых, пресловутая Ось изменений➡️ (воображаемая линия, протыкающая классы💘, которые необходимо затронуть при необходимости что-то обновить или исправить🆕) проходит, через такой менеджер буквально всегда🏪. *тут будет ссылка на статью, почему это плохо*

Да и вообще, перечитайте SRP про это🚽.

Во-вторых, при реализации такого контроллера, мы плотно завязываем🪦 все части нашей программы в одну точку🏹. А что будет, если нам их захочется пошевелить💥? Правильно, придется разбираться со всей архитектурой сразу💥.

В-третьих, пойти на менеджер – прямая дорога🚓 к god object`у. Зло нельзя контейнировать и удержать в коробочке🔒, оно будет расползаться по всему коду😋, пока в конце концов не поглотит его👀.


Ведь, если мы нормально относимся к тому, что есть один глобальный дядя😄, который говорит всем, что делать, то, может и вот эту маленькую штучку можно ему отдать😏..? И вот эту побольше тоже🤔? А раз эту отдали, то вот эту, с ней связанную неизбежно придется тоже😉. Ой, да и хрен с ним, давайте все туда засунем, а😎?

🪕 – Одно Кольцо, чтоб править всеми, Оно главнее всех, Оно соберет всех вместе и заключит во Тьме
🤡 – блин, у меня только один класс (5"Б")
Please open Telegram to view this post
VIEW IN TELEGRAM
43🔥1🤷1
Дорогие товарищи🥰, раз вы сюда подписаны✍️, смею предположить, что вам нравится канал😍, а от админа вы вообще без ума😩! А раз вы работаете/увлекаетесь программированием🎹, то у вас должны быть и друзья-программисты⌨️.
К чему это я🤔? Чтобы я и дальше мог радовать вас полезной информацией😌 в увлекательной подаче🤹, порадуйте и вы меня репостиком➡️.

Отправляйте понравившиеся посты❤️ или ссылку на канал🔗 в рабочий чат, коллегам в Slack'е, бабушке в домовой чат, любимым в лс📇!

А если вы шейх🤠, то можете и закинуть копеечку🤑!
Please open Telegram to view this post
VIEW IN TELEGRAM
💅421