Найти тему
Закреплено автором
48:12
David Dobryakov
Основы работы с TypeScript — Бэкенд-разработка на Node.JS #3
186 · 2 года назад
Что я прочитал - не только ORM #чтояпрочитал #orm #бд Ссылка на оригинал: https://habr.com/ru/articles/818761/ Ссылка на гитхаб проекта: https://github.com/amaslyaev/noorm Кратко В статье автор описывает устройство ORM и основную, на его взгляд, проблему такого подхода — "персистетные объекты". И предлагает альтернативу в виде кастомной библиотеки, позволяющей работать с БД без использования персистетных объектов, при этом не засоряя основной код SQL-запросами. Выдержка про проблему персистентных объектов: Примечательно здесь то, что работа с базой данных идёт через персистентные объекты, являющиеся экземплярами «модельных» классов, описывающих структуру БД. Эти персистентные объекты умеют себя прочитать из базы и в неё себя записать. Они живут внутри открытой сессии. И ещё эти объекты умеют «лениво» дотягивать из базы связанные с ними другие персистентные объекты. Эти самые персистентные объекты — корень всех проблем: 1. По сути, это передача мутабельного объекта в другой процесс. Безобразно тупая затея. Мы запросили сущность «пользователь Вася» из базы данных в процесс своего бэкенда, и теперь где у нас теперь мастер-копия? Как мы их собираемся синхронизировать, в какой момент, и что собираемся делать с возможными коллизиями? 2. Что случается с живущими в сессии объектами когда сессия закрывается? Что если они продолжают быть нужны в логике приложения? Что если эта логика продолжает считать, что это по-прежнему нормальные объекты, принадлежащие живой сессии? 3. Невозможно найти единственно правильный баланс между eager- и lazy-загрузкой. Если увлекаемся lazy, получаем проблему N+1, и всё начинает страшно тормозить. Если увлекаемся eager, на каждый невинный чих ORM пытается вычитать полбазы, и тоже всё тормозит. Короче, у нас две педали, но обе они педали тормоза. Какой подход предлагает автор взамен? Выделение отдельного модуля с логикой БД и SQL-запросами, который может выглядеть примерно так: from dataclasses import dataclass import noorm.sqlite3 as nm @dataclass class DbUser: id: int username: str email: str @nm.sql_fetch_all(DbUser, "SELECT rowid AS id, username, email FROM users") def get_users(): pass Использование датакласса позволяет однозначно определить возвращаемую структуру данных и ограничить её тип, что может быть довольно полезно при использовании этой самой структуры. Кроме того, в подсказке в IDE будет выводиться весь набор её свойств. Выводы В целом, подход имеет место быть и я даже уже начал собирать небольшой пет-проект с использованием NoORM. В ближайшие дни будет несколько постов по этой теме. Подумываю о том, чтобы снять об этом даже полноценное видео (не о самом подходе, а скорее о пет-проекте).
9 месяцев назад
Небольшой оффтоп по теме быта, ищу рекомендаций Подумываю о покупке ультракороткофокусного проектора для домашнего просмотра фильмов и прочего видеоконтента. Знаю, что надо уделить внимание такому параметру, как яркость, чтобы можно было смотреть и не зашторивая комнату полностью. Примерно понимаю, какую диагональ хочу и чтобы было хотя бы FullHD, а лучше если 4K. Причём, интересует именно проектор. Интересовался ли кто-то темой? Можете посоветовать, где можно посмотреть/почитать? На ютубе обзоров крайне мало и в основном на бюджетные модели :(
9 месяцев назад
Скрепка в vscode. Мнения?
9 месяцев назад
Что я прочитал: "какие привычки освоить it-шнику, чтобы стать продуктивнее (или здоровее)?" #чтояпрочитал #продуктивность Ссылка на оригинал: https://habr.com/ru/articles/818923/ Кратко (полностью скопировано из самой статьи) Общий список привычек на ежедневную основу - Пространственные упражнения: особые упражнения для формирования настроя на день. - Принятие холодного душа: холодный душ / обтирания / умывания для поднятия общего тонуса и настроя на день. - Планирование следующего дня: планирование задач на следующий день в конце текущего. - Чтение: чтение художественной / профессиональной литературы. - Стакан воды с утра: выпивание стакана воды после пробуждения для увлажнения организма и стимуляции обмена веществ. - Ходьба / Бег: регулярные прогулки или бег для поддержания физической формы и энергии. - Сон по расписанию: соблюдение определенного режима сна, с учетом жизненных циклов организма и мира. - Медитация: медитирование для улучшения концентрации, снятия стресса и общего благополучия. В целом, со многими пунктами я согласен, но в статье мне не нравится, что на текст тут явно забили. Много помарок и само изложение хромает. На мой взгляд, точно будет работать: - планирование следующего дня: я, к примеру, планирую все свои дела раз в неделю, а в конце дня просто сверяюсь с планом; - чтение: меня пока что хватает только на ежедневное чтение разных статей и постов в тг, до книжек руки не доходят; - стакан воды с утра: от воды в любом случае хуже не будет, а с утра действительно может помочь лучше проснуться; - ходьба: именно ходьба, а не бег, потому что бег травмоопасен, а гулять на свежем воздухе — очень полезно; - сон по расписанию: в ноябре прошлого года я уже писал про режим, рад поделиться тем, что уже более 3 недель удерживаю прекрасный режим без особых трудностей и делаю это довольно аккуратно. Мне помогают два будильника с интервалом 1.5 часа друг от друга. Первый за 1.5 часа до момента, когда мне надо проснуться, а второй ровно в то время, когда надо проснуться. Плюсом к этому, я включил сценарий светового будильника и когда я просыпаюсь с утра, чтобы выключить второй будильник, — в комнате уже светло, помогает легко встать. Дополнительный пункт от меня: баланс между работой и жизнью (aka "work/life balance"). Я поставил себе чёткие рамки начала и окончания рабочего дня и это действительно помогает удерживаться от переработок и уменьшает энтропию. По остальным пунктам у меня есть сомнения. Как минимум, тот же холодный душ много кому противопоказан. Рекомендуют принимать контрастный, вместо холодного, да и то не более двух минут, чтобы не повлиять негативно на свой организм. Я пробовал принимать контрастный душ и выяснил, что летом он вообще не ощущается контрастным, а вот зимой — наоборот. В среднем, любой душ с утра положительно сказывается на настроении. Пространственные упражнения, как их называет автор, я лично не делаю. Зато делаю ежедневно утреннюю суставную разминку и вечернюю суставную разминку. Это во-первых позволяет снять напряжение в мышцах, а во-вторых тело не будет болеть так сильно, как могло бы, после целого дня за компьютером. Медитацию я не пробовал и пока не горю желанием. Жду кризиса среднего возраста. Некоторые мейнстримные привычки, типа той же медитации, меня немного отталкивают как раз-таки своей мейнстримностью.
9 месяцев назад
Комментарии в коде #дискуссия На днях, автор канала Cross Join опубликовал пост с рассуждениями на тему того, насколько в коде нужны комментарии. Основной проблемой он считает то, что комментарии будут терять свою актуальность по мере внесения изменений в код. Как возможную альтернативу, он предлагает писать более подробные сообщения к коммитам, поскольку они как раз привязаны к конкретным точкам во времени. На мой взгляд, комментарии нужны и полезны. Как минимум, следует использовать документирующие комментарии, которые в некоторых случаях (например, использование jsdoc), позволяют описать типы входных и выходных аргументов у функции, дополнить её общим описанием, что упрощает работу с вашим кодом. Но вероятнее всего, этот пример один из немногих, когда комментарии действительно полезны и необходимы. Существуют разные точки зрения на комментирование кода. Автор книги "Чистый код", к примеру, призывает писать код без комментариев, объясняя это тем, что каждый оставленный комментарий - это неудача и комментировать код стоит только в крайнем случае. Конечно, в идеале, код должен легко читаться и без комментариев. На мой взгляд, допустимы документирующие комментарии, а также ссылки на референсы. К примеру, если вы добавляете новую библиотеку и дописываете её конфигурацию в общий конфигурационный файл, можно сослаться на документацию этой библиотеки. Я же, в свою очередь, признаюсь, что очень люблю оставлять иногда комментарии даже в самых очевидных местах, потому что мне приходится на постоянной основе переключаться между несколькими проектами, а всего в голове удержать не удаётся. Поэтому скорость переключения контекста, в моём случае, повышается за счёт оставленных подсказок и напоминаний. А как вы подходите к написанию комментариев в коде?
9 месяцев назад
Библия systemd — как управлять системой Systemd — пожалуй, самая важная подсистема в Linux, без которой редко обходится развёртывание приложений на Linux-серверах. Даже, если вы используете только контейнеризованные сервисы в docker, вам может пригодиться systemd для настройки автоматического перезапуска контейнеров после перезагрзузки. Пару дней назад, на хабре вышла объёмная статья, в которой вся работа systemd раскрывается во всех подробностях. Мои знания по работе с systemd ограничивались способностью написать простенький сервис, например такой: [Unit] Description=Echo server After=multi-user.target Conflicts=getty@tty1.service [Service] Type=simple ExecStart=/usr/bin/python3 -m flask -A main.py run --host 0.0.0.0 --port 80 WorkingDirectory=/var/www/apps Restart=always User=root Group=root [Install] WantedBy=multi-user.target И не могу сказать, что вам нужно знать сильно больше. Но отмечу, что статья помогла мне расставить точки над ё во многих моментах. Рекомендую. https://habr.com/ru/articles/817701/
10 месяцев назад
👩‍💻 Компонент для номера телефона #frontend #react Около месяца назад я писал пост про библиотеку imask, чтобы стандартизировать ввод номера телефона, с помощью использования маски. Тогда же я упомянул, что основным минусом, на мой взгляд, является то, что нужно написать много дополнительного кода, чтобы достичь желаемого результата. Пару недель назад я как раз столкнулся с подобной задачей в рамках проекта на react и захотел попробовать реализовать это с помощью imask, но столкнулся с проблемой: нужно отображать список стран, с привязанным к ним кодом. В imask есть возможность решить это, но нет готового набора кодов номеров телефонов. Я вспомнил о решении, которое мои сотрудники находили. Попробовал его адаптировать и понял, что я особо не могу его кастомизировать (по дизайну требовалось выводить двухбуквенное название страны, а не флаг), несмотря на его описание, — "Advanced, highly customizable phone input component for Ant Design." Поняв, что нахожусь в сложной ситуации, я пошёл искать библиотеки, которые предоставляют просто список телефонных кодов по странам, чтобы реализовать это с помощью imask и нашёл такое решение. По сути, это простая библиотечка, которая возвращает нам объект из пар ключ-значение в том формате, в котором нам необходимо. Казалось бы, всё замечательно. Можно брать динамически маски в imask, генерировать их с помощью этих самых кодов и идти спокойно пить чай. Но в этот момент я осознал, что у разных стран, буквально, могут быть разные маски для ввода номера телефона и это окончательно закопало мою прекрасную идею об использовании imask для решения этой задачи. Пример с самого сайта imask, где наглядно видно, что маски вообще не подчиняются единым правилам и могут выглядеть абсолютно как угодно: [ { mask: '+00 {21} 0 000 0000', startsWith: '30', lazy: false, country: 'Greece' }, { mask: '+0 000 000-00-00', startsWith: '7', lazy: false, country: 'Russia' }, { mask: '+00-0000-000000', startsWith: '91', lazy: false, country: 'India' }, { mask: '0000000000000', startsWith: '', country: 'unknown' } ]
1 год назад
👩‍💻 Компонент для номера телефона (продолжение) #frontend #react Ресёрч пришлось продолжать. Я нашёл библиотеку, которая позволяла валидировать номер телефона относительно двухбуквенного кода страны, к которой этот номер относится. Кроме прочего, в этой библиотеке есть и возможность форматирования номера телефона, как раз под маску, принятую в конкретной стране. В описании библиотеки также упоминался react-компонент, который использует эту самую библиотеку. И на основе уже этого компонента, я собрал своё решение с использованием ant-design (разумеется, оно не идеальное, но достаточно хорошее, чтобы использовать в условном продакшне): import PhoneInput from 'react-phone-number-input'; import PropTypes from 'prop-types'; import { getCountries } from 'react-phone-number-input'; import { Select as AntdSelect } from 'antd'; const phoneCountryLabels = () => { const countryLabels = {}; getCountries().forEach((country) => (countryLabels[country] = country)); return countryLabels; }; const CountrySelect = ({ value, onChange, labels, variant = 'filled', ...rest }) => ( <AntdSelect {...rest} value={value} showSearch optionFilterProp="label" onChange={onChange} variant={variant} size="large" style={{ '--ant-select-single-item-height-lg': '3rem' }} /> ); CountrySelect.propTypes = { value: PropTypes.string, onChange: PropTypes.func.isRequired, labels: PropTypes.objectOf(PropTypes.string).isRequired, variant: PropTypes.string, }; const PhoneNumberInput = ({ onChange, country = 'US' }) => { return ( <div className="base-phone-number"> <PhoneInput onChange={onChange} defaultCountry={country} international limitMaxLength labels={phoneCountryLabels()} countrySelectComponent={CountrySelect} numberInputProps={{ className: 'ant-input ant-input-filled css-var-r1 ant-input-css-var base-input', }} /> </div> ); }; PhoneNumberInput.propTypes = { onChange: PropTypes.func.isRequired, country: PropTypes.string, }; export default PhoneNumberInput; А как вы решали подобные задачи? Делитесь, будет интересно узнать. P. S. как появится немного времени, планирую тоже самое адаптировать под vue-компонент и поделиться результатом
1 год назад
👩‍💻 Что нужно знать python backend developer для устройства на работу #django #python #backend #fastapi Пару лет назад я уже писал подобный пост. Тогда он был основан на моём личном опыте в найме (текущий, в общем-то тоже), пришло время актуализировать список. Если считаете, что я что-то упустил, то жду ваших предложений в комментариях. 👩‍💻 Фреймворки: - Django (+ DRF), - FastAPI/Flask (+ alembic, sqlalchemy). 👩‍💻 Базы данных: - redis, - postgresql. 👩‍💻 Основы: - HTTP-протокол, HTTP-методы, - что такое REST, REST API, RESTful, - что такое CORS и как его победить, - linux/unix на уровне понимания работы по SSH, права доступа, - понимание концепции MVC и принципа работы паттерна репозиторий (больше нужен для работы с SQLAlchemy), - вопросы для подготовки к интервью (список там довольно большой, обращайте внимание на те моменты, по которым вы совсем ничего не знаете). 👩‍💻 Что нужно знать в django: Обязательно: - работа с django ORM: https://docs.djangoproject.com/en/5.0/topics/db/queries/, - миграции в django ORM: https://docs.djangoproject.com/en/5.0/topics/migrations/, - менеджеры моделей: https://docs.djangoproject.com/en/5.0/topics/db/managers/, - сериализаторы, представления и права доступа из DRF: https://www.django-rest-framework.org/tutorial/quickstart/, - работа с фильтрами через django-filter: https://django-filter.readthedocs.io/en/stable/guide/usage.html. Опционально: - формы: https://docs.djangoproject.com/en/5.0/ref/forms/, - admin actions: https://docs.djangoproject.com/en/5.0/ref/contrib/admin/actions/, - оптимизация запросов в Django ORM: https://t.me/davidobryakov/1195, - отправка почтовых уведомлений: https://docs.djangoproject.com/en/5.0/topics/email/. На уровне концепции: - работа с админкой: https://docs.djangoproject.com/en/5.0/ref/contrib/admin/, - сигналы: https://docs.djangoproject.com/en/5.0/topics/signals/. Полезные библиотеки и ссылки для django: - библиотека для установки настроек CORS: https://github.com/adamchainz/django-cors-headers, - библиотека для авторизации и регистрации через DRF: https://djoser.readthedocs.io/en/latest/, - библиотека для создания динамической конфигурации приложения, хранимой в БД: https://django-constance.readthedocs.io/en/latest/, - библиотека, добавляющая хуки жизненного цикла для моделей Django: https://rsinger86.github.io/django-lifecycle/, - библиотека, предоставляющая кастомную админку с большим количеством настроек: https://django-jazzmin.readthedocs.io/, - практические советы для начинающих Django-разработчиков: https://t.me/davidobryakov/1184, - подборка лучших библиотек для Django: https://t.me/davidobryakov/1139, - курс по Django на MDN: https://developer.mozilla.org/ru/docs/Learn/Server-side/Django, - мой шаблон для Django-проектов: https://github.com/kantegory/django-template. - работа с ORM SQLAlchemy: https://docs.sqlalchemy.org/en/20/intro.html, - работа с alembic: https://alembic.sqlalchemy.org/en/latest/, - понимание async/await: https://docs.python.org/3/library/asyncio-task.html. 👩‍💻 Что нужно знать/уметь в FastAPI/Flask: - не поместилось по лимиту в ТГ, читайте полную версию поста в блоге. Общие требования: - работа с очередями задач с помощью Celery + Redis/Celery + RabbitMQ (выполнение периодических или отложенных задач, например, отправка электронной почты); - настройка общения между сервисами посредством RabbitMQ 👩‍💻 Инструменты: - git (тренажёр: https://learngitbranching.js.org/?locale=ru_RU), - docker, docker compose (на уровне: могу прочесть конфиг, могу запустить проект, могу написать свой простой конфиг), - gunicorn/uvicorn (иметь представление о том что это и для чего используется), - nginx (понимание на уровне директив location и upstream).
1 год назад
👩‍💻 Браузерные ОС #браузеры #linux #wasm На одной из прошлых работ гендиректор сказал мне, что считает, что операционные системы со временем перетекут в браузер, в качестве аргумента он упомянул Electron, который является базой для большого числа современных десктоп-приложений. Я запомнил это, но не придавал значения его словам, хотя они с каждым днём всё ближе к реальности. Пару лет назад я писал про WebVM, который представляет из себя linux без графической оболочки, работающий через WASM. Пару недель назад видел несколько постов про InternetOS puter. По сути, она представляет из себя графическую оболочку рабочего стола, работающую на веб-технологиях (js + jQuery). В отличие от WebVM, puter это только GUI, операции происходят на сервере (заметно, что на каждое действие, отправляется запрос в API). Документации для API-сервера пока что нет. Его исходного кода мне также не удалось найти (допускаю, что плохо искал, хотя и заглянул в каждый репозиторий). Разработчики обещают опубликовать документацию по API-серверу к концу марта, чего я буду ждать с нетерпением. Как вы думаете, есть ли будущее у браузерных операционных систем? Смогут ли они со временем стать заменой привычным десктопным оболочкам? Мне кажется, что определённый тренд в этом направлении есть и во многом это происходит уже сегодня, правда в облачном гейминге. Количество сервисов, предоставляющих подобную услугу, уже довольно большое, значит, это находит некий отклик среди аудитории. Думаю, в ближайшие годы мы будем наблюдать всё больше развития в этой сфере.
1 год назад
👩‍💻 Вычисляемые свойства во Vue сломаны? #frontend #vue #производительность На reddit наткнулся на пост в комьюнити Vue.JS с описанием проблемы с производительностью у вычисляемых свойств (computed). Заключается проблема в том, что судя по тестам использованием watch + ref на 50% более эффективно, чем использованием computed. Добавим немного контекста. Тест проводился на дропдауне с 1 000 000 элементов. Задача теста состояла в том, чтобы написать функцию, которая будет конвертировать объекты (или строки) с типом selectOption в объект selectOptionsObject. Типы выглядят так: export type selectOption = selectOptionObject | string; export type selectOptionObject = { id: string | number; render: string; raw?: any; }; Код функции normaliseOptions для конвертации: const normaliseOptions = ( options?: selectOption[] ): normalisedOptionObject[] => { if (!options) return []; // We will use a straight for loop for performance const normalisedOptions = []; for (let i = 0; i < options.length; i++) { const option = options[i]; if (typeof option === "string") { normalisedOptions.push({ id: option, render: option, }); continue; } normalisedOptions.push({ id: option.id.toString(), render: option.render, disabled: option.disabled || false, raw: option.raw, }); } return normalisedOptions; }; Код, который использовался в тесте: 1) С использованием computed: const normalisedOptions = computed(() => { return normaliseOptions(props.options); }); 2) С использованием watch + ref: // Using the pattern below rather than a computed value gives us a 2x performance improvement const normalisedOptions = ref(normaliseOptions(props.options)); const recomputeOptions = () => { normalisedOptions.value = normaliseOptions(props.options); }; watch( () => props.options, () => { recomputeOptions(); } ); Самые умные и опытные уже догадались, в чём может заключаться проблема конкретно в данном случае (а я не успел самостоятельно подумать и наткнулся на ответ в комментариях). Проблема заключается в том, что computed отслеживает каждую вложенную зависимость. Поэтому он будет работать медленнее, если props.options не является плоской структурой, состоящей из примитивов, потому что требуется провести кратно больше вычислений. Таким образом, корректный код для данного случая выглядит так: const recomputedOptions = computed(() => normaliseOptions(toRaw(props.options))); Метод toRaw извлекает необработанный объект из proxy-объекта, созданного Vue, давая нам возможность поработать с оригинальным объектом. Подробнее про него можно почитать в документации.
1 год назад
Маска для номера телефона #frontend #браузеры #стандартизация Проблема стандартизации форматирования и валидации поля ввода номера телефона абсолютно не новая. Даже в MDN говорят о том, что <input type="tel"> в отличие от <input type="email"> не имеет никакой автоматической валидации, потому что "форматы телефонных номеров сильно раличаются по всему миру". Решение, которое мы можем без труда соорудить стандартными средствами браузера, не используя дополнительных библиотек выглядит примерно так: <div> <input type="tel" pattern="(^8|7|\+7)([0-9]{10})" required > </div> <div> <small>Формат: +79999999999</small> </div> С таким решением мы будем строго принимать один обозначенный формат (пример сильно упрощён, более комплексный вариант регулярного выражения можно подглядеть тут) с общей подсказкой для пользователя, без маски для ввода. Как давно вы в последний раз видели поле ввода для номера телефона без маски? Можно долго дискутировать о том, нужна ли маска для ввода в данном случае, но пользователи уже к этому привыкли и вы явно их не отучите, только добавите неудобств. Вернёмся к основной теме. Без добавления JS-кода маску мы не получим. Можно поискать готовое решение, но с этим тоже есть проблема. Решения, которые сразу будут хорошо работать из коробки найти сложно. Довольно часто, многие из этих решений уже содержат в себе стилизацию, которую не всегда легко переделать под нужный дизайн. На мой взгляд, всё, что должно быть в хорошем решении подобной задачи: 1) возможность управления паттерном форматирования, валидации; 2) отсутствие лишних зависимостей и любой стилизации, она должна поступать извне, либо легко кастомизироваться; 3) интернационализация. Почти идеальным решением, на мой взгляд, является imask. Он предоставляет только функциональную часть с очень простыми API. К примеру, для российского номера телефона код будет выглядеть так: IMask( document.getElementById('phone-mask'), { mask: '+{7}(000)000-00-00' } ) Кроме прочего, решение имеет адаптацию под популярные веб-фреймворки (react, vue, angular, svelte) и даже неплохой задел на интернационализацию за счёт использования динамических масок. Пожалуй, единственным минусом этого решения является необходимость написания большого количества кода для более тонкой настройки. С другой стороны, это даёт возможность широкой кастомизации и позволяет менять паттерны и маски так, как вам требуется, не отнимая возможности стилизовать свои поля ввода так, как вы считаете нужным.
1 год назад