Битмап / словарь разработчика
510 subscribers
71 photos
1 video
71 links
Всё, что должен знать настоящий сеньор — короткие, но ёмкие заметки о разработке, инструментах, практиках, бизнесе. Выходят каждый день. Подписывайся!
加入频道
iCalendar — стандартизированный в RFC 5545 формат описания календарных данных:

📅 встречи и их настройки
📝 задачи
🔔 напоминания
🌴 выходные, отпуска и т.п.

Это текстовый формат, который используется в Google и Apple Calendar, MS Outlook, для импорта/экспорта и обмена календрными событиями, а также в их API.

📝 К примеру, так задаётся день рождения одного из моих друзей:
BEGIN:VEVENT
DTSTART;TZID=Europe/London:20240602T080000
DTEND;TZID=Europe/London:20240602T090000
RRULE:FREQ=YEARLY
DTSTAMP:20240901T133201Z
UID:[email protected]
CREATED:20240602T195932Z
LAST-MODIFIED:20240602T195932Z
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:День рождения друга
TRANSP:OPAQUE
END:VEVENT

Обратите внимание на RRULE, который задаёт частоту повторения.

Кроме RRULE есть также RDATE для указания списка дат, а таже EXRULE и EXDATE для задания исключений.

Именно их мы используем, создавая повторяющиеся события даже в интерфейсе гугл-календаря.

🔗 https://datatracker.ietf.org/doc/html/rfc5545
👍113
— Давай, разработчик, скажи это снова.
— Всё почти готово.
— Будет в проде через 2 дня 🤣
😁10
ngrok — это утилита, которая позволяет создавать HTTPS- или TCP/TLS-тоннели до локального компьютера.

Например, вы запускаете ngrok http 8080 и получаете публичный URL вида https://5bda-92-236-115-181.ngrok-free.app/, который доступен кому угодно в интернете.

Это подходит для тестирования локальных версий веб-сервисов без выкладки их куда-либо.

🚀 Плюсы: ngrok удобный, не требует настройки, существует в бесплатной версии.

🚫 Минусы: бесплатная версия сильно ограничена, тоннели регулярно отваливаются, а также очень неудобно, что каждый тоннель сначала нужно подтвердить через веб, прежде чем им можно пользоваться.

Мне лично больше нравится Cloudflare Tunnels, которые работают через cloudflared.

📝 Создание тоннелей выглядит практически идентично ngrok:
cloudflared tunnel --url http://localhost:8080

Их также можно прикрепить к поддомену, чтобы получить постоянный URL. Только не оставляйте такой тоннель открытым надолго 🤭

🔗 https://ngrok.com/docs
👍15
Поэтапные, или пошаговые Docker-сборки ускоряют процесс и делают финальные образы меньше.

Плюсы: явное разбиение на этапы позволяет сохранить артефакты сборки в отдельном образе.

Потенциально улучшается и безопасность — в финальные образы попадают только явно выбранные и необходимые файлы.

👎 Минусы: чуть-чуть дольше, сложнее в настройке, особенно если проект использует какие-то глобальные, недоступные в урезанном образе зависимости — например, imagemagick.

📖 Допустим, вы собираете Node-приложение и разбиваете Dockerfile на части:
FROM node:22 AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:22-alpine
WORKDIR /app
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/build ./build
CMD ["node", "build/index.js"]

Обратите внимание на AS build, а также явное копирование из этого слоя в компактный alpine-образ.

🔗 https://docs.docker.com/develop/develop-images/multistage-build/
👍51🤔1
Интерактивный ребейз — мощная штука, которая позволяет:

squash — совместить несколько комитов
drop — исключить из истории
edit — отредактировать сообщение и т.д.

В отличие от обычного git commit --amend, с помощью git rebase -i можно изменить любой коммит.

🫣 Коммиты в git неизменяемые, поэтому даже небольшое изменение истории потребует делать форс-пуши: git push --force, а лучше git push --force-with-lease.

Это не порадует ваших коллег, а также, как и любой rebase, может привести к длинному циклу исправления конфликтов.

👌 Я обычно использую git rebase -i в feature-ветках, чтобы сделать историю комитов более логичной и удобной для восприятия.

В качестве альтернативы можно использовать squash & merge в пул-реквестах на GitHub, если вы им пользуетесь.

📖 К примеру, чтобы изменить последние 3 коммита, используйте:
git rebase -i HEAD~3

Обратите внимание, что коммиты перечислены в обратном порядке.

🔗 https://git-scm.com/book/ru/v2/Инструменты-Git-Перезапись-истории#r_changing_multiple
🔥9👍1
ARPANET — это компьютерная сеть, которая была запущена 29 октября 1969 года между 3 университетами в Калифорнии (UCLA, UCSB и Stanford) и университетом штата Юта.

Первым сообщением, доставленным через сеть, стало lo (часть слова login), но после этого передача оборвалась 😁

Его отправили с компьютера в UCLA (университет в Лос-Анджелесе) на компьютер в Menlo Park в Stanford.

Разработка велась в течение 1960-х годов подразделением экспериментальных проектов DARPA (Defense Advanced Research Projects Agency) американского министерства обороны.

📝 Посмотрите видео, в котором профессор UCLA показывает ARPANET-свитч в корпусе "миникомпьютера" Honeywell DDP-516, с которого было отправлено первое сообщение 👇

🔗 https://www.youtube.com/watch?v=yU9oMOcRsuE
👏7
🌟 Посты прошедшей недели:

- Спагетти-код
- Amazon S3
- CORS
- CSP
- CAC
- Retention
- Canary
- RPC
- iCalendar
- ngrok
- Поэтапные Docker-сборки
- git rebase -i
- ARPANET

👀 А вам что понравилось?
👍8
Задача двух генералов — мысленный эксперимент о синхронизации состояния 2 систем, соединённых ненадёжным каналом связи.

⚔️ Суть: два генерала подвели армии к вражескому городу и договариваются об атаке.

Они находятся с разных сторон от него вне прямой видимости, поэтому отправляют сообщения с посыльными.

☠️ Посыльных может перехватить враг, а значит гарантии доставки сообщения нет.

📚 Представьте, что военачальник Скобелев пишет генералу Драгомирову:

С: атакуем на рассвете 9 сентября.

С не уверен, что его посыльный доставил сообщение. Атаковать без поддержки армии Д рискованно, поэтому он ждёт подтвеждения от Д.

Д знает, что без его подтверждения С может не решиться на атаку, и отправляет подтверждение:

Д: подтверждаю атаку 9 сентября на рассвете.

Но и этого посыльного могут поймать, и генералы не смогут скоординировать атаку.

Получается, невозможно гарантировать доставку 100% сообщений и полный консенсус через ненадёжный канал связи.

🔗 https://ru.wikipedia.org/wiki/Задача_двух_генералов
👍7🔥1
Сериализация — преобразование структуры данных или объекта в памяти в последовательность байт.

🚨 Важно, что сериализованный объект можно восстановить без потерь с помощью десериализации (парсинга).

Сериализация происходит в момент передачи данных между сервисами в сети, перед сохранением объекта в БД или на диск.

🔗 Распространнёные форматы сериализации: JSON и YAML, XML, protobuf.

📚 Например, словарь в python превращается в JSON:
import json

c = {
'handle': '@bitmap18',
'subscribers': 10000,
}

print(json.dumps(c))
# {"handle": "@bitmap18", "subscribers": 10000}

⚠️ Ещё одно важное свойство сериализации: переносимость формата.

JSON, XML, protobuf и другие форматы стандартизированы. Их понимают сотни разных систем и языков программирования.

А вот, скажем, у PHP свой формат сериализации массивов, не являющийся кросс-платформенным.

Также не является переносимой наивная сериализация C-структур на диск в бинарном формате — хоть она и очень компактная.

🔗 https://ru.wikipedia.org/wiki/Сериализация
👍8
Парное программирование — это когда два программиста работают за одним компьютером.

Один пишет код, а другой наблюдает, предлагает улучшения и подмечает ошибки. Через полчаса-час они меняются ролями.

Плюсы: улучшение качества кода, обмен знаниями, повышение сплочённости команды.

⛔️ Минусы: требует больше времени и ресурсов, может быть утомительным для участников.

Практика была предложена Кентом Беком, автором экстремального программирования.

🔍 Представьте, что вы новоиспечённый тимлид в команде разработки партнёрского кода Рекламной сети Яндекса.

Чтобы освоиться в новом проекте, вы выделяете время по утрам для парного программирования с разработчиками из команды.

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

* Это не выдуманная история, а моя личная, из практики. Ваня, привет, если ты вдруг это читаешь! 😁

🔗 https://ru.wikipedia.org/wiki/Парное_программирование
😁15
Пост-знакомство

Меня зовут Олег Громов, и я приветствую тебя на канале Битмап!

🦸‍♂️ Я — человек-оркестр. Люблю проектировать и создавать полезные системы от начала и до конца. Мне неплохо даётся дизайн, написание текстов, маркетинговые активности и анализ их результатов. Умею нанимать и организовывать работу команды так, чтобы важные цели достигались, а людям было хорошо.

📝 Немного фактов обо мне
• Я тимлид команды AI tools и бэкендер в edtech-стартапе Oneday
• Живу в Лондоне, у меня Global Talent виза. Долго жил в Москве, гостил в Штатах и Швеции по полгода
• 3 года тимлидил в Яндексе в Рекламной сети, почти 2 года — в Toptal
• Провёл 200-250 собеседований разработчиков, немного дизайнеров и менеджеров. Сам прошёл (или провалил) порядка сотни
• Посмотрел на зарубежные бигтехи (Фейсбук, Klarna) и стартапы (Sourcegraph, Hook и пр.) изнутри
• Написал популярные статьи про удалёнку за доллары
• Запускаю разные сайд-проекты, включая этот канал

🔗 У меня есть сайт, линкедин, а также личный канал. А вот ссылки на мои перфомансы в интернете на русском и на английском.

❤️ Я даю платные личные консультации:
• развитие хард- и софт-скиллов, код-ревью
• планирование карьеры и релокация
• сайд-проекты

🏢 И для компаний:
• аудит веб-приложений, сайтов и их производительности
• аудит состояния кодовой базы
• помощь в настройке командных процессов и найма
• проведение собеседований
• создание и поддержка MVP

Записаться по ссылке: https://forms.gle/MyqcJCxZ6Phhzzi47
🔥11😁21
Поиск в глубину (DFS) — алгоритм обхода графов и деревьев.

Начинает с корневого узла и двигается как можно глубже по каждой ветке. Потом возвращается назад и продолжает в ширину.

DFS применяют для поиска пути и циклов в графах, в топологической сортировке (например, для построения графа зависимостей).

Сложность по времени: O(V + E).
💾 По памяти: O(V).

V — количество вершин, E — количество рёбер.

🔥 Плюсы: просто реализовать, особенно рекурсивную версию. Работает на направленных и ненаправленных графах.

⛔️ Минусы: не всегда находит кратчайший путь.

📝 Пример реализации для графа в виде списка смежности:
def dfs(graph, start, visited=None):
visited = visited or set()
visited.add(start)

print(start)

for next in graph[start] - visited:
dfs(graph, next, visited)
return visited

graph = {
'A': {'B', 'C'},
'B': {'A', 'D', 'E'},
'C': {'A', 'F'},
'D': {'B'},
'E': {'B', 'F'},
'F': {'C', 'E'}
}
dfs(graph, 'A')


🔗 https://ru.wikipedia.org/wiki/Поиск_в_глубину
👍6
Lean startup — способ работы над стартапом, когда команда проходит следующий цикл, пока не найдёт работающий продукт:

1️⃣ выдвинули измеримую гипотезу, обновили продукт
2️⃣ запустили обновлённый MVP, показали пользователям, измерили результаты
3️⃣ сделали выводы и вернулись в п.1

Методология была предложена и популяризована с выходом одноимённой книжки Eric Ries в 2011 году.

🚀 Плюсы: ускоряет вывод продукта на рынок. Поощряет регулярный сбор обратной связи от клиентов.

😞 Минусы: MVP могут не давать достаточно ценности клиентам. В череде пивотов легко потерять стратегию и видение (vision).

Важно уметь привлекать пользователей и трафик по доступной цене, чтобы собирать полезную ОС на каждой итерации.

📝 Например, Dropbox творчески использовали этот подход, чтобы подтвердить спрос на свой продукт.

Команде было сложно построить даже едва работающий прототип, поэтому они записали видео-демо — и за ночь привлекли 70 тысяч человек в список ожидания.

🔗 https://ru.wikipedia.org/wiki/Бережливый_стартап
👍3
— Какой XML-парсер лучший?
— rm your-file.xml

😂
😁16👍3🤔1
С праздником, коллеги! 🎉
🎉15
Same-origin policy (SOP) — механизм безопасности в браузерах, который частично запрещает обмен данными между разными origin.

Origin — это комбинация (protocol, hostname, port). Например, evil.com и bank.ru — разные origin, т.к. у них разный домен.

📚 Допустим, вы залогинились в bank.ru, а потом открыли evil.com. Его владелец вставил следующий скрипт:
fetch('http://bank.ru/transfer?amount=100000&to=<evil_account>', {method: 'POST'})

Если бы не SOP, браузер сделал бы этот запрос, отправив вместе с ним cookies, а значит потенциально выполнил бы запрос на перевод денег от вашего лица.

⚠️ Кроме этого, SOP также запрещает читать чужие cookies из JS, получать доступ к window и прочим внутренностям чужих сайтов, вставленных в iframe и кучу других мелочей.

SOP появился в Netscape Navigator 2 вместе с первой версией JavaScript ещё в 1995 году.

А уже спустя много лет появился CORS, Cross-origin Resource Sharing, который позволяет обойти SOP.

🔗 https://developer.mozilla.org/ru/docs/Web/Security/Same-origin_policy
🔥14👍2
JSON5 — это расширение формата JSON, которое поддерживает:

• комментарии /* */ и //
• висячие запятые в массивах и объектах: [1,2,]
• строки в одинарных кавычках: 'bitmap'
• ключи без кавычек, если это валидные JS-идентификаторы
• перенос строк с помощью \ в конце строки вместо \n
• 16-ричные числа: 0xCOFFEE
• пропущенный ноль в десятичных дробях: .41468
• плюс в положительных числах +3.14
Infinity, -Infinity и NaN, как в IEEE 754

Для поддержки JSON5 нужны сторонние библиотеки, например, json5 для node или json5 для python.

Несмотря на более удобный синтаксис, JSON5 нечасто встречается в дикой природе, а некоторые и вовсе относятся к нему крайне скептически.

📝 Так выглядит пример JSON5:
{
// видали, как можно
bitmap18: 'твой любимый "cловарик"'
yo: "Привет! \
Уже рассказал друзьям о @bitmap18?",
i_love: 0xCOFFEE,
syntax_sugar: [.41468, +1, ],
}


🔗 https://json5.org/
👍9😁3🤔1
Пятница! Наработались уже? 🙃
Кидаем мемы в коменты!
😁9
SELECT FOR UPDATE — способ избежать состояния гонки (race condition) и взаимных блокировок в UPDATE, исполняющихся одновременною

Поддерживается в Postgres, MySQL c InnoDB, Oracle.

📚 Например, пользователь покупает товары 1 и 4 в интернет магазине, и нам надо обновить остатки в БД:
BEGIN;

SELECT *
FROM product_qty
WHERE product_id IN (1,4)
ORDER BY product_id
FOR UPDATE;

UPDATE product_qty
SET qty = qty - 1
WHERE product_id IN (1,4);

COMMIT;

🎯 Как это работает:

1️⃣ начинаем транзакцию

2️⃣ делаем SELECT ... FOR UPDATE: обновляем несколько строк, значит нужно использовать ORDER BY

3️⃣ дальше обычный UPDATE

4️⃣ наконец, COMMIT, чтобы завершить транзакцию и снять блокировки

Без ORDER BY в п.2 одновремено исполняющиеся транзакции могут попытаться взять блокировки в разном порядке, что может привести к дедлоку.

⚠️ В зависимости от уровня изоляции транзакций, другие SELECT без FOR UPDATE могут получить устаревшие значения.

🔗 https://ru.wikipedia.org/wiki/Select_for_update
👍13