В этом выпуске мы поговорили с Владимиром Алиповым — нейробиологом и популяризатором науки, о том, действительно ли «математический склад ума» врождён, как работают IQ-тесты и почему поменять профессию в 40 лет — реальный шанс, а не приговор. Обсудили роль интереса против генетики, разобрали мифы о способностях программистов и поделились приёмами сохранения «свежего» мозга.
А так же:
- Как «g-фактор» помогает в любой умной работе, а не только в высшей математике.
- Почему интерес к алгоритмам важнее любви к формулам, если мечтаете о коде.
- Что общего у хоккеистов и айтишников, и при чём тут месяц рождения.
- Как правильно читать результаты IQ-тестов, чтобы не сломать мотивацию.
- Какие привычки сохраняют мозг острым после сорока и кто такие супер-эйджеры.
https://youtube.com/watch?v=_tj5way-6hQ
Альтернативные ссылки: Аудио | vk
А так же:
- Как «g-фактор» помогает в любой умной работе, а не только в высшей математике.
- Почему интерес к алгоритмам важнее любви к формулам, если мечтаете о коде.
- Что общего у хоккеистов и айтишников, и при чём тут месяц рождения.
- Как правильно читать результаты IQ-тестов, чтобы не сломать мотивацию.
- Какие привычки сохраняют мозг острым после сорока и кто такие супер-эйджеры.
https://youtube.com/watch?v=_tj5way-6hQ
Альтернативные ссылки: Аудио | vk
YouTube
IQ, генетика и среда: что формирует интеллект разработчика | Владимир Алипов #53
В этом выпуске мы поговорили с Владимиром Алиповым — нейробиологом и популяризатором науки, о том, действительно ли «математический склад ума» врождён, как работают IQ-тесты и почему поменять профессию в 40 лет — реальный шанс, а не приговор. Обсудили роль…
4👍56🔥17❤6🤮5🤔3👎2🤯1👀1
Инкапсуляция не работает
Это свойство считается невероятно важным в ООП языках, где она прописана как один из ключевых элементов. Делая наши поля приватными, мы таким образом даем доступ только через публичный интерфейс, который следит за соблюдением инвариантов. Так?
Только если в теории. На практике поменять почти все что угодно не составляет никакого труда. Предположим что у нас есть пользователь и у него должна быть установлена хотя бы одна роль и это проверяется где-то внутри пользователя (тут не показано) при изменении списка ролей.
Но нам никто не машет сделать так:
Даже если геттеров нет, рефлексия пробивает любую «защиту»:
Мое мнение о механизме private/protected/public со временем сильно поменялось, когда я пописал на языках где этого нет, но есть ООП. По большому счету этот механизм является в первую очередь защитой от дурака и он вообще не влияет на архитектуру. Если взять любой проект и поменять там все на public, то проект продолжит работать как ни в чем не бывало (если конечно код не завязан на рефлексию с этими).
Это не значит что инварианты соблюдать не надо и не нужно иметь публичный интерфейс для работы с нашими объектами (иначе как обновлять код и либы?). Речь скорее про другое, это не панацея и уж точно не механизм, который влияет хоть как-то на архитектуру. Обозначать публичный и внутренний интерфейс можно и другими способами, а данные внутри объектов часто делают закрытыми в принципе без возможности обращаться к ним без методов или рефлексии (например в ruby).
p.s. Какие еще способы вы знаете как обойти private?
Это свойство считается невероятно важным в ООП языках, где она прописана как один из ключевых элементов. Делая наши поля приватными, мы таким образом даем доступ только через публичный интерфейс, который следит за соблюдением инвариантов. Так?
Только если в теории. На практике поменять почти все что угодно не составляет никакого труда. Предположим что у нас есть пользователь и у него должна быть установлена хотя бы одна роль и это проверяется где-то внутри пользователя (тут не показано) при изменении списка ролей.
class User {
private final List<Role> roles = new ArrayList<>();
public List<Role> getRoles() {
return roles;
}
}
Но нам никто не машет сделать так:
user.getRoles().clear(); // теперь ролей нет
// Можно добавить дубль
user.getRoles().add(new Role("admin"));
user.getRoles().add(new Role("admin"));
Даже если геттеров нет, рефлексия пробивает любую «защиту»:
var field = User.class.getDeclaredField("roles");
field.setAccessible(true);
@SuppressWarnings("unchecked")
var roles = (List<Role>) field.get(user);
roles.clear();
Мое мнение о механизме private/protected/public со временем сильно поменялось, когда я пописал на языках где этого нет, но есть ООП. По большому счету этот механизм является в первую очередь защитой от дурака и он вообще не влияет на архитектуру. Если взять любой проект и поменять там все на public, то проект продолжит работать как ни в чем не бывало (если конечно код не завязан на рефлексию с этими).
Это не значит что инварианты соблюдать не надо и не нужно иметь публичный интерфейс для работы с нашими объектами (иначе как обновлять код и либы?). Речь скорее про другое, это не панацея и уж точно не механизм, который влияет хоть как-то на архитектуру. Обозначать публичный и внутренний интерфейс можно и другими способами, а данные внутри объектов часто делают закрытыми в принципе без возможности обращаться к ним без методов или рефлексии (например в ruby).
p.s. Какие еще способы вы знаете как обойти private?
👍54👎39❤9🤔3🤡2🤝2🔥1👀1
Программисты не верят в инструкции
За последний месяц я провел на собесе лайвкодинг порядка 15 человек и у меня остались смешанные чувства по тому как происходит сетап проекта с нуля. Практически все ребята, либо не следуют инструкции , либо следуют выборочно, по пути выполняя какие-то ручные действия, на базе своих представлений "как правильно", а не как надо в этом проекте. В итоге теряют время и впадают в цикл отладки из-за своих рукопашных действий.
Напоминание: мой собес это берем продакшен проект (опенсорсный), в котором классические rails. Человек его разворачивает на свой машине и делает несколько простых фиксов. Только вот до фич доходят единицы, в основном мы зависаем на сетапе. И вот почему. Ниже пара примеров.
Клонируют проект, видят, что есть .env.что-тотам и ручками создают пустой .env с комментарием "точно должен быть". И когда они доходят до команды, которая сама все правильно делает (в инструкции), то эта команда пропускает уже созданный .env файл (это осознанная идемпотентность для разворачивания), который в итоге пустой, а не наполнен базовыми ключами. Дальше естественно проект не работает и человек какое-то время не вдупляет, а когда вдуплил, начинает ручками эти переменные вставлять ориентируясь на ошибки вывода.
В другом случае человек увидел Dockerfile и даже не заглянув в README.md проекта начал его собирать. А в этом проекте запуск в деве идет не через него. Кстати, проект так и не запустился.
Еще один пример, это когда видят что в описании указан веб-сервер Caddy, сразу начинают его ставить (хотя команды сетапа сами это делают) и запускать. В итоге при старте проекта, Caddy проекта пишет что порт уже занят, потому что его стартанули отдельно от проекта. Потом десятки минут тратится на то, чтобы понять что не так.
Ну и последний пример. Видят домен .localhost и все равно идут добавлять его в hosts, хотя в инструкции нет такой установки (потому что и так работает)
И знаете что самое интересное? В большинстве случаев, ребята начинают менять что-то в файлах самого проекта, хотя для меня это нонсенс. Проект, сетап которого требует в рукопашную менять внутренние файлы (при этом оно нигде не описано)? Чот я давно с таким не встречался.
Без проблем все проходило только у тех, кто просто выполнял команды по очереди как они даны в README.md.
И вот какой вывод напрашивается. Разработчики как-будто настолько редко или никогда в своей жизни не работали с проектами, где не надо ничего делать ручками для разворачивания, что у них не йокает, когда они начинают править какие-то вещи в проекте для сетапа. В итоге чем прошаренее разработчик и менее доверяющий инструкциям, тем больше проблем он создает сам себе.
Ссылки: Телеграм | Youtube | VK
За последний месяц я провел на собесе лайвкодинг порядка 15 человек и у меня остались смешанные чувства по тому как происходит сетап проекта с нуля. Практически все ребята, либо не следуют инструкции , либо следуют выборочно, по пути выполняя какие-то ручные действия, на базе своих представлений "как правильно", а не как надо в этом проекте. В итоге теряют время и впадают в цикл отладки из-за своих рукопашных действий.
Напоминание: мой собес это берем продакшен проект (опенсорсный), в котором классические rails. Человек его разворачивает на свой машине и делает несколько простых фиксов. Только вот до фич доходят единицы, в основном мы зависаем на сетапе. И вот почему. Ниже пара примеров.
Клонируют проект, видят, что есть .env.что-тотам и ручками создают пустой .env с комментарием "точно должен быть". И когда они доходят до команды, которая сама все правильно делает (в инструкции), то эта команда пропускает уже созданный .env файл (это осознанная идемпотентность для разворачивания), который в итоге пустой, а не наполнен базовыми ключами. Дальше естественно проект не работает и человек какое-то время не вдупляет, а когда вдуплил, начинает ручками эти переменные вставлять ориентируясь на ошибки вывода.
В другом случае человек увидел Dockerfile и даже не заглянув в README.md проекта начал его собирать. А в этом проекте запуск в деве идет не через него. Кстати, проект так и не запустился.
Еще один пример, это когда видят что в описании указан веб-сервер Caddy, сразу начинают его ставить (хотя команды сетапа сами это делают) и запускать. В итоге при старте проекта, Caddy проекта пишет что порт уже занят, потому что его стартанули отдельно от проекта. Потом десятки минут тратится на то, чтобы понять что не так.
Ну и последний пример. Видят домен .localhost и все равно идут добавлять его в hosts, хотя в инструкции нет такой установки (потому что и так работает)
И знаете что самое интересное? В большинстве случаев, ребята начинают менять что-то в файлах самого проекта, хотя для меня это нонсенс. Проект, сетап которого требует в рукопашную менять внутренние файлы (при этом оно нигде не описано)? Чот я давно с таким не встречался.
Без проблем все проходило только у тех, кто просто выполнял команды по очереди как они даны в README.md.
И вот какой вывод напрашивается. Разработчики как-будто настолько редко или никогда в своей жизни не работали с проектами, где не надо ничего делать ручками для разворачивания, что у них не йокает, когда они начинают править какие-то вещи в проекте для сетапа. В итоге чем прошаренее разработчик и менее доверяющий инструкциям, тем больше проблем он создает сам себе.
Ссылки: Телеграм | Youtube | VK
Telegram
Организованное программирование | Кирилл Мокевнин
Как из джуниора дойти до мидла, а потом и до синьора
Ютуб https://youtube.com/@mokevnin
Связь для предложений: @kirillpublic
Ютуб https://youtube.com/@mokevnin
Связь для предложений: @kirillpublic
👍83❤33🤔22😁9🤣8🔥5🤯4😢3💯3👀1
Одна мысль - один абзац
Как многие знают, я уже довольно давно и много пишу, в основном статьи и курсы (и даже небольшую книжку сделал). Это очень много контента, через который прошла толпа людей, а я получил от нее звиздулей на тему того что такое хорошо и плохо.
Иногда меня подмывает поделиться чем-то таким. Было даже дело, я вел курс школа авторов по тому, как создавать обучающие материалы технической направленности. Хотя говорят что он полезен всем кто этим интересуется. Вот тут есть ссылка: https://making.hexlet.io/
Попробую понемногу эту тему развивать. Буду рассказывать и про обучение как таковое так и про принципы организации учебных материалов и их написания. Начну с простой штуки, которая описана в "пиши и сокращай", но она настолько часто встречается, что нельзя молчать. Посмотрите на текст ниже:
> Срезы — основной способ работы с коллекциями в Go. Чтобы обрабатывать такие структуры, чаще всего используются циклы. Go предлагает два подхода: классический цикл с индексом и удобный
Это классический пример того как пишут тексты люди и chatgpt, который у них учился. Вроде сходу выглядит нормально, но вообще он не очень, потому, что в рамках одного абзаца, он упаковывает слишком много мыслей, которые заставляют мозг спотыкаться из-за слишком быстрого переключения от одной темы к другой. Хороший абзац раскрывает ровно одну мысль, которая закладывается в первых словах абзаца и развивается к концу.
Правда определить где одна мысль, а где несколько не всегда очевидно без опыта. У меня были ситуации, когда на созвонах это нужно было прямо проговаривать, потому что с точки зрения автора казалось что мы тут говорим об одном, но после объяснения он понимал и переписывал.
В качестве эксперимента, я не буду переработанный вариант, хочу проработать это с вами. Скидывайте в комментах ваши примеры, а тот который победит по количеству лайков, я приведу как пример в одном из следующих постов.
p.s. Ребят, если вам интересно про все это, поставьте лайк, если нет - дизлайк
Ссылки: Телеграм | Youtube | VK
Как многие знают, я уже довольно давно и много пишу, в основном статьи и курсы (и даже небольшую книжку сделал). Это очень много контента, через который прошла толпа людей, а я получил от нее звиздулей на тему того что такое хорошо и плохо.
Иногда меня подмывает поделиться чем-то таким. Было даже дело, я вел курс школа авторов по тому, как создавать обучающие материалы технической направленности. Хотя говорят что он полезен всем кто этим интересуется. Вот тут есть ссылка: https://making.hexlet.io/
Попробую понемногу эту тему развивать. Буду рассказывать и про обучение как таковое так и про принципы организации учебных материалов и их написания. Начну с простой штуки, которая описана в "пиши и сокращай", но она настолько часто встречается, что нельзя молчать. Посмотрите на текст ниже:
> Срезы — основной способ работы с коллекциями в Go. Чтобы обрабатывать такие структуры, чаще всего используются циклы. Go предлагает два подхода: классический цикл с индексом и удобный
range
, каждый из которых подходит под разные задачи.Это классический пример того как пишут тексты люди и chatgpt, который у них учился. Вроде сходу выглядит нормально, но вообще он не очень, потому, что в рамках одного абзаца, он упаковывает слишком много мыслей, которые заставляют мозг спотыкаться из-за слишком быстрого переключения от одной темы к другой. Хороший абзац раскрывает ровно одну мысль, которая закладывается в первых словах абзаца и развивается к концу.
Правда определить где одна мысль, а где несколько не всегда очевидно без опыта. У меня были ситуации, когда на созвонах это нужно было прямо проговаривать, потому что с точки зрения автора казалось что мы тут говорим об одном, но после объяснения он понимал и переписывал.
В качестве эксперимента, я не буду переработанный вариант, хочу проработать это с вами. Скидывайте в комментах ваши примеры, а тот который победит по количеству лайков, я приведу как пример в одном из следующих постов.
p.s. Ребят, если вам интересно про все это, поставьте лайк, если нет - дизлайк
Ссылки: Телеграм | Youtube | VK
3👍303❤29👎24🔥15🍌6🤮2👀1
Легаси != говнокод
Каждый раз когда обсуждается легаси, создается впечатление, как будто мы обсуждаем какой-то очень плохо написанный код в прошлом, который обязательно надо выкинуть и переписать, потому что он нам мешает жить.
Последнее может быть правдой, но легаси может быть хорошо написанным и отлично работающим кодом. Почему?
Код становится легаси как только мы его выпустили, просто потому что уже начиная с этого момента, мы можем решить писать по другому, с другим набором библиотек и в другую сторону с точки зрения решаемых задач. Но на момент своего написания, он использовал самые современные библиотеки и подходы, а так же решал нужную задачу в тех ограничениях (сроках, ресурсах) настолько хорошо, насколько это было возможно.
Такой взгляд на ситуацию полезен, чтобы меньше стресовать на тему того, что приходится копаться в чем-то устаревшем или бояться идти в какие-то проекты. Легаси это вообще хорошо, только поработав с легаси, человек понимает, чего стоят те или иные решения.
Тогда что такое говнокод? Несмотря на наличие каких-то общепризнанных признаков, все же восприятие кода у разных людей слишком разное. Один видит что у нас классы разбиты не правильно, другой что система не разбита на сервисы, третий, что нет нормальной работы с микросервисами, а я, например, плююсь от программирования на флагах.
Давайте об этом поговорим немного (или много). Как вы определяете говнокод? И допустимо ли так делать?
Ссылки: Телеграм | Youtube | VK
Каждый раз когда обсуждается легаси, создается впечатление, как будто мы обсуждаем какой-то очень плохо написанный код в прошлом, который обязательно надо выкинуть и переписать, потому что он нам мешает жить.
Последнее может быть правдой, но легаси может быть хорошо написанным и отлично работающим кодом. Почему?
Код становится легаси как только мы его выпустили, просто потому что уже начиная с этого момента, мы можем решить писать по другому, с другим набором библиотек и в другую сторону с точки зрения решаемых задач. Но на момент своего написания, он использовал самые современные библиотеки и подходы, а так же решал нужную задачу в тех ограничениях (сроках, ресурсах) настолько хорошо, насколько это было возможно.
Такой взгляд на ситуацию полезен, чтобы меньше стресовать на тему того, что приходится копаться в чем-то устаревшем или бояться идти в какие-то проекты. Легаси это вообще хорошо, только поработав с легаси, человек понимает, чего стоят те или иные решения.
Тогда что такое говнокод? Несмотря на наличие каких-то общепризнанных признаков, все же восприятие кода у разных людей слишком разное. Один видит что у нас классы разбиты не правильно, другой что система не разбита на сервисы, третий, что нет нормальной работы с микросервисами, а я, например, плююсь от программирования на флагах.
Давайте об этом поговорим немного (или много). Как вы определяете говнокод? И допустимо ли так делать?
Ссылки: Телеграм | Youtube | VK
Telegram
Организованное программирование | Кирилл Мокевнин
Как из джуниора дойти до мидла, а потом и до синьора
Ютуб https://youtube.com/@mokevnin
Связь для предложений: @kirillpublic
Ютуб https://youtube.com/@mokevnin
Связь для предложений: @kirillpublic
3👍68❤16🔥5🤮3👀1
Долгожданный выпуск про DDD. Местами даже получились дебаты :) Смотрим, слушаем, наслаждаемся!
https://www.youtube.com/watch?v=03FnrgYLkV8
Альтернативные ссылки: Аудио | vk
https://www.youtube.com/watch?v=03FnrgYLkV8
Альтернативные ссылки: Аудио | vk
YouTube
DDD: как подружить бизнес и код | Кирилл Ветчинкин | Организованное программирование #55
Когда архитектура перестаёт быть просто техническим решением и становится инструментом понимания бизнеса, в игру вступает DDD. В этом видео — как выстраивать границы контекстов, выявлять субдомены, находить общий язык между разработкой и бизнесом, использовать…
5❤35👍28🔥12🤮3
Наткнулся на твит, где человек пишет: "вам не нужен ORM, если вы знаете SQL" — и прикладывает вот такой пример:
И его версию в Laravel:
Я абсолютно согласен, что знать SQL для бекендера важно и нужно, но этим все не ограничивается, а еще:
- То что здесь описывается это не ORM, а Query Builder
- Конкретно тут показан Query Builder Laravel, который нельзя назвать эталоном среди QB
- Запросы с группировкой составляют доли процента от обычных запросах в типовых веб-проектах (Аналитические запросы не считаем их вообще делают во внешних системах)
- Сам запрос это еще полдела, в статически типизированных языках еще придется фигачить маппинг если не пользоваться никакими либами
- Чистый SQL это полное отсутствие типобезопасности
- В такой запрос невозможно нормально вставить условные конструкции, например если понадобится фильтрация. Мы сразу попадем либо в склеивание строк, либо в необходимость затаскивать Query Builder
А на картинке к посту пример на drizzle-orm, в котором обеспечивается 100% типобезопасность: проверка всех условий (включая возможность выполнить join), всех операций, всех имен (таблиц и полей). Естественно автокомплит и рефакторинг в наличии.
Естественно это отдельный язык (хотя и крайне близкий к sql), но в современном мире ИИ, подобные запросы могут генериться без проблем, особенно в drizzle-orm, с его описанием схемы.
Плюс хочется сказать, что active = 1 в исходном запросе я не могу рассматривать как не говнокод. Активность должна определяться не флагом, а нормальным статусом. Про флаговое программирование скоро пост в телеге, не пропустите
Ссылки: Телеграм | Youtube | VK
SELECT u.*, COUNT(c.id) as comment_count
FROM users u
LEFT JOIN comments c ON c.user_id = u.id
WHERE u.active = 1 AND c.created_at > NOW() - INTERVAL 30 DAY
GROUP BY u.id
HAVING comment_count > 5;
И его версию в Laravel:
User::select('users.*', DB::raw('COUNT(comments.id) as comment_count'))
->leftJoin('comments', 'comments.user_id', '=', 'users.id')
->where('users.active', 1)
->where('comments.created_at', '>', DB::raw('NOW() - INTERVAL 30 DAY'))
->groupBy('users.id')
->having('comment_count', '>', 5)
->get();
Я абсолютно согласен, что знать SQL для бекендера важно и нужно, но этим все не ограничивается, а еще:
- То что здесь описывается это не ORM, а Query Builder
- Конкретно тут показан Query Builder Laravel, который нельзя назвать эталоном среди QB
- Запросы с группировкой составляют доли процента от обычных запросах в типовых веб-проектах (Аналитические запросы не считаем их вообще делают во внешних системах)
- Сам запрос это еще полдела, в статически типизированных языках еще придется фигачить маппинг если не пользоваться никакими либами
- Чистый SQL это полное отсутствие типобезопасности
- В такой запрос невозможно нормально вставить условные конструкции, например если понадобится фильтрация. Мы сразу попадем либо в склеивание строк, либо в необходимость затаскивать Query Builder
А на картинке к посту пример на drizzle-orm, в котором обеспечивается 100% типобезопасность: проверка всех условий (включая возможность выполнить join), всех операций, всех имен (таблиц и полей). Естественно автокомплит и рефакторинг в наличии.
Естественно это отдельный язык (хотя и крайне близкий к sql), но в современном мире ИИ, подобные запросы могут генериться без проблем, особенно в drizzle-orm, с его описанием схемы.
Плюс хочется сказать, что active = 1 в исходном запросе я не могу рассматривать как не говнокод. Активность должна определяться не флагом, а нормальным статусом. Про флаговое программирование скоро пост в телеге, не пропустите
Ссылки: Телеграм | Youtube | VK
👍81❤24🔥7👎5😁4🤔1
Программирование на флагах
Недавно я упомянул этот термин в одном и постов и получил неожиданно большое количество комментариев "что это?". Тема заслуживает раскрытия, поэтому пост.
Возьмем пример с sql:
Почти наверняка это поле из двух состояний активен/не активен (1/0), где активность определяется подтверждением емейла. В Postgresql это было бы true/false.
В целом, этот код выглядит совершенно нормально и очень хорошо работает. До поры до времени. А потом выясняется, что «неактивный» бывает как «удалённый», так и «заблокированный». Или, например, мы (бизнес) захотим давать работать на сайте тем кто зарегистрировался, но не подтвердил емейл. Подтверждение емейла будет работать как способ получить больше функций. В сумме мы получаем:
⁃ зарегистрированный
⁃ активный (подтвержден емейл)
⁃ удаленный
⁃ забаненный
Поскольку в базе уже есть active, то разарботчик, вероятно, пойдет по наиболее легкому пути - начнет добавлять новые флаги. Это просто и не требует хитрых миграций, чтобы обеспечивать обратную совместимость (для zero downtime). В итоге в базе появятся флаги:
и с этого момента начинается то самое программирование на флагах.
Вместо одной колонки состояния появляется несколько несвязанных булевых полей, которые можно комбинировать как угодно:
⁃ Комбинаторный взрыв состояний - пользователь может быть
⁃ Неявные правила - чтобы понять, что такое «активный пользователь», нужно лезть в код и смотреть, как именно проверяются флаги (active && !deleted && !banned && email_confirmed)
⁃ Сложность изменений - добавление нового флага или изменение бизнес-логики требует правок во множестве мест, потому что условия размазаны по коду и SQL-запросам.
⁃ Повышенный риск багов - достаточно забыть один флаг в проверке и все, приплыли.
Самое главное, что состояния в рамках одного процесса будут требовать синхронного изменения. Если меняется один, то надо не забыть поменять другой. Например если мы человека вводим в бан, то надо не забыть снять активность.
Более универсальный и безопасный для расширения способ в таком случае, это не флаги, а одно свойство определяющее состояние нашей сущности.
Мы кстати с этого и начали, когда перечисляли возможные состояния пользователя.
Фактически такой подход гораздо лучше ложится на то, как мы думаем об этом, чем флаги. Более того, это и намного нагляднее с точки зрения кода. Таким образом мы сразу решаем проблему синхронизации, переход из одного состояния в другое это одно действие и отсутствие багов в стиле "флаги не согласованы"
Есть еще один немаловажный плюс. Допустим у нас изначально два состояния и мы решили, что не будем бежать впереди паровоза. Мы делаем в базе boolean и попадаем в ситуацию, что когда добавится третье состояние, придется менять тип колонки на строку и все значения внутри него. Опытные разработчики сразу будут этому сопротивляться, потому что ломать обратную совместимость в базе нельзя, поэтому правильным способом, будет создать новую колонку и выполнить миграцию туда. Оно нам надо? То есть использования состояния это безопасно и расширяемо в отличие от флагов.
Но даже этого может быть недостаточно. Следующим шагом будет использование конечных автоматов https://github.com/eram/typescript-fsm (в том случае если нужна реакция на переходы, а сама структура переходов не линейная)
Ссылки: Телеграм | Youtube | VK
Недавно я упомянул этот термин в одном и постов и получил неожиданно большое количество комментариев "что это?". Тема заслуживает раскрытия, поэтому пост.
Возьмем пример с sql:
SELECT *
FROM users
WHERE active = 1;
Почти наверняка это поле из двух состояний активен/не активен (1/0), где активность определяется подтверждением емейла. В Postgresql это было бы true/false.
В целом, этот код выглядит совершенно нормально и очень хорошо работает. До поры до времени. А потом выясняется, что «неактивный» бывает как «удалённый», так и «заблокированный». Или, например, мы (бизнес) захотим давать работать на сайте тем кто зарегистрировался, но не подтвердил емейл. Подтверждение емейла будет работать как способ получить больше функций. В сумме мы получаем:
⁃ зарегистрированный
⁃ активный (подтвержден емейл)
⁃ удаленный
⁃ забаненный
Поскольку в базе уже есть active, то разарботчик, вероятно, пойдет по наиболее легкому пути - начнет добавлять новые флаги. Это просто и не требует хитрых миграций, чтобы обеспечивать обратную совместимость (для zero downtime). В итоге в базе появятся флаги:
active
, email_convirmed
, banned
, deleted
и с этого момента начинается то самое программирование на флагах.
Вместо одной колонки состояния появляется несколько несвязанных булевых полей, которые можно комбинировать как угодно:
⁃ Комбинаторный взрыв состояний - пользователь может быть
active = true
, но при этом banned = true
и deleted = true
. Что это значит? Он активен или нет?⁃ Неявные правила - чтобы понять, что такое «активный пользователь», нужно лезть в код и смотреть, как именно проверяются флаги (active && !deleted && !banned && email_confirmed)
⁃ Сложность изменений - добавление нового флага или изменение бизнес-логики требует правок во множестве мест, потому что условия размазаны по коду и SQL-запросам.
⁃ Повышенный риск багов - достаточно забыть один флаг в проверке и все, приплыли.
Самое главное, что состояния в рамках одного процесса будут требовать синхронного изменения. Если меняется один, то надо не забыть поменять другой. Например если мы человека вводим в бан, то надо не забыть снять активность.
Более универсальный и безопасный для расширения способ в таком случае, это не флаги, а одно свойство определяющее состояние нашей сущности.
Мы кстати с этого и начали, когда перечисляли возможные состояния пользователя.
type UserState = 'active' | 'banned' | 'deleted' | 'waiting_email_confirmation'
Фактически такой подход гораздо лучше ложится на то, как мы думаем об этом, чем флаги. Более того, это и намного нагляднее с точки зрения кода. Таким образом мы сразу решаем проблему синхронизации, переход из одного состояния в другое это одно действие и отсутствие багов в стиле "флаги не согласованы"
Есть еще один немаловажный плюс. Допустим у нас изначально два состояния и мы решили, что не будем бежать впереди паровоза. Мы делаем в базе boolean и попадаем в ситуацию, что когда добавится третье состояние, придется менять тип колонки на строку и все значения внутри него. Опытные разработчики сразу будут этому сопротивляться, потому что ломать обратную совместимость в базе нельзя, поэтому правильным способом, будет создать новую колонку и выполнить миграцию туда. Оно нам надо? То есть использования состояния это безопасно и расширяемо в отличие от флагов.
Но даже этого может быть недостаточно. Следующим шагом будет использование конечных автоматов https://github.com/eram/typescript-fsm (в том случае если нужна реакция на переходы, а сама структура переходов не линейная)
Ссылки: Телеграм | Youtube | VK
👍119❤27🔥12🤔2
Мы с Саматом раньше лично не были знакомы, но всегда крутились в одной технической тусовке. Я давно хотел записать с ним выпуск, потому что мне интересен путь, который он прошёл — как технарь превращается в предпринимателя. Я регулярно делаю подкасты на эту тему, и нам было важно разобрать его историю: он пришёл к бизнесу через запуск собственного аутсорса, а не через стартапы. В этом разговоре мы обсудили, как из разработчика вырастаешь в владельца сервиса, переход от аутсорса к продуктам, изменения на рынке и почему продажи часто важнее кода. Мы говорили о найме и проверке разработчиков, об испытательном сроке как фильтре, а также о скучных, но прибыльных нишах, автоматизации рутины и подводных камнях работы с клиентами.
https://youtube.com/watch?v=T7WsVGtKZJw
https://youtube.com/watch?v=T7WsVGtKZJw
YouTube
Самат Галимов: экс-CTO «Медузы» о найме, клиентах и деньгах в аутсорсе | #56
Мы с Саматом раньше лично не были знакомы, но всегда крутились в одной технической тусовке. Я давно хотел записать с ним выпуск, потому что мне интересен путь, который он прошёл — как технарь превращается в предпринимателя. Я регулярно делаю подкасты на эту…
103👍50🤮15❤9👎7🔥7⚡5🖕3💊1