Через полчаса стартую новогодний стрим, где покажу все что скрыто. Новости Хекслета, как прошел год, что будет в следующем. Немного про канал, немного про программирование, отвечу на вопросы и вот это все https://www.youtube.com/watch?v=RgZ-YsDuibc
YouTube
Хекслет и 2023: эфир с Кириллом Мокевниным / Внедрение ChatGPT в онлайн-курсы, планы и разработка
✅ Полезные вебинары по программированию каждую неделю: https://ru.hexlet.io/link/xNJY4I
Готовьте ваши вопросы – традиционный прямой эфир с сооснователем Хекслета Кириллом Мокевниным уже 27 декабря! Поговорим о новостях Хекслета за 2023 год, поделимся планами…
Готовьте ваши вопросы – традиционный прямой эфир с сооснователем Хекслета Кириллом Мокевниным уже 27 декабря! Поговорим о новостях Хекслета за 2023 год, поделимся планами…
❤19👍11🤔1
Итоги 2023 года
В этом году встречаемся последний раз, поэтому можно немного подвести итогов. За шесть месяцев я нафигачил 68 постов (ничо си) и вас, мои дорогие, стало 3500 человек. Учитывая что все это происходит в свободное время без каких-то вложений, то результат достаточно хороший, но пока еще никто не пришел с предложением продавать рекламу. Делать я этого не буду, но все равно обидно :D
В целом опыт классный и я буду продолжать. Единственное до конца непонятно в какую сторону сдвигаться. Канал в любом случае про программирование и связанные темы, но есть нюансы. В какой стек больше подаваться? Больше технических деталей или про концепции? Нужно ли обсуждать новости? Нужно ли делиться какими-то ситуативными вещами, типа что мы делаем на хекслете или с какими штуками я сталкиваюсь в работе? Нужно ли говорить про инструменты? Нужно ли переодически рассказывать про бизнесовую часть связанную с программированием (программисты с трудом выносят такие разговоры)? И так далее, пока не до конца определился и буду снова экспериментировать. Немного набросов, немного про жизнь, немного про принципы, немного про хардкор.
В конечном итоге, моя цель не в том чтобы просто выговориться, а в том, чтобы вы открывали для себя что-то новое, что влияло бы на ваше представление о программировании и внедрялось в ваши проекты. Я знаю что это иногда происходит, даже когда под постами разгорается много споров)
Всем спасибо за доверие! С наступающим! Я не планирую уходить на выходные, буду писать и дальше. Уже есть план на два десятка статей. Накидывайте своих тем, я буду их добавлять в список.
p.s. Если у вас есть свой канал на любой площадке, сбросьте ссылку на него в комментах с описанием. Давайте посмотрим кто у нас тут собрался)
В этом году встречаемся последний раз, поэтому можно немного подвести итогов. За шесть месяцев я нафигачил 68 постов (ничо си) и вас, мои дорогие, стало 3500 человек. Учитывая что все это происходит в свободное время без каких-то вложений, то результат достаточно хороший, но пока еще никто не пришел с предложением продавать рекламу. Делать я этого не буду, но все равно обидно :D
В целом опыт классный и я буду продолжать. Единственное до конца непонятно в какую сторону сдвигаться. Канал в любом случае про программирование и связанные темы, но есть нюансы. В какой стек больше подаваться? Больше технических деталей или про концепции? Нужно ли обсуждать новости? Нужно ли делиться какими-то ситуативными вещами, типа что мы делаем на хекслете или с какими штуками я сталкиваюсь в работе? Нужно ли говорить про инструменты? Нужно ли переодически рассказывать про бизнесовую часть связанную с программированием (программисты с трудом выносят такие разговоры)? И так далее, пока не до конца определился и буду снова экспериментировать. Немного набросов, немного про жизнь, немного про принципы, немного про хардкор.
В конечном итоге, моя цель не в том чтобы просто выговориться, а в том, чтобы вы открывали для себя что-то новое, что влияло бы на ваше представление о программировании и внедрялось в ваши проекты. Я знаю что это иногда происходит, даже когда под постами разгорается много споров)
Всем спасибо за доверие! С наступающим! Я не планирую уходить на выходные, буду писать и дальше. Уже есть план на два десятка статей. Накидывайте своих тем, я буду их добавлять в список.
p.s. Если у вас есть свой канал на любой площадке, сбросьте ссылку на него в комментах с описанием. Давайте посмотрим кто у нас тут собрался)
❤79🔥24🎄15👍12🤔1
Если бы я делал веб-проект с нуля
Меня регулярно спрашивают, на каких технологиях я бы делал проект если бы пришлось делать его с нуля. И у меня есть ответ на это. Он не универсальный, есть совершенно разные проекты, но так как нельзя охватить сразу все, я опишу некий средний проект, в котором есть веб-морда с большим количеством логики, скорее это какое-то SaaS-решение.
Базовым стеком я бы назвал:
Ruby On Rails, React, React Native
Дальше по приоритетам:
⁃ Система будет очень сложной с большим количеством программистов сразу? Spring Boot
⁃ Нужно много бекендовой тяжелой обработки? Go или Java
⁃ Нет экспертизы в руби? Берем Laravel или Django
⁃ Нужны нативные мобильные приложения? Тут все понятно: Swift и Kotlin
⁃ Нужен реалтайм на фронте (а значит асинхронный бекенд)? Node.js, Go
⁃ Нужно e2e тестирование? Playwright
Критерии достаточно простые. Не так важно что есть более крутые альтернативы, гораздо важнее распространенность и устоканенность экосистемы. Это дает возможность быстрее нанимать, быстрее двигаться, быстрее решать проблемы и понимать какие они вообще бывают (с новыми инструментами это становится сюрпризом). Еще важно кто стоит за технологией. Должны быть крупные ребята, которые вкладываются в нее иначе слишком большие риски, что она пойдет не туда/ее оставят и тому подобное
p.s. На чем бы вы сделали проект с нуля?
Меня регулярно спрашивают, на каких технологиях я бы делал проект если бы пришлось делать его с нуля. И у меня есть ответ на это. Он не универсальный, есть совершенно разные проекты, но так как нельзя охватить сразу все, я опишу некий средний проект, в котором есть веб-морда с большим количеством логики, скорее это какое-то SaaS-решение.
Базовым стеком я бы назвал:
Ruby On Rails, React, React Native
Дальше по приоритетам:
⁃ Система будет очень сложной с большим количеством программистов сразу? Spring Boot
⁃ Нужно много бекендовой тяжелой обработки? Go или Java
⁃ Нет экспертизы в руби? Берем Laravel или Django
⁃ Нужны нативные мобильные приложения? Тут все понятно: Swift и Kotlin
⁃ Нужен реалтайм на фронте (а значит асинхронный бекенд)? Node.js, Go
⁃ Нужно e2e тестирование? Playwright
Критерии достаточно простые. Не так важно что есть более крутые альтернативы, гораздо важнее распространенность и устоканенность экосистемы. Это дает возможность быстрее нанимать, быстрее двигаться, быстрее решать проблемы и понимать какие они вообще бывают (с новыми инструментами это становится сюрпризом). Еще важно кто стоит за технологией. Должны быть крупные ребята, которые вкладываются в нее иначе слишком большие риски, что она пойдет не туда/ее оставят и тому подобное
p.s. На чем бы вы сделали проект с нуля?
👍70❤5🤔3😁2🔥1👏1
Хранение деревьев в базе: Материализованный путь
Обычно, для хранения деревьев в базе в таблицу добавляется поле parent_id. Это дубовое решение, которое работает хорошо в небольшом количестве ситуаций. Кому-то даже может хватить, но есть запросы, на которых такая схема не работает. Например если нам понадобится извлечь ветку этого дерева. В таком случае понадобится рекурсивно выполнять запрос с parent_id где для каждого нового запроса parent_id становится id записи из предыдущего запроса. Кто-то пытается решать эту задачу прямо в коде, создавая очень не эффективное решение, кто-то с помощью возможностей базы данных, что сильно привязывает к ней, плюс, страдает интеграция с ORM.
Однако, есть решение лучше. Кое-кто слышал про nested set и это действительно решение, но очень громоздкое, тяжелое в реализации и понимании. Поэтому тут мы его даже не будем рассматривать, так как есть по настоящему элегантное решение, которое называется materialized path.
Идея в Materialized path заключается в том, что каждый узел (каждая запись в базе) хранит полный путь до корня. То есть вместо parent_id, мы добавляем path, который выгляди
Этим подходом мы сразу решили проблему выборку всей нужной ветки. Все что нам надо будет сделать это в коде разд
При такой структуре, для выборки всех потомков понадобится такой запрос:
Для выборки детей:
Одна из приятнейших особенностей materialized path заключается в том, что это очень наглядная схема, когда глядя на сырые данные в базе, сразу понятно что куда. Запросы строятся на здравом смысле и все это еще легко отлаживать.
habr.com/en/articles/46659/
Обычно, для хранения деревьев в базе в таблицу добавляется поле parent_id. Это дубовое решение, которое работает хорошо в небольшом количестве ситуаций. Кому-то даже может хватить, но есть запросы, на которых такая схема не работает. Например если нам понадобится извлечь ветку этого дерева. В таком случае понадобится рекурсивно выполнять запрос с parent_id где для каждого нового запроса parent_id становится id записи из предыдущего запроса. Кто-то пытается решать эту задачу прямо в коде, создавая очень не эффективное решение, кто-то с помощью возможностей базы данных, что сильно привязывает к ней, плюс, страдает интеграция с ORM.
Однако, есть решение лучше. Кое-кто слышал про nested set и это действительно решение, но очень громоздкое, тяжелое в реализации и понимании. Поэтому тут мы его даже не будем рассматривать, так как есть по настоящему элегантное решение, которое называется materialized path.
Идея в Materialized path заключается в том, что каждый узел (каждая запись в базе) хранит полный путь до корня. То есть вместо parent_id, мы добавляем path, который выгляди
т, нап
ример,
так: 1/2/5/8/99/3. / - часто используется как разделитель, но можно выбрать и другой. 1 - в примере это корень под который попадает текущая запись, 3 это прямой родитель. Все что между это промежуточные родительские записи.Этим подходом мы сразу решили проблему выборку всей нужной ветки. Все что нам надо будет сделать это в коде разд
елить 1/2/5/
8/99/3 на идентификаторы, и сделать оди
н in запро
с IN (1, 2, 5, 8, 99, 3)При такой структуре, для выборки всех потомков понадобится такой запрос:
SELECT * FROM <name> WHERE path LIKE '1/2/%';
Для выборки детей:
SELECT * FROM <name> WHERE path LIKE '1/2';
Одна из приятнейших особенностей materialized path заключается в том, что это очень наглядная схема, когда глядя на сырые данные в базе, сразу понятно что куда. Запросы строятся на здравом смысле и все это еще легко отлаживать.
habr.com/en/articles/46659/
👍92🔥36❤3🤔1🐳1👾1
Как мы экономим на фронтенде используя виджеты
Хекслет фронтенда реализован в виде виджетов. Что это значит? Изначально сам проект представляет собой классический MVC (model2), в котором View это обычные серверные шаблоны, в нашем случае на haml.
Это дешево, быстро и эффективно. По дефолту все отлично с сео и кнопкой назад. Нет отдельного фронтенда со своими приколами и интеграцией. Пока на сайте мало интерактивности, с таким подходом можно жить очень долго и счастливо.
Но в какой-то момент нам понадобились интерактивные элементы, например механизм квизов (вопросы после теории), обсуждения (вопросы/ответы во время обучения), тренажер и так далее. Все это было решено делать в виде виджетов, то есть кода, который подключается в классический бекенд шаблон:
Эти файлы готовит webpack на базе entrypoints. Каждый entrypoint это свой виджет. Внутри уже идет подключение реакта, стилей и всего что там нужно (с точки зрения перфоманса вебпак выделяет общие чанки, которые подключаются один раз для всех).
В итоге у нас несколько десятков подобных виджетов, которые подключаются в разных местах, для решения локальных задач. Из общего кода у этих виджетов только библиотеки. Все остальное свое. Размер виджетов от десятков строк кода до 5 тысяч.
Такой подход позволяет оставаться в рамках классической серверной шаблонизации и при этом по необходимости внедрят интерактивные элементы на нужных страницах или на сквозь (как нотификации).
Хекслет фронтенда реализован в виде виджетов. Что это значит? Изначально сам проект представляет собой классический MVC (model2), в котором View это обычные серверные шаблоны, в нашем случае на haml.
.table-responsive
%table.table.table-striped
%thead
%tr
%th= sort_link(@search, :id)
%th= sort_link(@search, :email)
%tbody
- @users.each do |user|
%tr
%td= user.id
%td= user.email
Это дешево, быстро и эффективно. По дефолту все отлично с сео и кнопкой назад. Нет отдельного фронтенда со своими приколами и интеграцией. Пока на сайте мало интерактивности, с таким подходом можно жить очень долго и счастливо.
Но в какой-то момент нам понадобились интерактивные элементы, например механизм квизов (вопросы после теории), обсуждения (вопросы/ответы во время обучения), тренажер и так далее. Все это было решено делать в виде виджетов, то есть кода, который подключается в классический бекенд шаблон:
- append_javascript_packs 'community'
- append_stylesheet_packs 'community'
Эти файлы готовит webpack на базе entrypoints. Каждый entrypoint это свой виджет. Внутри уже идет подключение реакта, стилей и всего что там нужно (с точки зрения перфоманса вебпак выделяет общие чанки, которые подключаются один раз для всех).
import app from '../community/index.jsx';
import './community.scss';
const communityBoxId = 'community-box';
app.init(communityBoxId, /* параметры */);
В итоге у нас несколько десятков подобных виджетов, которые подключаются в разных местах, для решения локальных задач. Из общего кода у этих виджетов только библиотеки. Все остальное свое. Размер виджетов от десятков строк кода до 5 тысяч.
Такой подход позволяет оставаться в рамках классической серверной шаблонизации и при этом по необходимости внедрят интерактивные элементы на нужных страницах или на сквозь (как нотификации).
👍49🐳13🔥12⚡3❤2❤🔥2🤔2
Заблуждения программистов относительно времени
Кто работал со временем в коде, тот в цирке не смеется. Вот вам подборка заблуждений насчет времени, которые гуляют среди программистов:
1. В месяцах бывает 28, 29, 30 или 31 день.
2. В одно и то же время используется только одна календарная система.
3. Переход на летнее время происходит в одно и то же время каждый год.
4. Переход на летнее время происходит в одно и то же время в каждом часовом поясе.
5. Переход на летнее время всегда корректируется на час.
6. В одном и том же месяце везде одинаковое количество дней!
7. Время Unix - это количество секунд, прошедших с 1 января 1970 года.
8. День перед субботой всегда пятница.
9. Если создать два объекта даты рядом друг с другом, они будут представлять одно и то же время. (фантастический генератор Heisenbug)
10. Недели начинаются в понедельник.
11. Дни начинаются утром.
12. Выходные состоят из субботы и воскресенья.
13. В каждой минуте 60 секунд.
14. GMT и UTC - это один и тот же часовой пояс.
15. Время всегда идет вперед.
16. 24:12:34 - недействительное время.
17. Часовые пояса всегда отличаются на целый час
18. Двузначные годы должны быть где-то в диапазоне 1900-2099
19. Существует только 24 часовых пояса
20. Часовые пояса всегда на целые часы удалены от UTC
21. В году 365 или 366 дней.
22. Високосные годы случаются каждые 4 года.
p.s. оригинал поста https://infiniteundo.com/post/25509354022/more-falsehoods-programmers-believe-about-time Там 79 пунктов
Кто работал со временем в коде, тот в цирке не смеется. Вот вам подборка заблуждений насчет времени, которые гуляют среди программистов:
1. В месяцах бывает 28, 29, 30 или 31 день.
2. В одно и то же время используется только одна календарная система.
3. Переход на летнее время происходит в одно и то же время каждый год.
4. Переход на летнее время происходит в одно и то же время в каждом часовом поясе.
5. Переход на летнее время всегда корректируется на час.
6. В одном и том же месяце везде одинаковое количество дней!
7. Время Unix - это количество секунд, прошедших с 1 января 1970 года.
8. День перед субботой всегда пятница.
9. Если создать два объекта даты рядом друг с другом, они будут представлять одно и то же время. (фантастический генератор Heisenbug)
10. Недели начинаются в понедельник.
11. Дни начинаются утром.
12. Выходные состоят из субботы и воскресенья.
13. В каждой минуте 60 секунд.
14. GMT и UTC - это один и тот же часовой пояс.
15. Время всегда идет вперед.
16. 24:12:34 - недействительное время.
17. Часовые пояса всегда отличаются на целый час
18. Двузначные годы должны быть где-то в диапазоне 1900-2099
19. Существует только 24 часовых пояса
20. Часовые пояса всегда на целые часы удалены от UTC
21. В году 365 или 366 дней.
22. Високосные годы случаются каждые 4 года.
p.s. оригинал поста https://infiniteundo.com/post/25509354022/more-falsehoods-programmers-believe-about-time Там 79 пунктов
Tumblr
More falsehoods programmers believe about time; "wisdom of the crowd" edition
A couple of days ago I decided to [write down some of the things I've learned about testing][testing_post] over the course of the last [several years.][codeascraft] In the course of enumerating the...
👍35❤14🔥7😁7🤯5🤔4🤷♂2🤓1
Синхронные VS Асинхронные дейли
Дейли митинги, если без фанатизма, довольно неплохая практика в девелоперских командах. Почти везде где я работал они либо уже были, либо я их внедрял. Как полагалось дейли проводились в коротком формате, стоя и когда все соберутся в одно и тоже время. Этот формат для многих был долгое время единственно правильным.
В какой-то момент все чаще стали появляться удаленные сотрудники и дейли местами переехали в совместный кол по утрам. Кто жил в других часовых поясах напрягался, но в целом жить было можно. Потом у меня появилась своя компания где разница в часовых поясах и времени работы сместилась настолько, что проводить такие дейли стало проблемой. Плюс стал набирать обороты слак и общение частично переехало туда.
Я уже не помню когда пришла эта идея, но в слаке появились боты для проведения асинхронных дейли и мы решили их попробовать внедрить. Практически сразу стало понятно что это чертовски удобно и с тех пор (прошло очень много лет) дейли в командах только асинхронные. Что мы выяснили в процессе:
• Асинхронный дейли напрягает намного меньше 🙂
• Не нужен процессник, который ведет дейли и следит за тем как он проходит. Достаточно руководителя, который может поправить формат дейли, если кто-то пишет не в том формате, который требуется.
• Больше никаких завязок друг на друга, начал работать - заполнил дейли. Никто никого не ждет, никто не пропускает (если не отсутствует), никто не тратит время на то что ему не интересно.
• Асинхронный дейли в слаке внезапно оказался удобен тогда, когда нужно что-то уточнить или поправить человека. Любой человек в команде может зайти в тред к посту и что-то уточнить и синхронизировать свою работу. Плюс это видят остальные, что делает процесс прозрачным.
• Асинхронный текстовый дейли сохраняется, можно примерно понимать что происходит у человека или происходило не только в конкретный день но и в динамике.
В итоге перешли и остались довольны. Пример того как это работает можно посмотреть тут https://geekbot.com/
p.s. Какой дейли у вас в компании? Это эффективно иль нет?
Дейли митинги, если без фанатизма, довольно неплохая практика в девелоперских командах. Почти везде где я работал они либо уже были, либо я их внедрял. Как полагалось дейли проводились в коротком формате, стоя и когда все соберутся в одно и тоже время. Этот формат для многих был долгое время единственно правильным.
В какой-то момент все чаще стали появляться удаленные сотрудники и дейли местами переехали в совместный кол по утрам. Кто жил в других часовых поясах напрягался, но в целом жить было можно. Потом у меня появилась своя компания где разница в часовых поясах и времени работы сместилась настолько, что проводить такие дейли стало проблемой. Плюс стал набирать обороты слак и общение частично переехало туда.
Я уже не помню когда пришла эта идея, но в слаке появились боты для проведения асинхронных дейли и мы решили их попробовать внедрить. Практически сразу стало понятно что это чертовски удобно и с тех пор (прошло очень много лет) дейли в командах только асинхронные. Что мы выяснили в процессе:
• Асинхронный дейли напрягает намного меньше 🙂
• Не нужен процессник, который ведет дейли и следит за тем как он проходит. Достаточно руководителя, который может поправить формат дейли, если кто-то пишет не в том формате, который требуется.
• Больше никаких завязок друг на друга, начал работать - заполнил дейли. Никто никого не ждет, никто не пропускает (если не отсутствует), никто не тратит время на то что ему не интересно.
• Асинхронный дейли в слаке внезапно оказался удобен тогда, когда нужно что-то уточнить или поправить человека. Любой человек в команде может зайти в тред к посту и что-то уточнить и синхронизировать свою работу. Плюс это видят остальные, что делает процесс прозрачным.
• Асинхронный текстовый дейли сохраняется, можно примерно понимать что происходит у человека или происходило не только в конкретный день но и в динамике.
В итоге перешли и остались довольны. Пример того как это работает можно посмотреть тут https://geekbot.com/
p.s. Какой дейли у вас в компании? Это эффективно иль нет?
Geekbot
Geekbot — Standups, Polls & Surveys in Slack and MS Teams
Automate standups, run surveys, and use quick polls to make fast decisions. Free up time for meaningful work!
👍57🔥11❤2❤🔥1🤔1
Фил тут забахал пост в твиттере на тему того, какой язык вам нравится https://twitter.com/fillpackart/status/1750825875669688497 Мой топ для души: Elixir, Clojure, Ocaml, Ruby (и для работы). А у вас?
X (formerly Twitter)
Фил Ранжин (@fillpackart) on X
Какой язык программирования вам сейчас нравится больше всех? Именно нравится, кайф даёт процесс разработки на нём. На бизнес и его ебучие запросы похуй, прям вот для души: какой?
🤡20👍18💩4🤔1
В ближайшие месяцы хотим провести экскурсии в it компании для студентов нашего колледжа https://hexly.ru/ Это Москва, Питер и Новосиб. Ребят если вы можете это организовать или есть кому/кого посоветовать, то напишите плс. Лайк шер алишер.
hexly.ru
Хекслет IT колледж — обучение программированию после 9 и 11 класса
Открыт набор 2024/2025. Поступление без результатов экзаменов на IT-специальность. Колледж информационных технологий в Москве и Санкт-Петербурге. Первый IT-колледж с гарантированной стажировкой
👏16😁3🤔1
Ревью кода, которые не тормозят
Проведение ревью во многих компаниях довольно болезненная тема, пулреквесты висят дням, а то и неделями. Обсуждения затягиваются, иногда приходится много и долго переделывать, а в конце еще целый день ребейза чтобы выкатиться.
Корень сложности здесь кроется в том, что пулреквест обычно решает какую-то задачу от начала до конца. Поэтому недостаточно быстро пробежаться по коду, придется вникать целиком, в том числе в архитектуру решения, так как оно может не соответствовать тому как и куда движется проект, что может повлечь за собой серьезные обсуждения и переделки в конце концов. Все это требует времени и ресурсов мозга, который обычно сопротивляется крупным изменениям, в которые надо погружаться.
Можно считать это издержками производства, но можно пойти и другим путем. Например, разбивать задачу на более мелкие шаги, которые не решают задачу целиком (если она большая), но которые делают какое-то одно законченное понятное действие. Тут часть программистов, обычно, говорит что “моя фича не бьется”, но жизнь показывает, что почти все бьется, но чтобы это увидеть нужно немного потратить время на обсуждение.
По каким критериям можно разбивать задачу?
⁃ По слоям. Например мы можем сначала создать таблицы в базе данных и модели для них. Эта самая важная часть с точки зрения архитектуры кода и при этом она довольно компактная. Использование моделей уже можно добавлять позже, отдельным пулреквестом.
⁃ По возможностям. Можно ограничить функциональность, так чтобы первый рабочий вариант не включал всех требований и не поддерживал все возможные варианты поведения или форматы или что-то еще.
⁃ По компонентам. Просто добавляем куски кода, которые потом соберуться в картинку, но сейчас сами по себе не задействованы. Например утилитные классы и тому подобное. Тут конечно надо находить баланс, чтобы в pr можно было оценить все же этот код его правильность нужность и направление движения.
Одна из фишек такого подхода в том, что подобные пулреквесты требуют намного меньшего внимания так как изменения небольшие и даже если что-то пошло не туда, это можно быстро поправить. Таким образом значительно снижается шанс потерять время и деньги, а значит, что в немалом количестве случаев принятие пулреквестов можно делегировать ребятам с меньшим опытом или вообще дать возможность сливать что-то автоматом при прохождении всех проверок (например если есть требование писать тесты).
Например у себя мы делаем так, что опытные разработчики сами и сливают, при этом они посматривают код друг друга, но уже опосля. Иногда не сливают, если хотят посоветоваться. Мидлы сами не сливают, но пулреквесты делают небольшими. А у джуниоров не бывает больших пулреквестов, поэтому они их делают и ждут когда их проверят.
p.s. Вы страдаете от процесса проверки пулреквестов у вас в компании?
Проведение ревью во многих компаниях довольно болезненная тема, пулреквесты висят дням, а то и неделями. Обсуждения затягиваются, иногда приходится много и долго переделывать, а в конце еще целый день ребейза чтобы выкатиться.
Корень сложности здесь кроется в том, что пулреквест обычно решает какую-то задачу от начала до конца. Поэтому недостаточно быстро пробежаться по коду, придется вникать целиком, в том числе в архитектуру решения, так как оно может не соответствовать тому как и куда движется проект, что может повлечь за собой серьезные обсуждения и переделки в конце концов. Все это требует времени и ресурсов мозга, который обычно сопротивляется крупным изменениям, в которые надо погружаться.
Можно считать это издержками производства, но можно пойти и другим путем. Например, разбивать задачу на более мелкие шаги, которые не решают задачу целиком (если она большая), но которые делают какое-то одно законченное понятное действие. Тут часть программистов, обычно, говорит что “моя фича не бьется”, но жизнь показывает, что почти все бьется, но чтобы это увидеть нужно немного потратить время на обсуждение.
По каким критериям можно разбивать задачу?
⁃ По слоям. Например мы можем сначала создать таблицы в базе данных и модели для них. Эта самая важная часть с точки зрения архитектуры кода и при этом она довольно компактная. Использование моделей уже можно добавлять позже, отдельным пулреквестом.
⁃ По возможностям. Можно ограничить функциональность, так чтобы первый рабочий вариант не включал всех требований и не поддерживал все возможные варианты поведения или форматы или что-то еще.
⁃ По компонентам. Просто добавляем куски кода, которые потом соберуться в картинку, но сейчас сами по себе не задействованы. Например утилитные классы и тому подобное. Тут конечно надо находить баланс, чтобы в pr можно было оценить все же этот код его правильность нужность и направление движения.
Одна из фишек такого подхода в том, что подобные пулреквесты требуют намного меньшего внимания так как изменения небольшие и даже если что-то пошло не туда, это можно быстро поправить. Таким образом значительно снижается шанс потерять время и деньги, а значит, что в немалом количестве случаев принятие пулреквестов можно делегировать ребятам с меньшим опытом или вообще дать возможность сливать что-то автоматом при прохождении всех проверок (например если есть требование писать тесты).
Например у себя мы делаем так, что опытные разработчики сами и сливают, при этом они посматривают код друг друга, но уже опосля. Иногда не сливают, если хотят посоветоваться. Мидлы сами не сливают, но пулреквесты делают небольшими. А у джуниоров не бывает больших пулреквестов, поэтому они их делают и ждут когда их проверят.
p.s. Вы страдаете от процесса проверки пулреквестов у вас в компании?
👍41💯7❤4🤔3😭2🤡1
Парный кодинг для всех
Про парное программирование слышали наверное все, но все ли его практикуют?
Сразу к делу, парное программирование, при правильном использовании, лучшая техника прокачки и распространения знаний в команде. Кроме того, качество кода выдаваемое парами, намного выше чем код, который пишется в одиночку.
Небольшой ликбез. Парное программирование работает так, один пишет код, второй сидит сзади, вникает и подсказывает (а не сам сидит в своем ноуте и делает что-то другое). Пары меняются раз в какое-то время, например полчаса. Меняются это не значит что они работают за одним компом, окружение у всех разное, поэтому они скорее переходят от одного компьютера к другому. При этом парное программирование хорошо работает когда как минимум один из разработчиков опытен. Если оба новички, то им нужно помочь научиться работать в паре. Если говорить про уровень задач, то идеально в парах выполнять средние задачи, когда не слишком просто, но и не слишком сложно (где надо скорее больше сидеть думать или тратить часы на отладку). А еще парнокодить можно удаленно.
Что происходит в это время? Во-первых у разных людей разный уровень владения инструментами и видя как работает пара, другой человек постоянно узнает новые подходы, горячие клавиши и другие примеры оптимизации работы. Тоже самое происходит в коде, подходы, функции, анализ документации, ошибок и многое другое значительно влияют на обоих людей в паре. Это кстати работает как и для опытных разработчиков так и для пары в которой один человек новичок. В это время новичок конечно прокачивается значительно больше чем опытный. Во-вторых, человек который сидит сзади, находится немного в другом режиме работы (мозга), он замечает значительно больше архитектурных проблем и потенциальных багов. Это приводит к повышению качества кода при более высокой скорости разработки чем если бы это был один человек.
Из важного, работать в парах по началу может быть тяжело ментально, тут нужно время на привыкание. Плюс пары могут начать спорить из-за стандартов кодирования, поэтому такие вещи лучше зафиксировать заранее. Плюс, как это не странно, надо чистить зубы и иметь здоровый рот 🙂 В остальном это крутейшая техника, которую имеет смысл регулярно практиковать в любой компании.
Научные исследования https://tuple.app/pair-programming-guide/scientific-research-into-pair-programming
Отличный доклад на тему https://www.youtube.com/watch?v=Vu5ujdZDS6E
p.s. Практикуете ли вы парное программирование у себя в компании?
Про парное программирование слышали наверное все, но все ли его практикуют?
Сразу к делу, парное программирование, при правильном использовании, лучшая техника прокачки и распространения знаний в команде. Кроме того, качество кода выдаваемое парами, намного выше чем код, который пишется в одиночку.
Небольшой ликбез. Парное программирование работает так, один пишет код, второй сидит сзади, вникает и подсказывает (а не сам сидит в своем ноуте и делает что-то другое). Пары меняются раз в какое-то время, например полчаса. Меняются это не значит что они работают за одним компом, окружение у всех разное, поэтому они скорее переходят от одного компьютера к другому. При этом парное программирование хорошо работает когда как минимум один из разработчиков опытен. Если оба новички, то им нужно помочь научиться работать в паре. Если говорить про уровень задач, то идеально в парах выполнять средние задачи, когда не слишком просто, но и не слишком сложно (где надо скорее больше сидеть думать или тратить часы на отладку). А еще парнокодить можно удаленно.
Что происходит в это время? Во-первых у разных людей разный уровень владения инструментами и видя как работает пара, другой человек постоянно узнает новые подходы, горячие клавиши и другие примеры оптимизации работы. Тоже самое происходит в коде, подходы, функции, анализ документации, ошибок и многое другое значительно влияют на обоих людей в паре. Это кстати работает как и для опытных разработчиков так и для пары в которой один человек новичок. В это время новичок конечно прокачивается значительно больше чем опытный. Во-вторых, человек который сидит сзади, находится немного в другом режиме работы (мозга), он замечает значительно больше архитектурных проблем и потенциальных багов. Это приводит к повышению качества кода при более высокой скорости разработки чем если бы это был один человек.
Из важного, работать в парах по началу может быть тяжело ментально, тут нужно время на привыкание. Плюс пары могут начать спорить из-за стандартов кодирования, поэтому такие вещи лучше зафиксировать заранее. Плюс, как это не странно, надо чистить зубы и иметь здоровый рот 🙂 В остальном это крутейшая техника, которую имеет смысл регулярно практиковать в любой компании.
Научные исследования https://tuple.app/pair-programming-guide/scientific-research-into-pair-programming
Отличный доклад на тему https://www.youtube.com/watch?v=Vu5ujdZDS6E
p.s. Практикуете ли вы парное программирование у себя в компании?
tuple.app
Tuple's Pair Programming Guide
Comprehensive guides for thoughtful pair programmers.
👍45❤25🔥3🤔2
simple git hook для всех
Вы знаете что можно удобно управлять хуками в git с помощью либы simple-git-hook?
Два действия:
1. Ставится эта либа через npm
2. Прописывается нужная команда на нужный хук в package.json
3. Запускаетс
Шикарная вещь, ставим во все наши опенсорсы и внутренние проекты.
p.s. Какие подобные улучшалки вы еще знаете?
Вы знаете что можно удобно управлять хуками в git с помощью либы simple-git-hook?
Два действия:
1. Ставится эта либа через npm
2. Прописывается нужная команда на нужный хук в package.json
3. Запускаетс
я команда npx simple
-git-hooks, которая все сама апдейтит
{
"simple-git-hooks": {
"pre-commit": "npx lint-staged",
"pre-push": "cd ../../ && npm run format",
// All unused hooks will be removed automatically by default
// but you can use the `preserveUnused` option like following to prevent this behavior
// if you'd prefer preserve all unused hooks
"preserveUnused": true,
// if you'd prefer preserve specific unused hooks
"preserveUnused": ["commit-msg"]
}
}
Шикарная вещь, ставим во все наши опенсорсы и внутренние проекты.
p.s. Какие подобные улучшалки вы еще знаете?
👏15👍8🥴7🔥2❤1🤔1
Делать ли livecoding на собесе
Тут в твиттере разгорелось после того как Козуля написал о лайвкодинге, который не проходят люди подделавшие резюме. Твит раз https://twitter.com/vladkozulya/status/1754986992570450283 твит два https://twitter.com/vladkozulya/status/1755209744057299174
Как обычно все поделились на две группы, среди которых та что считает лайвкодинг злом. Хочу на эту тему кое что сказать.
Если коротко, то я считаю что уровень джуниор и большинство тех кто идет на мидла, должны проходить стадию лайвкодинга. У синьоров обычно есть либо открытые проекты либо куски кода, либо с ними можно глубоко закопаться в проблематику и технические решения из которых многое становится понятно. По лайвкодить в целом тоже можно, но тут скорее только если есть доп сомнения. В моей практике такого было мало.
С джуниорами у меня была ситуация когда я их нанимал в больших количествах и в какой-то момент почувствовал что могу очень быстро понимать кто потянет, а кто нет. Отменил лайвкодинг и буквально сразу после этого жизнь меня ударила обухом по голове. Я встретил как минимум двух людей, которые умудрились меня заболтать (я многого с них не спрашивал, они же джуны) и я повелся на их осведомленность и рассуждения по разным темам. А потом оказалось что люди просто не могут писать код и не обучаемы за разумное время (у меня за два месяца не получилось их сдвинуть с места). При том что у них был уже опыт на другом месте и когда я спрашивал как так они говорили “у меня были проблемы на другом месте, я подбирал все методом тыка”.
А что касается разговоров что собес это стресс и человек покажет себя хуже. Да это так, но во-первых задание все же, в моем случае, простое, а во-вторых, если человека так парализует, то риск что с ним произойдет тоже самое когда рухнет продакшен (да он потом окрепнет, но риск что нет тоже есть) не иллюзорный и как следствие в-третьих, выбор среди джуниоров достаточно большой, чтобы поставить себе планку “справился с лайвкодингом”.
p.s. Вы делаете лайвкодинг? Проходите его сами и завалили?
p.s.s. Задачка на разминку: Какой угол между часовой и минутной стрелкой когда на часах 15:15? 🙂
Тут в твиттере разгорелось после того как Козуля написал о лайвкодинге, который не проходят люди подделавшие резюме. Твит раз https://twitter.com/vladkozulya/status/1754986992570450283 твит два https://twitter.com/vladkozulya/status/1755209744057299174
Как обычно все поделились на две группы, среди которых та что считает лайвкодинг злом. Хочу на эту тему кое что сказать.
Если коротко, то я считаю что уровень джуниор и большинство тех кто идет на мидла, должны проходить стадию лайвкодинга. У синьоров обычно есть либо открытые проекты либо куски кода, либо с ними можно глубоко закопаться в проблематику и технические решения из которых многое становится понятно. По лайвкодить в целом тоже можно, но тут скорее только если есть доп сомнения. В моей практике такого было мало.
С джуниорами у меня была ситуация когда я их нанимал в больших количествах и в какой-то момент почувствовал что могу очень быстро понимать кто потянет, а кто нет. Отменил лайвкодинг и буквально сразу после этого жизнь меня ударила обухом по голове. Я встретил как минимум двух людей, которые умудрились меня заболтать (я многого с них не спрашивал, они же джуны) и я повелся на их осведомленность и рассуждения по разным темам. А потом оказалось что люди просто не могут писать код и не обучаемы за разумное время (у меня за два месяца не получилось их сдвинуть с места). При том что у них был уже опыт на другом месте и когда я спрашивал как так они говорили “у меня были проблемы на другом месте, я подбирал все методом тыка”.
А что касается разговоров что собес это стресс и человек покажет себя хуже. Да это так, но во-первых задание все же, в моем случае, простое, а во-вторых, если человека так парализует, то риск что с ним произойдет тоже самое когда рухнет продакшен (да он потом окрепнет, но риск что нет тоже есть) не иллюзорный и как следствие в-третьих, выбор среди джуниоров достаточно большой, чтобы поставить себе планку “справился с лайвкодингом”.
p.s. Вы делаете лайвкодинг? Проходите его сами и завалили?
p.s.s. Задачка на разминку: Какой угол между часовой и минутной стрелкой когда на часах 15:15? 🙂
X (formerly Twitter)
Козуля (@vladkozulya) on X
При чем написанное в резюме никак не коррелирует с тем, пройдет ли человек техническое интервью.
Лайвкодинг не щадит никого. Я почти никогда не угадываю, дойдет ли человек до финала или нет. Как так. Это даже не олимпиадная шняга, а задачи прямо из проекта…
Лайвкодинг не щадит никого. Я почти никогда не угадываю, дойдет ли человек до финала или нет. Как так. Это даже не олимпиадная шняга, а задачи прямо из проекта…
👍34🔥8👎2🤔1🤮1
Переписывание редактора Хекслета на TS
Давно я не махал шашками серьезно, а тут полез поправить одну штуку в редактор, ну и как-то затянуло и в итоге уже третью неделю я переписываю его с JS на TS. Заодно так сказать вливаюсь в современные тренды. Я еще не закончил, но история уже получается прикольная, что я даже пытаюсь податься с докладом на holyjs, чтобы там про это рассказать.
Здесь я поделюсь немного разными мыслями, которые возникли в процессе. Понимаю что для многих это банальщина так как TS щас используют все, но вдруг кому будет интересно и даже полезно. Посвящу этот пост бекенду на Next.js
Первое что я сделал это заменил бек fastify на nextjs. Я люблю fastify, но мне хотелось снизить уровень конфигурирования до минимума. Это получилось, что-что, а вот тут next работает из коробки очень хорошо. Иногда все же приходится рестартовать, когда почему-то стейт не обновляется на беке, но в целом оно как-то само там магически работает и достаточно легко поддается легкой кастомизации если надо.
Что удивило, это поддержка бека. Правда вебсокеты подрубаются как костыль и команда разработки не очень спешит заниматься этим вопросом, так как для их платформы Vercel это не вещь, которая принесет деньги. Из-за этого получилось что я одновременно для части апи использую старый роутинг pages, а для части новый в app. Это рекомендация во всех issues.
Из странного, некст не показывает access логи к апи. Если что-то не так, ты вообще не понимаешь что не так. Опций никаких нет, в ишьюсе тихо. Понятно что api не приоритет.
Их хорошего, за счет того что у неста все же есть бек и мне он подходит, то получилось что не надо стартовать два отдельных приложения и менеджерить их. А это всегда требует доп усилий, в таких случаях, надо поставить что-то типа foreman (pm2) или docker compose.
В целом у редактора бекенд очень небольшой, буквально вебсокеты с rpc на 15 действий поверх него и пара rest эндпоинтов. Некст такое обрабатывает легко. Но если бы у меня был по настоящему большой и развесистый бекенд, то я бы брал fastify.
Давно я не махал шашками серьезно, а тут полез поправить одну штуку в редактор, ну и как-то затянуло и в итоге уже третью неделю я переписываю его с JS на TS. Заодно так сказать вливаюсь в современные тренды. Я еще не закончил, но история уже получается прикольная, что я даже пытаюсь податься с докладом на holyjs, чтобы там про это рассказать.
Здесь я поделюсь немного разными мыслями, которые возникли в процессе. Понимаю что для многих это банальщина так как TS щас используют все, но вдруг кому будет интересно и даже полезно. Посвящу этот пост бекенду на Next.js
Первое что я сделал это заменил бек fastify на nextjs. Я люблю fastify, но мне хотелось снизить уровень конфигурирования до минимума. Это получилось, что-что, а вот тут next работает из коробки очень хорошо. Иногда все же приходится рестартовать, когда почему-то стейт не обновляется на беке, но в целом оно как-то само там магически работает и достаточно легко поддается легкой кастомизации если надо.
Что удивило, это поддержка бека. Правда вебсокеты подрубаются как костыль и команда разработки не очень спешит заниматься этим вопросом, так как для их платформы Vercel это не вещь, которая принесет деньги. Из-за этого получилось что я одновременно для части апи использую старый роутинг pages, а для части новый в app. Это рекомендация во всех issues.
Из странного, некст не показывает access логи к апи. Если что-то не так, ты вообще не понимаешь что не так. Опций никаких нет, в ишьюсе тихо. Понятно что api не приоритет.
Их хорошего, за счет того что у неста все же есть бек и мне он подходит, то получилось что не надо стартовать два отдельных приложения и менеджерить их. А это всегда требует доп усилий, в таких случаях, надо поставить что-то типа foreman (pm2) или docker compose.
В целом у редактора бекенд очень небольшой, буквально вебсокеты с rpc на 15 действий поверх него и пара rest эндпоинтов. Некст такое обрабатывает легко. Но если бы у меня был по настоящему большой и развесистый бекенд, то я бы брал fastify.
👍38🔥2🤔1
Кладбище забытых проектов
Большинство проектов на которых я работал программистом закрылись. Не взлетел стартап, разорилась компания, что-то стало не актуально. Иногда, когда надо показать что-то из прошлого, я понимаю, что даже ни один сайт, который хоть как-то был связан с тем что я делал, не работает.
Странное чувство, вроде и не в стол работал, а все в труху. Возникает вопрос, что оставил после себя? А у меня такой вопрос возникает, потому что как программист я уже не сделаю никаких свершений, хотя и продолжаю этим заниматься.
Кое что все таки оставил, одна часть это опенсорс, который может и не стал невероятно популярным, но все же я понаделал разного добра: отправил кучу пулреквестов (недавно у меня приняли пулреквест из php либы, который я года три-четыре назад сделал), создал немного относительно популярных библиотек, собрал большой список тестовых заданий, который наверное стал самым популярным из того что я начинал (но это не код хаха) https://github.com/Hexlet/ru-test-assignments.
Вторая это Хекслет, которым я занимаюсь уже 11 лет. Есть чем городиться, это довольно крутая техническая штука, которая даже легла в основу книги https://painlessrails.com/book/ Несмотря на размер (а Хекслет довольно большой) и возраст, он в отличном состоянии и поддерживается очень небольшой профессиональной командой. Но так как он свой, почему-то нет ощущения, что я сделал что-то как программист, с чужими это как-то по другому работает)
Но вообще больше я скорее сделал уже как наставник, преподаватель и автор курсов, но это уже совсем другая история.
p.s. Что самого крутого сделали вы?
Большинство проектов на которых я работал программистом закрылись. Не взлетел стартап, разорилась компания, что-то стало не актуально. Иногда, когда надо показать что-то из прошлого, я понимаю, что даже ни один сайт, который хоть как-то был связан с тем что я делал, не работает.
Странное чувство, вроде и не в стол работал, а все в труху. Возникает вопрос, что оставил после себя? А у меня такой вопрос возникает, потому что как программист я уже не сделаю никаких свершений, хотя и продолжаю этим заниматься.
Кое что все таки оставил, одна часть это опенсорс, который может и не стал невероятно популярным, но все же я понаделал разного добра: отправил кучу пулреквестов (недавно у меня приняли пулреквест из php либы, который я года три-четыре назад сделал), создал немного относительно популярных библиотек, собрал большой список тестовых заданий, который наверное стал самым популярным из того что я начинал (но это не код хаха) https://github.com/Hexlet/ru-test-assignments.
Вторая это Хекслет, которым я занимаюсь уже 11 лет. Есть чем городиться, это довольно крутая техническая штука, которая даже легла в основу книги https://painlessrails.com/book/ Несмотря на размер (а Хекслет довольно большой) и возраст, он в отличном состоянии и поддерживается очень небольшой профессиональной командой. Но так как он свой, почему-то нет ощущения, что я сделал что-то как программист, с чужими это как-то по другому работает)
Но вообще больше я скорее сделал уже как наставник, преподаватель и автор курсов, но это уже совсем другая история.
p.s. Что самого крутого сделали вы?
GitHub
GitHub - Hexlet/ru-test-assignments: Тестовые задания для самостоятельного выполнения от разных it компаний
Тестовые задания для самостоятельного выполнения от разных it компаний - Hexlet/ru-test-assignments
👍50🔥26❤9❤🔥1🤔1
Шаблоны проектирования
В разных стеках разное отношение к шаблонам проектирования. Где-то про них только и говорят, например, в Java. Там на собесе вас обязательно спросят про SOLID. Где-то себя противопоставляют шаблонам говоря, что они нам не нужны, мы же не Java. Существует даже такая фраза, что чем менее выразительный ваш язык, тем больше шаблонов проектирования в нем присутствует.
Шаблоны штука интересная, я посвятил много лет своей жизни ооп дизайну, но самое смешное, что больше всего шаблоны я понял именно тогда, когда начал заниматься фп. Стало понятна суть многих вещей. Поделюсь накопленной мудростью так сказать)
Большая часть шаблонов, которые описаны в известных книгах, посвящены конкретным кускам кода, а не архитектуре в целом. Честно говоря их влияние на систему не такое большое, как об этом принято думать или написано в этих же книгах, в отличии от архитектурных шаблонов типа MVC.
Какие проблемы они например решают? Вы возможно не поверите, но значительное количество шаблонов проектирования это всего лишь вариация на тему полиморфизма подтипов (или subtyping, не путать с параметрическим и ad-hoc полиморфизмами), когда у нас есть общий интерфейс (по смыслу, а не обязательно как конструкция) и разные реализации. Сюда входят: команда, стратегия, стейт, декоратор, прокси и адаптер. Если упрощать, то такой полиморфизм решает две задачи:
• Убирает ифы из кода. Да вот так вот просто.
• Позволяет управлять кодом через конфигурацию, когда мы не очередной иф вставляем или правим сам код где используется объект, а мы в конфигурации приложения меняем реализацию. В основном это делается в библиотеках, которые мы можем конфигурировать. На уровне приложений такое применяется там где есть контейнеры зависимостей, например, активно в php и java фреймворках. Редко в js, go, python, ruby.
Правильный взгляд на такие паттерны состоит в том, чтобы видеть именно задачу полиморфизма, в таком случае вы сможете использовать подходящее решение даже не зная паттерна. Но не надо забывать, что паттерн далеко не всегда решает проблемы, важно, чтобы он вводился только тогда, когда это выгоднее чем бахнуть обычный иф.
p.s. Часто ли вы используете паттерны?
p.s.s. Домашнее задание: Какой паттерн используется в ситуации, когда вы хотите иметь возможность подменить базу данных, в течении жизни приложения (например переехать с одной на другую) без изменения кода (в теории)
В разных стеках разное отношение к шаблонам проектирования. Где-то про них только и говорят, например, в Java. Там на собесе вас обязательно спросят про SOLID. Где-то себя противопоставляют шаблонам говоря, что они нам не нужны, мы же не Java. Существует даже такая фраза, что чем менее выразительный ваш язык, тем больше шаблонов проектирования в нем присутствует.
Шаблоны штука интересная, я посвятил много лет своей жизни ооп дизайну, но самое смешное, что больше всего шаблоны я понял именно тогда, когда начал заниматься фп. Стало понятна суть многих вещей. Поделюсь накопленной мудростью так сказать)
Большая часть шаблонов, которые описаны в известных книгах, посвящены конкретным кускам кода, а не архитектуре в целом. Честно говоря их влияние на систему не такое большое, как об этом принято думать или написано в этих же книгах, в отличии от архитектурных шаблонов типа MVC.
Какие проблемы они например решают? Вы возможно не поверите, но значительное количество шаблонов проектирования это всего лишь вариация на тему полиморфизма подтипов (или subtyping, не путать с параметрическим и ad-hoc полиморфизмами), когда у нас есть общий интерфейс (по смыслу, а не обязательно как конструкция) и разные реализации. Сюда входят: команда, стратегия, стейт, декоратор, прокси и адаптер. Если упрощать, то такой полиморфизм решает две задачи:
• Убирает ифы из кода. Да вот так вот просто.
• Позволяет управлять кодом через конфигурацию, когда мы не очередной иф вставляем или правим сам код где используется объект, а мы в конфигурации приложения меняем реализацию. В основном это делается в библиотеках, которые мы можем конфигурировать. На уровне приложений такое применяется там где есть контейнеры зависимостей, например, активно в php и java фреймворках. Редко в js, go, python, ruby.
Правильный взгляд на такие паттерны состоит в том, чтобы видеть именно задачу полиморфизма, в таком случае вы сможете использовать подходящее решение даже не зная паттерна. Но не надо забывать, что паттерн далеко не всегда решает проблемы, важно, чтобы он вводился только тогда, когда это выгоднее чем бахнуть обычный иф.
p.s. Часто ли вы используете паттерны?
p.s.s. Домашнее задание: Какой паттерн используется в ситуации, когда вы хотите иметь возможность подменить базу данных, в течении жизни приложения (например переехать с одной на другую) без изменения кода (в теории)
👍37🔥19❤8🤔1
План на ближайшие посты по шаблонам проектирования
Тема с шаблонами зашла, она как обычно вызывает разные чувства, но комментариев много и интерес есть. Я хочу сделать цикл прямо обучающих постов, в которых мы кое что разберем. Однако, сразу хочу обозначить. Это ни в коем случае не стандартное вот шаблон вот поехали. Мы попробуем разобраться со смысловой частью программирования, в которой появляются шаблоны с рассмотрением проблемы, альтернатив, плюсов минусов и так далее. И что важно, даже когда мы будем говорить про паттерны, мы не будем говорить про набор классов как это описано в большинстве мест, мы будем говорить про организацию кода, которая решает реальную проблему, не зависимо от того, на каком языке мы пишем. На выходе у вас должно появиться более четкое понимание проблем, которые вызывает сложный код и как это код можно упростить (или усложнить) разными решениями. Первый пост будет завтра, а тут немного комментариев на те комментарии, которые вы оставляли к посту:
> С тех пор как ушел на го, то сразу исчез этот мешок барахла в голове. Максимум на практике встречаются декораторы. Но у меня в конторе не фанатики писать код по книгам. Используем там где уместно, а уместно прям мало где. Но это в го.
Если смотреть в суть вещей, то проблемы, которые решают часть шаблонов (не все), являются языконезависимыми проблемами. Но даже к ним есть отторжение именно из-за постоянного навязывания и культа карго. Плюс на разных языках решают разные задачи, поэтому часть паттернов просто уходит автоматически. Например абстрактная фабрика это очень специфический паттерн, встречающийся в определенных задачах, которые решают полтора землекопа в мире (конечно чуть больше, но идея понятна).
> Неироничный вопрос: а чем программистов так пугают ифы? Ветвление - фундаментальная конструкция в языках программирования. А то иной раз вместо простого ифа два интерфейса, пять классов, абстрактная фабрика абстрактных синглтонов (утрировано). Так происходит от бездумного применения паттернов ради паттернов, потому что так написали в книжках умные дядьки. Простые вещи должны быть простыми.
Как раз в этом соль, когда понимание этой системы проблем, а за ними и шаблонов достаточно хорошее, то в каждой задаче достаточно легко ответить на вопрос, а нужно ли вообще что-то кроме ифов делать. В прикладном коде намного меньше чем кажется программистам. В библиотеках и фреймворках этого сильно больше, но их мало кто пишет.
> Интересно, кто-то на практике сталкивался с потребностью поменять базу во время жизни приложения?
У меня на практике разок было, но в первую очередь в ORM это сделано для того, чтобы какую бы вы базу не выбрали изначально, вам не пришлось бы как-то менять свои подходы в написании кода, по крайней мере в первое время.
> А в чем вообще разница между медиатором и адаптером?)
Поговорим) Однако тут надо идти от проблематики, в которых эти паттерны возникают.
p.s. Знаете ли вы что такое динамическая диспетчеризация и мультидиспетчеризация?
Тема с шаблонами зашла, она как обычно вызывает разные чувства, но комментариев много и интерес есть. Я хочу сделать цикл прямо обучающих постов, в которых мы кое что разберем. Однако, сразу хочу обозначить. Это ни в коем случае не стандартное вот шаблон вот поехали. Мы попробуем разобраться со смысловой частью программирования, в которой появляются шаблоны с рассмотрением проблемы, альтернатив, плюсов минусов и так далее. И что важно, даже когда мы будем говорить про паттерны, мы не будем говорить про набор классов как это описано в большинстве мест, мы будем говорить про организацию кода, которая решает реальную проблему, не зависимо от того, на каком языке мы пишем. На выходе у вас должно появиться более четкое понимание проблем, которые вызывает сложный код и как это код можно упростить (или усложнить) разными решениями. Первый пост будет завтра, а тут немного комментариев на те комментарии, которые вы оставляли к посту:
> С тех пор как ушел на го, то сразу исчез этот мешок барахла в голове. Максимум на практике встречаются декораторы. Но у меня в конторе не фанатики писать код по книгам. Используем там где уместно, а уместно прям мало где. Но это в го.
Если смотреть в суть вещей, то проблемы, которые решают часть шаблонов (не все), являются языконезависимыми проблемами. Но даже к ним есть отторжение именно из-за постоянного навязывания и культа карго. Плюс на разных языках решают разные задачи, поэтому часть паттернов просто уходит автоматически. Например абстрактная фабрика это очень специфический паттерн, встречающийся в определенных задачах, которые решают полтора землекопа в мире (конечно чуть больше, но идея понятна).
> Неироничный вопрос: а чем программистов так пугают ифы? Ветвление - фундаментальная конструкция в языках программирования. А то иной раз вместо простого ифа два интерфейса, пять классов, абстрактная фабрика абстрактных синглтонов (утрировано). Так происходит от бездумного применения паттернов ради паттернов, потому что так написали в книжках умные дядьки. Простые вещи должны быть простыми.
Как раз в этом соль, когда понимание этой системы проблем, а за ними и шаблонов достаточно хорошее, то в каждой задаче достаточно легко ответить на вопрос, а нужно ли вообще что-то кроме ифов делать. В прикладном коде намного меньше чем кажется программистам. В библиотеках и фреймворках этого сильно больше, но их мало кто пишет.
> Интересно, кто-то на практике сталкивался с потребностью поменять базу во время жизни приложения?
У меня на практике разок было, но в первую очередь в ORM это сделано для того, чтобы какую бы вы базу не выбрали изначально, вам не пришлось бы как-то менять свои подходы в написании кода, по крайней мере в первое время.
> А в чем вообще разница между медиатором и адаптером?)
Поговорим) Однако тут надо идти от проблематики, в которых эти паттерны возникают.
p.s. Знаете ли вы что такое динамическая диспетчеризация и мультидиспетчеризация?
❤39🔥20👍7🤩2🤔1👌1🤓1
Шаблоны проектирования: Синглотон
Начнем с чего-то наиболее простого, но наиболее известного. Синглотон, это объект, который создается ровно в одном экземпляре и за этим не надо следить, он сам за этим следит за счет того как его реализуют.
Эта идея кажется привлекательной только для тех, кто никогда с ними в коде не сталкивался. В реальности же, постоянно выясняется, что ситуаций где нужны разные объекты гораздо больше чем кажется. Сегодня была одна база данных, завтра мы подключимся к двум. Кроме того, в тестах почти всегда нужна возможность задавать любые объекты с нуля индивидуально, так как разные тесты как раз тестируют разные кейсы.
Фактически, синглотон больше используют там, где нужен доступ к объекту из совершенно разных мест приложения и не хочется его везде прокидывать. То есть с его помощью реализуют глобальную переменную, к которой есть доступ отовсюду. Подобный код говорит о двух вещах: в коде появляется много неявных зависимостей, которые особенно больно стреляют если объект имеет состояние и оно может меняться. В таком случае вы никогда не можете быть ни в чем уверенными, а в работающей программе будут появляться глюки. Ну и банально это говорит о том что абстракции текут по полной программе, раз мы работаем не через интерфейсы (не как конструкции, а по смыслу), а тянем такой объект напрямую во внутрь на любом уровне.
Но как это ни странно, все же есть разные экосистемы с разными порядками. Например эталонный пример где синглотоны никак не нужны и не используются почти никогда это spring (boot), так как там крутой контейнер зависимостей, который решает проблему доступа и управляет жизненным циклам объектов. В JavaScript, Python и Ruby подобные синглотоны встречаются, но в другой реализации. В JavaScript и Python иногда делают файлы, в которых формируются данные/объект, который может быть импортирован куда-то и этот объект инициализирован ровно один раз, так как сам файл интерпретируется только один раз. В Ruby такое принято и в самой Rails и в ее библиотеках, когда класс содержит статическое поле с объектом. Да это сильно упрощает написание кода (так как нет контейнера) и помогает новичкам, но иногда больно стреляет и если не следить за абстракциями, делает из кода кашу. Кстати поэтому в тестах на Ruby часто встречается такое когда синглотон меняют в начале теста и потом возвращают обратно в конце. Подобные хаки для синголотон встречаются и в других языках, я точно такое делал сам на php
Общий вывод такой. Синглотон лучше не использовать если есть возможность этого не делать, но в вашей экосистеме могут быть устоявшиеся каноны, которые лучше не нарушать или как минимум вы должны понимать последствия своих действий.
Про альтернативу синголотоном можно прочитать тут: https://en.wikipedia.org/wiki/Dependency_injection
p.s. Вы сталкивались с проблемами в использовании синглотонов?
Начнем с чего-то наиболее простого, но наиболее известного. Синглотон, это объект, который создается ровно в одном экземпляре и за этим не надо следить, он сам за этим следит за счет того как его реализуют.
public class Singleton {
// The volatile keyword ensures that multiple threads handle the uniqueInstance variable correctly when it is being initialized to the Singleton instance.
private static volatile Singleton uniqueInstance;
// private constructor so no one can instantiate the class from outside
private Singleton() {}
// Method to return an instance of the class
public static Singleton getInstance() {
// First check without locking to improve performance
if (uniqueInstance == null) {
// Locking the class object to only let one thread in to check and instantiate the singleton
synchronized (Singleton.class) {
// Double-check whether the instance is null or not to ensure that no two instances are created
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
// other useful methods here
}
Эта идея кажется привлекательной только для тех, кто никогда с ними в коде не сталкивался. В реальности же, постоянно выясняется, что ситуаций где нужны разные объекты гораздо больше чем кажется. Сегодня была одна база данных, завтра мы подключимся к двум. Кроме того, в тестах почти всегда нужна возможность задавать любые объекты с нуля индивидуально, так как разные тесты как раз тестируют разные кейсы.
Фактически, синглотон больше используют там, где нужен доступ к объекту из совершенно разных мест приложения и не хочется его везде прокидывать. То есть с его помощью реализуют глобальную переменную, к которой есть доступ отовсюду. Подобный код говорит о двух вещах: в коде появляется много неявных зависимостей, которые особенно больно стреляют если объект имеет состояние и оно может меняться. В таком случае вы никогда не можете быть ни в чем уверенными, а в работающей программе будут появляться глюки. Ну и банально это говорит о том что абстракции текут по полной программе, раз мы работаем не через интерфейсы (не как конструкции, а по смыслу), а тянем такой объект напрямую во внутрь на любом уровне.
Но как это ни странно, все же есть разные экосистемы с разными порядками. Например эталонный пример где синглотоны никак не нужны и не используются почти никогда это spring (boot), так как там крутой контейнер зависимостей, который решает проблему доступа и управляет жизненным циклам объектов. В JavaScript, Python и Ruby подобные синглотоны встречаются, но в другой реализации. В JavaScript и Python иногда делают файлы, в которых формируются данные/объект, который может быть импортирован куда-то и этот объект инициализирован ровно один раз, так как сам файл интерпретируется только один раз. В Ruby такое принято и в самой Rails и в ее библиотеках, когда класс содержит статическое поле с объектом. Да это сильно упрощает написание кода (так как нет контейнера) и помогает новичкам, но иногда больно стреляет и если не следить за абстракциями, делает из кода кашу. Кстати поэтому в тестах на Ruby часто встречается такое когда синглотон меняют в начале теста и потом возвращают обратно в конце. Подобные хаки для синголотон встречаются и в других языках, я точно такое делал сам на php
Общий вывод такой. Синглотон лучше не использовать если есть возможность этого не делать, но в вашей экосистеме могут быть устоявшиеся каноны, которые лучше не нарушать или как минимум вы должны понимать последствия своих действий.
Про альтернативу синголотоном можно прочитать тут: https://en.wikipedia.org/wiki/Dependency_injection
p.s. Вы сталкивались с проблемами в использовании синглотонов?
Wikipedia
Dependency injection
technique in software engineering
👍46✍9🫡9❤7
Шаблон проектирования: Команда
Паттерн, который как правило упоминают в контексте разделения логики представления и бизнес логики. Типичные кейсы:
⁃ В GUI интерфейсе есть разные способы сделать одно и тоже, например копирование текста (контекстное меню, комбинация клавиш, кнопка и т.п.). Очень много подобных вещей в гугл документах, например, для создания файлов, выделения и других операций.
⁃ В бекенде тоже есть представление, это вьюхи, которые формируются контроллерами, это api или cli интерфейс. Во всех этих местах вызываются какие-то бизнесовые сценарии и они легко могут повторяться.
Идея паттерна в том, что давайте не будем зашивать логику в то место, где оно используется, например в кнопку, а сделаем механизм, который позволит отделить саму кнопку, от того поведения, которое произойдет при ее нажатии. Соответственно у нас получается инверсия зависимости, сама по себе кнопка не делает ничего, она только передает управление, той команде, которой ее сконфигурировали. Так мы можем гибко менять поведение разных элементов интерфейса не создавая новые элементы на каждый чих, с другой стороны, мы можем одну и ту же операцию вызывать в разных местах без дублирования кода.
В случае Java это объект-команда.
В случае JS это обычная анонимная функция, которая вешается на событие. Собственно сам механизм реакции на события это и есть реализация паттерна команда.
Если посмотреть описание этого паттерна, то видно, что оно довольно сильно заточено под классовые языки. Там как преимущество говорится о том, что если сделать команду объектом, то ее можно использовать как данные, передавать куда-то, записывать и так далее. В языках где все нормально с функциями высшего порядка, такой проблемы нет. Поэтому и паттерн команда там реализуется настолько просто, что даже возникает вопрос “для этого нужен паттерн?”. Но по смыслу команда там есть, даже если код очень простой.
Чаще всего команда встречается в библиотеках и фреймворках и мы настолько привыкли к этому паттерну (особенно фротендеры и мобильщики), что даже не замечаем этого, считая команду чем-то само собой разумеющимся. Однако, когда доходит дело до написания своих библиотек, без четкого представления о том как устроен этот паттерн, могут происходить затупы, приводящие к херовым решениям. Но теперь вы знаете)
Кстати проверка на хорошее понимание ооп: Если вы видите, что команда это просто частный случай реализации полиморфизма подтипов (subtyping), то у вас отличный уровень владения предметом. Если нет, то по ооп нужно подкачать базу и мы этим займемся тоже
p.s. Вам приходилось реализовывать команду в своей практике?
Паттерн, который как правило упоминают в контексте разделения логики представления и бизнес логики. Типичные кейсы:
⁃ В GUI интерфейсе есть разные способы сделать одно и тоже, например копирование текста (контекстное меню, комбинация клавиш, кнопка и т.п.). Очень много подобных вещей в гугл документах, например, для создания файлов, выделения и других операций.
⁃ В бекенде тоже есть представление, это вьюхи, которые формируются контроллерами, это api или cli интерфейс. Во всех этих местах вызываются какие-то бизнесовые сценарии и они легко могут повторяться.
Идея паттерна в том, что давайте не будем зашивать логику в то место, где оно используется, например в кнопку, а сделаем механизм, который позволит отделить саму кнопку, от того поведения, которое произойдет при ее нажатии. Соответственно у нас получается инверсия зависимости, сама по себе кнопка не делает ничего, она только передает управление, той команде, которой ее сконфигурировали. Так мы можем гибко менять поведение разных элементов интерфейса не создавая новые элементы на каждый чих, с другой стороны, мы можем одну и ту же операцию вызывать в разных местах без дублирования кода.
В случае Java это объект-команда.
var button = new Button();
// У команды есть один интерфейсный метод execute()
var command = new CopyCommand();
button.setCommand(copy);
// Кнопка добавляется в интерфейс
В случае JS это обычная анонимная функция, которая вешается на событие. Собственно сам механизм реакции на события это и есть реализация паттерна команда.
const button = document.getElementById('myButton');
// Adding a click event listener to the button
button.addEventListener('click',() => {
// Тут может быть напрямую зашитая логика
// Если логика повторяется, то она может быть вынесена куда-то,
// а здесь только вызов
});
Если посмотреть описание этого паттерна, то видно, что оно довольно сильно заточено под классовые языки. Там как преимущество говорится о том, что если сделать команду объектом, то ее можно использовать как данные, передавать куда-то, записывать и так далее. В языках где все нормально с функциями высшего порядка, такой проблемы нет. Поэтому и паттерн команда там реализуется настолько просто, что даже возникает вопрос “для этого нужен паттерн?”. Но по смыслу команда там есть, даже если код очень простой.
Чаще всего команда встречается в библиотеках и фреймворках и мы настолько привыкли к этому паттерну (особенно фротендеры и мобильщики), что даже не замечаем этого, считая команду чем-то само собой разумеющимся. Однако, когда доходит дело до написания своих библиотек, без четкого представления о том как устроен этот паттерн, могут происходить затупы, приводящие к херовым решениям. Но теперь вы знаете)
Кстати проверка на хорошее понимание ооп: Если вы видите, что команда это просто частный случай реализации полиморфизма подтипов (subtyping), то у вас отличный уровень владения предметом. Если нет, то по ооп нужно подкачать базу и мы этим займемся тоже
p.s. Вам приходилось реализовывать команду в своей практике?
👍53✍6❤6🫡2❤🔥1🔥1👌1
Шаблон проектирования: Стратегия
Пожалуй один из самых полезных шаблонов, который связан с объективной сложностью задач программирования, а не ооп, красивым кодом и так далее.
Расскажу про него на примере задачи. Предположим, что у вас есть страница на сайте, на которой отображается список пользователей. В зависимости от того, кто смотрит на эту страницу, список может быть очень разным. Например по дефолту выводятся только активные за последние 10 дней, админ видит вообще всех с пейджингом, какой-нибудь менеджер смотрит активность за месяц, при этом видит только своих подчиненных и так далее.
Эту задачу логично начинать решать обычным набором ифов, которые проверяют тип пользователя и дальше формируют правильный запрос. В большинстве случаев для подобной задачи нам хватит, но если сложность выборки вырастет до определенного уровня за счет доп. условий и/или количества новых ролей, то анализировать такой код станет крайне затруднительно. Это связано с тем, что сложно вычленить конкретную роль и то что будет выведено для нее с одной стороны, а с другой, любое изменение потребует постоянного анализа “а как это скажется на остальных”. Вероятность ошибки тут крайне высокая и через такие решения проходил не мало в своей жизни, когда делаешь изменение для одной ветки, а ломаются другие.
Вся проблема заключается в большом количестве состояний системы, что косвенно показывает цикломатическая сложность (количество возможных путей программы, то есть веток в ифах).
Выпутаться из этой ситуации можно двумя способами. Первый это просто вынос кусков кода в отдельные функции, что как будто-бы уменьшает цикломатическую сложность основного кода. Но в данном случае это иллюзия, нам все равно надо понимать логику на всех уровнях, чтобы увидеть что произойдет для конкретной роли. Поэтому здесь лучше подойдет второй способ. Нужно изолировать логику составления запроса для каждой роли в свой собственный кусок кода, например функцию. Общее количество кода и ифов в таком случае вырастет, так как появится дублирование если некоторые роли хотят одного и того же. Но, с другой стороны, сложность логики под каждую конкретную роль значительно снизится. Станет и легко анализировать и легко править конкретный кейс не боясь сломать остальное. Итого здесь мы получаем баланс между сложностью и дублированием которым можно управлять.
Именно это называется стратегией. Как правило, стратегия это разделение логики вычисления на независимые блоки, по какому-то одному общему ключевому признаку. Выше это роль пользователя. В других ситуациях ключом может быть что-то совершенно другое.
p.s. Расскажите про свои ситуации, где стратегия помогала снизить сложность?
Пожалуй один из самых полезных шаблонов, который связан с объективной сложностью задач программирования, а не ооп, красивым кодом и так далее.
Расскажу про него на примере задачи. Предположим, что у вас есть страница на сайте, на которой отображается список пользователей. В зависимости от того, кто смотрит на эту страницу, список может быть очень разным. Например по дефолту выводятся только активные за последние 10 дней, админ видит вообще всех с пейджингом, какой-нибудь менеджер смотрит активность за месяц, при этом видит только своих подчиненных и так далее.
// ChatGPT
async function fetchUserData(userRole, userId = null) {
let queryOptions = {};
if (userRole === 'admin') {
// Admin gets access to all users
queryOptions = {};
} else if (userRole === 'user') {
// Regular user gets only their data
queryOptions = {
where: {
id: userId
}
};
}
try {
const users = await User.findAll(queryOptions);
console.log(users);
} catch (error) {
console.error('Error fetching user data:', error);
}
}
// Example usage
fetchUserData('admin'); // Fetches all users for admins
fetchUserData('user', 1); // Fetches data for user with id 1
Эту задачу логично начинать решать обычным набором ифов, которые проверяют тип пользователя и дальше формируют правильный запрос. В большинстве случаев для подобной задачи нам хватит, но если сложность выборки вырастет до определенного уровня за счет доп. условий и/или количества новых ролей, то анализировать такой код станет крайне затруднительно. Это связано с тем, что сложно вычленить конкретную роль и то что будет выведено для нее с одной стороны, а с другой, любое изменение потребует постоянного анализа “а как это скажется на остальных”. Вероятность ошибки тут крайне высокая и через такие решения проходил не мало в своей жизни, когда делаешь изменение для одной ветки, а ломаются другие.
Вся проблема заключается в большом количестве состояний системы, что косвенно показывает цикломатическая сложность (количество возможных путей программы, то есть веток в ифах).
Выпутаться из этой ситуации можно двумя способами. Первый это просто вынос кусков кода в отдельные функции, что как будто-бы уменьшает цикломатическую сложность основного кода. Но в данном случае это иллюзия, нам все равно надо понимать логику на всех уровнях, чтобы увидеть что произойдет для конкретной роли. Поэтому здесь лучше подойдет второй способ. Нужно изолировать логику составления запроса для каждой роли в свой собственный кусок кода, например функцию. Общее количество кода и ифов в таком случае вырастет, так как появится дублирование если некоторые роли хотят одного и того же. Но, с другой стороны, сложность логики под каждую конкретную роль значительно снизится. Станет и легко анализировать и легко править конкретный кейс не боясь сломать остальное. Итого здесь мы получаем баланс между сложностью и дублированием которым можно управлять.
Именно это называется стратегией. Как правило, стратегия это разделение логики вычисления на независимые блоки, по какому-то одному общему ключевому признаку. Выше это роль пользователя. В других ситуациях ключом может быть что-то совершенно другое.
p.s. Расскажите про свои ситуации, где стратегия помогала снизить сложность?
❤35👍20✍3🔥2👨💻2🫡1
PHP работы пост: Ищу Laravel-разработчика с фронтенд опытом на проектную работу для нашего колледжа https://mokevnin.notion.site/a62fc9b140df44609ee2b365d70f4e90?v=ecb6fa57cfe84022add265b6b574c2d1&p=a0195e34c32c4c6fb622662cdfe4b83a&pm=c стоимость проекта будет считаться исходя из 2000 руб/час, ориентировочно месяц на разработку, дедлайн 15 мая. Я соучаствую, помогаю с архитектурой, инфрой и ревью
Personal (Kirill Mokevnin) on Notion
Laravel-разработчик | Notion
Задача
🤔1