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🎯 , отсутствие использования – это часто отсутствие адекватного ответа, потому что класс его просто не знает😐 . Это не обязательно приведет к проблемам, но это узкое место, которое может привести к проблемам🚨 . Домашнее задание – подумать, почему нельзя наследовать квадрат от прямоугольника (загуглите, если сдаетесь) .
🤡 – щас секундочку, щас я позвоню уточню, она че-то не сказала мне, блин...
Подставила меня опять. Блин, не берет еще и...
🍾 – Подставляйте стаканы, у нас тут разливают базу
🪕 – В моем сердце дырка, мне нужна таблетка💊 🫦
А мы продолжаем разбирать принципы проектирования. В прошлый раз выяснили, что открыть, а что закрыть, а теперь будем решать, как правильно подставлять
Оглавление:
S – Single Responsibility
O – Open-Closed
L – Liskov Substitution
I – Interface Segregation
D – Dependency Inversion
(Bonus) DRY – Don`t repeat yourself
Пропустим матан от Лисков👩🔬, давая определение от любимца публики Боба Мартина
– функции, которые используют базовый тип, должны иметь возможность использовать подтипы базового типа, не зная об этом🤷♀️ .
Ну, вроде, базированная база, но давайте разберем подробнее
Все очень просто. Вот, к примеру, есть у нас класс Enemy
В любое место, куда впихуется базовый класс, должен впихиваться и наследник. Без любых условий🙅♂️ .
И ладно бы Exception, его мы на Unit-тестах отловим
И в заключение вот несколько подсказок, которые помогут распознать в себе нехорошего человека
1. Возникает необходимость
Не надо
2. if (Obj is Subclass)
Это просто
3. Наследник не использует функции базового класса.
В принципе, с этим можно жить
Подставила меня опять. Блин, не берет еще и...
🍾 – Подставляйте стаканы, у нас тут разливают базу
Please open Telegram to view this post
VIEW IN TELEGRAM
Wild Russian GameDev Mentor
ОТЧЕТ ПО НЕЙРОСЕТИ СО СТРИМА #5 Для начала, вкратце напомню, что изменилось за прошлый стрим🆕 : 📯 Добавил новый вид препятствия: летающие ящеры🐥 . Проблем они вообще не доставили. Сетка обучилась за пару поколений по-разному реагировать на разные препятствия🏃♂️ .…
ОТЧЕТ ПО НЕЙРОСЕТИ СО СТРИМА #6
📯 Для начала, вкратце напомню, что изменилось за прошлый стрим🆕
1. Создали новую игру для тестирования возможностей нашей нейросети: Flappy Dino🐔 .
Сделал это для тестирования скорости переноса существующей нейросети на другой проект🚜. Получилось даже лучше, чем я рассчитывал😎 .
2. Попробовал увеличить дистанцию, на которой появляются препятствия🔭 .
Теория была в том, что на максимальной достигнутой скорости (~5200 очков) динозавры🦕 должны прыгнуть раньше, чем объект появляется на экране. Прорыва не произошло🚱. Видимо, одного этого недостаточно😔 .
3. Добавил график сходимости – зависимости результата от времени📈 .
Это ключевой показатель в оценке окружения нейросети🔑 . И чем он ровнее, тем лучше – это значит, что на каждой итерации приспособленность увеличивается📈 . Ну и иногда неровный график может значить, что сама сетка сбоит, но это видно и по другим параметрам (у меня такого нет)👍 .
Пока что грешу на случайность🎲 игры и плохую физику, которая вносит погрешности, но разброс значений какой-то слишком огромный🎯 .
📯 Результаты ночного прогона
Переходим к картинкам. Огромному числу в таймере не удивляйтесь, в этот раз Unity решила не жрать🍬 всю память и позволила мне увеличить скорость в 100 раз💨. Тем не менее, уже после девяти часов сетка в обоих вариантах упирается в потолок. Что указывает на проблемы с игрой: либо там непреодолимое препятствие🌳 , либо слишком узкое горлышко🍾 .
📯 Что будет через неделю
1. Хочется добить идею с простой интеграцией в любое окружение⚙️ .
Думаю, можно сделать какой-нибудь агент, чтобы цеплять⛓ его компонентом к префабу.
2. Будем опять разбираться в том, что же тормозит эволюцию🧬.
Наверное, поковыряемся с механизмом отбора👁 и условиями игры.
3. Попробуем написать игру с кардинально другими условиями.
Наверное, что-то головоломко-образное, чтобы проверить ее интеллектуальные способности🤪 .
А вы все еще пишите свои идеи для новой игры в комментариях⬇️
P.S. Потрогать проект своими руками можно на гите!
1. Создали новую игру для тестирования возможностей нашей нейросети: Flappy Dino
Сделал это для тестирования скорости переноса существующей нейросети на другой проект🚜. Получилось даже лучше, чем я рассчитывал
2. Попробовал увеличить дистанцию, на которой появляются препятствия
Теория была в том, что на максимальной достигнутой скорости (~5200 очков) динозавры
3. Добавил график сходимости – зависимости результата от времени
Это ключевой показатель в оценке окружения нейросети
Пока что грешу на случайность
Переходим к картинкам. Огромному числу в таймере не удивляйтесь, в этот раз Unity решила не жрать
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💅1 1
ПРОЩАНИЕ С ИДЕАЛИЗМОМ или КАК Я ПОЛЮБИЛ ГОВНОКОД
Весь этот канал состоит из статей разного рода, рассказывающих про качественный и красивый код🌹 . И эту информацию нужно держать в голове каждый раз, когда трогаешь клавиатуру⌨️ , но.
📯 Только ситхи все возводят в абсолют.
Если вы читаете мои статьи📖 , то знаете, что некоторые положения т.н. "чистого кода" в абсолютной форме противоречат друг другу, здравому смыслу и даже сами себе🏥 .
И вот мы убили на это свое здоровье👨⚕️ , все бабки заказчика💵 , возможность жить в социуме🌚 ... А все равно какой-нибудь душнила🤓 скажет нам, что наш код говно. И, что самое удивительное, будет прав😎 .
Потому что чистота в глазах смотрящего👁 .
Нельзя сказать, что арочный мост однозначного лучше подвесного🌉. Так и у нас.
Конечно, это не разрешение вам писать монолит🧐 – границы-то знать надо! Отличайте, пожалуйста, выбор архитектурного решения от выбора насрать себе в штаны💩 .
📯 Это просто непрактично
Я вот иногда сплю🥱 , и вижу всегда один и тот же сон☁️ : каждый продукт, который я создаю, имеет бесконечный жизненный цикл♾ , заказчик не закроет его через месяц🍌 , условия рынка не меняются🎉 ... А еще бюджет бесконечный💰 ...... А потом я просыпаюсь и вспоминаю, что
В таких условиях не до белых перчаток🧤 . В таких условиях чистый код – это роскошь💎 , мы можем иметь его ровно столько, сколько необходимо для функционирования проекта, ни граммом больше🤏 .
📯 Чистый код как анкап – не точка назначения, а моральный компас.
А в остальном, вы должны примерно представлять, в какую сторону🧭 вы будете потом рефакторить🖥 . Делать же что-то для этого можно только в том случае, если это не отвлекает вас от настоящей работы – пилить фичи🪚 и фиксить баги🐛.
🪕 – За три сотенных к/наносек на селе возил говяшки, ой-ой-ой
🤡 – Писать говнокод – это милосердие
Весь этот канал состоит из статей разного рода, рассказывающих про качественный и красивый код
Если вы читаете мои статьи
Как ветеран срачей в интернете🫡 и обладатель десятка проектов👍 (выпущенных и нет 🎓 ) , я вам авторитетно заявляю: чистый код недостижим🙅♂️ . Он как скорость света: чем ближе мы находимся, тем сложнее следующее продвижение🏎 .
И вот мы убили на это свое здоровье
Потому что чистота в глазах смотрящего
Программирование, как и архитектура – это искусство👨🎨 , тут можно достичь одного и того же результата кардинально разными способами, у каждого из которых есть свои плюсы и минусы🤨 .
Нельзя сказать, что арочный мост однозначного лучше подвесного🌉. Так и у нас.
Конечно, это не разрешение вам писать монолит
Я вот иногда сплю
На самом деле задача программиста: написать за три копейки😭 то, что будет кое-как работать💻 . Но чтобы можно было масштабировать🙈 , ЕСЛИ тестовый запуск покажет хорошие результаты😉 .
В таких условиях не до белых перчаток
Следовать правилам хорошего кода необходимо процентов на 60-80😉 , в зависимости от ситуации. И только если это необходимо + если это не слишком дорого⏳ (по времени, хотя это то же самое) .
А в остальном, вы должны примерно представлять, в какую сторону
Please open Telegram to view this post
VIEW IN TELEGRAM
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
Или в формулировке Немчинского:
Или, как бы сказал я:
Выбирайте любимчика🥰 .
📯 Интерфейс, клиент.. Статья для фронтендеров, что-ли?
Рассмотрим пример с моим проектом по ИИ🤖 :
Класс самой нейросети довольно огромный🐖 . При том в клиентах – динозаврике🦕 или котике😼 – нужны только три метода: конструктор, мутатор и обработчик. Все остальное используется для дебага🐛, наглядности👀 и вообще красоты✨ .
📯 Так стоп, мультиответственный класс.. А ЧТО ТАМ С SRP?!
Поздравляю, вы нашли первое противоречие в словах всеотцов программирования👁 . Сначала немного пощиплет🩸 , зато можете взять шоколадку на выходе🍫 .
Даже в моем примере можно упаковать📦 класс чистой нейросети в отдельный класс-дебаггер.
Но.. зачем? В общем, на мой взгляд это паттернодрочерство🤓 .
📯 И все-таки, ISP полезный
В моем примере можно сказать, что просто я рукожоп, и надо было вообще все по-другому сделать(напишите это на бумажке и съешьте 👏 ) . Но зачастую ситуация в том, что есть огромные Фасады, код бюрократии или просто 20-летний энтерпрайс, с которым так или иначе придется работать💩 .
Этот принцип помогает изолировать говнокод и, хотя бы, не давать ему расползаться👎 .
🤡 – пост про сегрегацию, ОСУЖДАЮ
🤬 – интерфейсы как туалеты. Клиентно-нейтральных не должно быть.
А мы продолжаем разбирать принципы проектирования. В прошлый раз выяснили, как правильно подставлять
Оглавление:
S – Single Responsibility
O – Open-Closed
L – Liskov Substitution
I – Interface Segregation
D – Dependency Inversion
(Bonus) DRY – Don`t repeat yourself
– Программные сущности не должны зависеть от методов, которые они не используют.
Или в формулировке Немчинского:
– Много интерфейсов, специально предназначенных для клиентов, лучше, чем один общий.
Или, как бы сказал я:
– Интерфейс делается ОТ и ДЛЯ клиента
Выбирайте любимчика
Под клиентом в программировании подразумевается клиентский код👩💻 – тот код👩💻 , который потом будет использовать наш код👩💻 . Это важно не только при написании библиотек📚 , но и для грамотного распределения обязанностей и ролей🎭 .
Рассмотрим пример с моим проектом по ИИ
Класс самой нейросети довольно огромный
А, следуя ISP, я бы мог:
1. Легко заменить класс под интерфейсом на другой🔄 (допустим, украл бы чужую более удачную реализацию🥷) .
2. Не видеть лишних членов класса там, где они не нужны🙈.
3. Снизить количество классов, через которые проходит ось изменений⛓ .
4. Да и вообще отделить мультиответственное чудовище🦍 от нормального SOLID-friendly кода🐱 .
Поздравляю, вы нашли первое противоречие в словах всеотцов программирования
Да, ISP нужен исключительно при нарушении SRP💔 . Что немного нормализует нарушение SRP, не правда ли🤭 ? И действительно, кому в голову придет разделять интерфейсы, если идеальный класс содержит не больше одного метода🤔 ?
Даже в моем примере можно упаковать📦 класс чистой нейросети в отдельный класс-дебаггер.
Но.. зачем? В общем, на мой взгляд это паттернодрочерство
В моем примере можно сказать, что просто я рукожоп, и надо было вообще все по-другому сделать
Говно не исчезнет и не перестанет быть говном, если его (даже очень громко) осуждать в интернете💻 . С говном нужно уметь работать и, по возможности, рефакторить💩 . И ISP говорит, как.
Этот принцип помогает изолировать говнокод и, хотя бы, не давать ему расползаться
🤬 – интерфейсы как туалеты. Клиентно-нейтральных не должно быть.
Please open Telegram to view this post
VIEW IN TELEGRAM
НИКОГДА НЕ ВОЗВРАЩАЙ 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евой пациент – это пациент дурки😂
В нашем любимом Си Хэштег-чике, как и во многих других ООП-языках
Написали метод, который возвращает самого сочного трапика🏳️⚧️ в стране. А потом что-то случилось
Иными словами, null чаще всего отдают🫳 , когда метод не может правильно выполнить свою функцию🤔 .
Null – это диверсант-смертник💣 , который притворяется обычным гражданином. Null – это отсутствие несущего кирпичика🧱. Null – это арматура на дне мутного озера🦑 .
Вам уже страшно? Так и должно быть
В итоге получаем плавающую ошибку🏊♂️ , которая не отслеживается по цепочке вызовов⛓ , и вообще не сразу понятно, кем и чем вызвана🤨 .
Вы скажете, так делай проверку на null
1. Как сказано в названиии, никогда не возвращай null.
Простой совет, не правда ли? Если твой метод не может отработать правильно, кинь Exception
2. Если ты рукожоп и не можешь следовать первому пункту, хотя бы используй Nullable.
Тип Nullable<MyClass> – декоратор
😭 – Заглянул в переменную MyCareer, а там null
🤣 – Ааа, nullевой пациент – это пациент дурки
Please open Telegram to view this post
VIEW IN TELEGRAM
🤣3😭2💅2❤1
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, мы рассуждаем🤔 : "Ага, значит, везде, где всовывается базовый класс👵, должен всовываться дочерний👧. Ну, значит, нужно их привести к одному интерфейсу♊️... К наследнику🤡 (ведь строить проще, чем ломать) !"
📯 А вот и нихренашеньки!
Ведь теперь мы добавили в базовый класс функционал, который все наследники обязаны реализовывать🧠 .
Цель ООП как раз состоит в том, чтобы ввести разные уровни "глобальности" мышления🧠 , потому что человеческий мозг не может одновременно думать о вечном😇 и о насущном🍞 . А когда мы перемешиваем частное с общим, наше ✨ красивое✨ разделение на слои сыпется в момент💔 .
📯 Вывод
DI дополняет LSP, делает следование соседнему принципу осмысленным🧠 . Да и сам по себе он полезный и важный. Любите DI❤️ .
🤔 – Слои абстракции какие-то были упомянуты, а можно поподробнее?
🤣 – Я тоже зависимый(от написания кода)
А мы продолжаем разбирать принципы проектирования. В прошлый раз выяснили, как правильно разделять
Оглавление:
S – Single Responsibility
O – Open-Closed
L – Liskov Substitution
I – Interface Segregation
D – Dependency Inversion
(Bonus) DRY – Don`t repeat yourself
– Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.
Давайте немного откатимся назад, к основам🔙 . Нам вообще зачем нужно наследование🤱? Очевидно, чтобы сделать базовое поведение, от которого мы будем расширяться при необходимости➕ .
Но в какой-то момент нам требуется, чтобы вот этот конкретный наследник делал что-то уникальное
И, помня об LSP, мы рассуждаем
Во-первых, тогда у нас количество нарушений LSP не уменьшится, а скорее всего, даже увеличится😱 .
Ведь теперь мы добавили в базовый класс функционал, который все наследники обязаны реализовывать
Во-вторых, что важнее, при таком подходе(разработка от частного к целому) теряется вся суть абстракции🧐 .
Цель ООП как раз состоит в том, чтобы ввести разные уровни "глобальности" мышления
DI дополняет LSP, делает следование соседнему принципу осмысленным
🤔 – Слои абстракции какие-то были упомянуты, а можно поподробнее?
🤣 – Я тоже зависимый
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔2🤣2 2💅1 1
This media is not supported in your browser
VIEW IN TELEGRAM
Wild Russian GameDev Mentor
Video message
По дороге с пляжа еще и подобрал пачку сухариков🍀 🦋 🦋
Любите природу, мать вашу😡 !!!
Любите природу, мать вашу
Please open Telegram to view this post
VIEW IN TELEGRAM
🤩5🗿3
А ССЫЛОЧКУ МОЖНО? СПАСИБО, БЛЯТЬ...
Давайте немного отойдем от высокопарных метаний умными словами🧘 про архитектуру и всякие абстрактные эфемерности✨ , а поговорим сегодня о таких твердо-измеримых понятиях📐, как reference types и value types.
📯 Кто есть кто
К ним относятся:
• Integers (в т.ч. byte, long и т.п.)
• Floats (аналогично, double, decimal и пр.)
• bool
• char
• enums
• structs (это как классы, только value type)
• value tuples (это как Tuple, только value type)
• string
К ним относятся:
• class (и другие варианты его объявления, типа, record, interface).
• dynamic
• object
• string
📯 Ну и в чем разница?
Заметили? Получается, для ссылочных типов объект по ссылке один и тот же☝️ .
В результате, когда мы пишем
, в a останется 10, так как мы скопировали 10.
А вот когда мы пишем
, в оригинальный names будет добавлен "Albert", потому что список-то один и тот же!
📯 А что там со стрингами👙 ?
Кстати, помните пост про null? Так вот, его мы можем положить только в reference types, потому что он, в сущности – пустая ссылка0️⃣ . А в string можно положить null. Что и требовалось доказать🤓 .
📯 Модификаторы параметров
Если вы думали, что у нас есть два вида типов, и мы не можем использовать преимущества одного для другого, то вы ошибались❌ . Помогут нам следующие заклинания🪄 :
Эти модификаторы пишутся при объявлении метода, а также при его вызове📞 :
Боевой👊 пример можно посмотреть в Physics.Raycast в Unity📱 (там используется out).
📯 А еще есть object
Он reference type и является родительским классом для вообще всех классов в C#👵 . Да, даже для тех, которые value types😧 . Нужен он для предоставления базовых интерфейсов, таких как Equals, ToString и др.💻
А еще с value types можно делать прикольный boxing-unboxing🥊 . Пожалуйста, никогда его не делайте, он генерирует путаницу и не дает никаких выгод 🌟 .
❤️ – Хочу еще таких постов про механизмы конкретно C#
🤡 – Я не разговариваю на вашем языке C#, давай что-то про 1С
Давайте немного отойдем от высокопарных метаний умными словами
Value types (Типы значений) – те, переменные которых содержат непосредственно данные📦.
К ним относятся:
• Integers (в т.ч. byte, long и т.п.)
• Floats (аналогично, double, decimal и пр.)
• bool
• char
• enums
• structs (это как классы, только value type)
• value tuples (это как Tuple, только value type)
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, потому что он, в сущности – пустая ссылка
Если вы думали, что у нас есть два вида типов, и мы не можем использовать преимущества одного для другого, то вы ошибались
• 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
Боевой
Он reference type и является родительским классом для вообще всех классов в C#
А еще с value types можно делать прикольный boxing-unboxing
❤️ – Хочу еще таких постов про механизмы конкретно C#
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7💅3 2 1
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
Но как тогда сделать похожий, но немного другой функционал🤔 ?
📯 Наследование (LSP и DI)
Ну, это если по самому очевидному пройтись🤓 . А если отойти от параллелей с другими принципами и посмотреть внимательно на DRY, там главная идея💡
А при вынесении предкас ноги мы внимательно смотрим в DI, который нам помогает не ошибиться😑 , особенно, когда мы строим иерархию наследования снизу вверх🙃 .
В общем, идея почти во всем хорошая, и с ней даже сложно переусердствовать💻 . Но, теоретически, возможно, так что вы все равно там поосторожней🖥 .
📯 Подводя итог
А вот если волк молчит, потому что он спросил и ждет ответа⏳ ? Или если волк умер от кринжа💀 ? То есть, о применимости такого принципа повсеместно. Также как и куча вопросов о совместимости🧐 отдельно взятого принципа с другими умными словами легендарных дядек🤓 .
🤡 – фух, наконец-то месяц Clean Code`а закончился, можно снова писать монолит😁
🪕 – Я уже говорил тебе, что такое безумие?
А мы продолжаем разбирать принципы проектирования. В прошлый раз решили, кто тут от чего зависимый
Да, DRY не входит в SOLID, но давайте его бонусом разберем
Оглавление:
S – Single Responsibility
O – Open-Closed
L – Liskov Substitution
I – Interface Segregation
D – Dependency Inversion
(Bonus) DRY – Don`t repeat yourself
– Каждая часть знания должна иметь единственное, непротиворечивое и авторитетное представление в рамках системы.
В этом коротком определении совмещаются SRP, LSP и DI.
Помните Single Responsibility Principle? О том, что одна ответственность = один класс. Так вот и здесь что-то похожее, но с другой стороны: если у нас ответственность уже реализована, мы не имеем права ее повторять где-то еще👯♀️. = один фю
Но как тогда сделать похожий, но немного другой функционал
Тут мы подходим к ООП🤱 . Код должен быть непротиворечивым: если B -> A, то B делает все то, что и A. Ничего не напоминает?
Ну, это если по самому очевидному пройтись
– ни в коем случае не повторять то, что уже написано👎 . Если все же нужно сделать что-то похожее, но другое, то надо добавить над ними общего предка👵, и все общее вынести в него☝️ .
А при вынесении предка
В общем, идея почти во всем хорошая, и с ней даже сложно переусердствовать
Самое главное🚨 , что я хотел, чтобы вы поняли после прочтения цикла СОЛИДНОЕ ПРОГРАММИРОВАНИЕ – это то, что все эти паттерны суть – волчьи цитаты🐺 уровня "Если волк молчит, то его лучше не перебивать". Вроде бы, ух, сука, сос мыслом👺 , но, если задуматься, то возникает куча вопросов🐺 .
А вот если волк молчит, потому что он спросил и ждет ответа
Please open Telegram to view this post
VIEW IN TELEGRAM
Вы у меня часто спрашиваете❓ , какая погода на море "Привет, можно с вами🥺 ?" И теперь у нас наконец-то будет ответ, который вас удовлетворит: ДА, МОЖНО😦 !
Ведь мы c @BO3bMAK открываем СЕРВЕР ПО МАЙНКРАФТУ🌎 !!!
Survival + 1.21.5 + BlazeandCave's.
📱 Как зайти 📱
А как я сам играю
📱 смотрим тут 📱 .
Ведь мы c @BO3bMAK открываем СЕРВЕР ПО МАЙНКРАФТУ
Survival + 1.21.5 + BlazeandCave's.
А как я сам играю
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5🎉2 2💅1
ПИШЕМ КОД СТИЛЬНО
Мы уже разбирались с жестким кодом💪, решили, что такого добра нам не надо🙅♂️ . Давайте теперь поговорим о том, как правильно ставить скобочки)))
📯 Мы живем в сосаети
Над современными продуктами редко трудится только один человек. Даже микростартап с коленки🦵 может внезапно выстрелить🔫 так, что придется собирать целых трех програмистов (космические цифры🚀 )! А может, даже и пять...
И как же нам поможет этот ваш кодстайл🤔 ? А он как раз определяет внешний вид написанной программы💅 , являя собой набор правил оформления кода📜. Где мы расставляем переносы↩️, как называем классы и их члены👉 , даже как раскидывать файлы проекта по папкам📂.
📯 Где его взять?
Если компания крупнаяи душная🪟, вам скинут ссылку на документ в локальной базе знаний🖥 , поставят задачу изучить, а потом устроят тестирование по материалу. И все это до первого собеса 😂 . Короче, расскажут.
В первом случае, смотрите в рот и повторяйте👄. Если сложно, то спрашивайте💬 , но только по важным поводам❗️ . Иногда можно и забить, если выглядит достаточно похоже.
Во втором же...бегите оттуда 🏃 . Серьезно. Если в компании код пишется абы-как, значит, и все остальное в ней работает абы-как🤬 . И даже если Божьей помощью✝ они допинают проект до релиза🚀 , что с ним будет дальше? Верно, он превратится в легаси👨🦳 с уходом любого разработчика. А учитывая, что команда небольшая, легаси займет значительную часть проекта👁 .
📯 Ну какая разница, главное же, что работает!
Вся эта статья про поддерживаемость, а зачем она вообще😕 ?
Для этого надо построить широкий проспект, а не как попало🧱 . Что посеешь, то и пожнешь🤮 , получается🧐 .
Да и вообще, я частенько повторяю, что программист тратит бóльшую часть времени не на написание кода✍️ , а на его чтение📕 – соответственно, уменьшить сложность этого действия будет, безусловно, благом😇 .
📯 И что, для каждого проекта учить новый кодстайл?
Это с одной стороны.
С другой, да, кодстайл, бывает, сильно меняется от компании к компании и даже от проекта к проекту🔄 . Тут (разумеется, если он адекватный) стоит просто смириться и принять😮💨 . Не стоит начинать холивары👊 из-за того, что вам просто не нравится, положение скобочки.
P.S. если хотите углубиться сильнее, то вот еще приятный лонгрид.
🪕 – Я против плохого стиля — я денди, мама
Стиль — основа, без стиля, мама, пиздец
А стиль — не обои, мама, хотя и обои тоже
Стиль — это жить на стиле, и весь холодец
🔥 – Хочу, чтобы половина поста сгорела, тогда я осилю прочитать половину от оставшегося...
Мы уже разбирались с жестким кодом💪, решили, что такого добра нам не надо
Над современными продуктами редко трудится только один человек. Даже микростартап с коленки🦵 может внезапно выстрелить
И, работая, над одним проектом, необходимо сделать код унифицированным🏭 настолько, чтобы кусок, написанный одним разработчиком не отличался от куска, написанного другим💕 . В таких условиях, вашимкотикампрограммистам🐈 придется тратить меньше умственных усилий на чтение кода📖 .А у них и так мозг бо-бо 🧠 , бедняжки(
И как же нам поможет этот ваш кодстайл
Если компания крупная
А вот в наколеночных🤡 стартапах, дело обстоит иначе. Так как соотношение программисты/задачи там намного хуже🚣 , этим всегда некому заниматься🤷♀️ . И стиль кода определяется либо самым настойчивым программистом😬 , либо никак😶 .
В первом случае, смотрите в рот и повторяйте👄. Если сложно, то спрашивайте
Во втором же...
Вся эта статья про поддерживаемость, а зачем она вообще
Да, прямо сейчас работает👍 . Но, как и мы сами, наш код не всегда будет молодой и здоровый😣 . Тут внешний API отвалится💔 , там библиотека устареет👵 , тут бизнес-требования изменятся🔄 ... И каждое из этих действий заставляет нас залезать в, казалось бы, готовый функционал🤪 . Все же мы хотим, чтобы это залезание было прогулкой по широкому проспекту с указателями🛣, а не продиранием сквозь азиатские трущобы🙅♂️ ?
Для этого надо построить широкий проспект, а не как попало
Да и вообще, я частенько повторяю, что программист тратит бóльшую часть времени не на написание кода
Совсем нет🙅! Общие принципы устоялись довольно давно👴. Во многих IDE даже встроено форматирование, чтобы малыши не уляпывались👶 и сразу смотрели на красивое✨ . Потом, гляньте крупные проекты, в определенный момент поймете, что они во многом одинаковые👯♀️.
Это с одной стороны.
С другой, да, кодстайл, бывает, сильно меняется от компании к компании и даже от проекта к проекту
P.S. если хотите углубиться сильнее, то вот еще приятный лонгрид.
Стиль — основа, без стиля, мама, пиздец
А стиль — не обои, мама, хотя и обои тоже
Стиль — это жить на стиле, и весь холодец
🔥 – Хочу, чтобы половина поста сгорела, тогда я осилю прочитать половину от оставшегося...
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4💅1 1 1
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
ТВОЙ ПЕРВЫЙ РАЗ #1
По долгу службы мне приходится видеть довольно много первых проектов начинающих разработчиков🧑💻 , и.. они все неправильные . Не в смысле кода, там понятно, что ошибка на ошибке🪲, и это нормально. А в смысле как ступенька🪜 на пути к становлению настоящим разработчиком🧑💻 .
Поясняю в следующем порядке:
• Размер имеет значение📍
• Важно кончить
• Первый раз всегда неловкий
• Каждый раз как в первый
📯 Размер имеет значение
После того, как мы научились более-менее шкодить, попробовали реализовать две микро-механики😨 , мы садимся в горделивую позу, исполнившись уверенности🤓 , и думаем: "Вот теперь я готов, сейчас как сделаю свою игру мечты! В ней можно будет грабить корованы🛒, NPC будут через нейронку общаться с персонажем на любые темы💭 , а еще будет глобальная система репутации➕ , коллекционные карточки💳 , эль и эльфийки в откровенных доспехах👙 !"
Но дело не в том, что тебе не дано🤲 , тебя просто никто не научил, что первое и самое главное для создания игры❗️ – это умение оценить ее размер📐. Идеально для первого проекта – 3-6 месяцев. Тогда, с одной стороны, ты узнаешь достаточно🤯 , чтобы начинать свой первый настоящий проект, а с другой – не будешь слишком долго торчать на обучении🧠 .
📯 Почему столько?
По причине отсутствия опыта, твоя игра будет сломана во множестве мест🫠 . И, как назло, это будут самые критические места🎯 . То есть, те, чтобы исправить которые, нужно переделывать игру полностью🚜. И как раз через 3-6 месяцев их накапливается, в среднем, уже неподъемное количество🏋️.
📯 Вы не понимаете время
Оценке времени можно научиться, но для этого нашей головной нейросети🧠 нужно скормить кучу размеченных данных👋 . А как мы их получим? Правильно, делая кучу неверных предположений🙅♂️ . И я догадываюсь, что перед началом первого проекта ты не делал других проектов, так что та самая куча у тебя пустая🔍 .
Я, например, со своим ошибся раз в тридцать, со вторым уже всего в восемь👍 . В третьем, надеюсь, будет в два, и это уже уровень профессионалов🤓 .
📯 Окей, где референс?
Для того, чтобы вы могли хотя бы отдаленно сопоставить свой проект с реальностью👍 , вот вам небольшой список подходящих по размеру примеров✅ :
• Простая визуальная новелла (не учитывая текст)
• Копия почти любой настолки (морской бой там, монополия)
• Простой платформер уровня Марио
• Hyper-casual головоломки типа Cut the rope или найди кота
😭 – мой первый раз был с другом бати, поэтому я и пошел в программисты...
🤡 – хочется стереть себе память и снова сделать свой первый Flappy Bird🤤
По долгу службы мне приходится видеть довольно много первых проектов начинающих разработчиков
Поясняю в следующем порядке:
• Размер имеет значение
• Важно кончить
• Первый раз всегда неловкий
• Каждый раз как в первый
После того, как мы научились более-менее шкодить, попробовали реализовать две микро-механики
Ясен хрен, такая игра никогда не выйдет😭 . Зато ты потратишь на нее год-два, выгоришь😕 , урежешь до того, что она будет похожа на обрубок шаблонной рпг-поделки👨🦽, решишь, что программирование – не твое и грустный пойдешь на завод к восьми утра🏭.
Но дело не в том, что тебе не дано
По причине отсутствия опыта, твоя игра будет сломана во множестве мест
Это значит, что разработка начинает экспоненциально замедляться🐢 , а ты не растешь, потому что не можешь попробовать новую архитектуру🏗. Чем меньше уровень знаний, тем реще рост специалиста📈 , это везде так. И, опять же, через примерно такое время ты начнешь ненавидеть себя из прошлого🤬 . Так что столкновение с собой только-только начинающим лучше не затягивать👀 .
Оценке времени можно научиться, но для этого нашей головной нейросети
Я это пишу не чтобы сказать, что ты лох, а я уже смешарик, но чтобы донести простую мысль👁 : ты даже понятия не имеешь, сколько займет твой первый проект🤨 . Просто прими как факт и отталкивайся в планах от этого✍️ .
Я, например, со своим ошибся раз в тридцать, со вторым уже всего в восемь
Для примера попробуй провести следственный эксперимент🤔 : выбери какую-нибудь фичу среднего размера, которая, ты думаешь, займет у тебя день и выясни, за сколько ты ее допинаешь⏳ . Результат, как говорится, на лице💦.
Для того, чтобы вы могли хотя бы отдаленно сопоставить свой проект с реальностью
• Простая визуальная новелла (не учитывая текст)
• Копия почти любой настолки (морской бой там, монополия)
• Простой платформер уровня Марио
• Hyper-casual головоломки типа Cut the rope или найди кота
Но помните, это не список игр, которые я вам предлагаю сделать. Я вам ЗАПРЕЩАЮ🩺 делать что-то из этого списка Ну, может быть, кроме платформера🆗 , если он оригинальный.
Во-первых, вы ничему не научитесь, повторяя чужие готовые решения📖 , а во-вторых, такое нельзя будет ни выложить куда-то, ни в портфолио показать💼 .
😭 – мой первый раз был с другом бати, поэтому я и пошел в программисты...
Please open Telegram to view this post
VIEW IN TELEGRAM
😭2💅2🤷2 2👏1 1
ОДИН КЛАСС, ЧТОБЫ ПРАВИТЬ ВСЕМИ
Пересматривая Властелина Колец💍 на праздниках, решил пояснить🙄 , почему Темный Властелин Саурон был бы плохим программистом💻 .
📯 Твой класс божественный, и это плохо
По определению, думаю, понятно, почему мы должны этого избегать👀 . Но для тех, кто не знает, будем пояснять📖 .
📯 ООП – круто
Когда же мы пишем god object😇 , мы лишаемся возможности думать отдельно на низком уровне⌨️ (как пересылаются байтики) и на высоком🧠 (об архитектуре).
📯 God object поменьше
Есть еще один вариант god objecta👼 , который обычно пишут люди, чуть более сведующие🤓 . Однако он тоже очень фу🤢 .
Тут уже запах ООП присутствует🐽 , но есть и много проблем💥 .
Во-первых, пресловутая Ось изменений➡️ (воображаемая линия, протыкающая классы 💘 , которые необходимо затронуть ✋ при необходимости что-то обновить или исправить 🆕 ) проходит, через такой менеджер буквально всегда🏪 . *тут будет ссылка на статью, почему это плохо*
Да и вообще, перечитайте SRP про это🚽 .
Во-вторых, при реализации такого контроллера, мы плотно завязываем🪦 все части нашей программы в одну точку🏹 . А что будет, если нам их захочется пошевелить💥 ? Правильно, придется разбираться со всей архитектурой сразу💥 .
Ведь, если мы нормально относимся✅ к тому, что есть один глобальный дядя😄 , который говорит всем, что делать, то, может и вот эту маленькую штучку можно ему отдать😏 ..? И вот эту побольше тоже🤔 ? А раз эту отдали, то вот эту, с ней связанную неизбежно придется тоже😉 . Ой, да и хрен с ним, давайте все туда засунем, а😎 ?
🪕 – Одно Кольцо, чтоб править всеми, Оно главнее всех, Оно соберет всех вместе и заключит во Тьме
🤡 – блин, у меня только один класс (5"Б")
Пересматривая Властелина Колец
God object⚡️ – класс, который хранит в себе основной функционал программы.
По определению, думаю, понятно, почему мы должны этого избегать
Вся суть Объектно-Ориентированного Программирования заключается в разделении кода на блоки🌎 , отвечающие за разные функции✨ . Это позволяет нам вводить, как минимум, один уровень абстракции в программе🔡 . Пренебрегать этим не следует👎 .
Когда же мы пишем god object
Вся наша программа превращается в один большой ком💩 функционального программирования с хаотично😱 разбросанными по нему функциями ВСЕГО👁 . Соответственно, чтобы ориентироваться в такой программе, нужно знать всю эту программу и держать всю ее в голове одновременно😨 . А такое возможно только в крошечном продукте до 300 строк🐈⬛ .
Есть еще один вариант god objecta
Чаще его называют менеджер или контроллер🪪 .
Такой класс управляет общим состоянием программы🛂 (бой/пауза/отдых, например ), хранит глобальные переменные🌍 , запускает различные сценарии работы🎬 и много чего еще.
Тут уже запах ООП присутствует
Во-первых, пресловутая Ось изменений
Да и вообще, перечитайте SRP про это
Во-вторых, при реализации такого контроллера, мы плотно завязываем
В-третьих, пойти на менеджер – прямая дорога🚓 к god object`у. Зло нельзя контейнировать и удержать в коробочке🔒 , оно будет расползаться по всему коду😋 , пока в конце концов не поглотит его👀 .
Ведь, если мы нормально относимся
Please open Telegram to view this post
VIEW IN TELEGRAM
Дорогие товарищи🥰 , раз вы сюда подписаны✍️ , смею предположить, что вам нравится канал😍 , а от админа вы вообще без ума 😩 ! А раз вы работаете/увлекаетесь программированием🎹 , то у вас должны быть и друзья-программисты⌨️ .
К чему это я🤔 ? Чтобы я и дальше мог радовать вас полезной информацией😌 в увлекательной подаче🤹 , порадуйте и вы меня репостиком➡️ .
Отправляйте понравившиеся посты❤️ или ссылку на канал🔗 в рабочий чат, коллегам в Slack'е, бабушке в домовой чат, любимым в лс📇 !
А если вы шейх🤠 , то можете и закинуть копеечку🤑 !
К чему это я
Отправляйте понравившиеся посты
А если вы шейх
Please open Telegram to view this post
VIEW IN TELEGRAM
💅4 2❤1