Добро пожаловать на канал!
Меня зовут Максим, я Ведущий разработчик в VK, работаю над доставкой электронных писем в проекте Почта Mail.ru. Я разрабатываю ПО, которое работает 24/7 под нагрузкой 1.000.000 писем/мин.
За 5 лет в компании я прошёл путь Intern → Junior → Middle → Senior → Lead, а в целом разрабатываю ПО где-то 9 лет.
На канале я делюсь практическим опытом backend-разработки. Каждый пост - краткая выжимка из профессионального опыта, который можно перенять и применить в работе.
3 моих лучших поста:
- 10 советов сделают твой код лучше https://t.me/uimindev/31
- Как поменять раскладку? https://t.me/uimindev/29
- Пусть баги ищут роботы, а не человек https://t.me/uimindev/44
Другие мои любимые посты, список постоянно обновляется: t.me/uimindev/37
Приятного чтения!
Меня зовут Максим, я Ведущий разработчик в VK, работаю над доставкой электронных писем в проекте Почта Mail.ru. Я разрабатываю ПО, которое работает 24/7 под нагрузкой 1.000.000 писем/мин.
За 5 лет в компании я прошёл путь Intern → Junior → Middle → Senior → Lead, а в целом разрабатываю ПО где-то 9 лет.
На канале я делюсь практическим опытом backend-разработки. Каждый пост - краткая выжимка из профессионального опыта, который можно перенять и применить в работе.
3 моих лучших поста:
- 10 советов сделают твой код лучше https://t.me/uimindev/31
- Как поменять раскладку? https://t.me/uimindev/29
- Пусть баги ищут роботы, а не человек https://t.me/uimindev/44
Другие мои любимые посты, список постоянно обновляется: t.me/uimindev/37
Приятного чтения!
Уймин - про разработку pinned «Добро пожаловать на канал! Меня зовут Максим, я Ведущий разработчик в VK, работаю над доставкой электронных писем в проекте Почта Mail.ru. Я разрабатываю ПО, которое работает 24/7 под нагрузкой 1.000.000 писем/мин. За 5 лет в компании я прошёл путь Intern…»
Анализируем соединения netstat
Работа с сетевыми соединениями лежит в основе серверной разработки. Важность этой темы сложно переоценить, однако ни в универе, ни на курсах дополнительного образования никто толком не рассказывал, как отлаживать работу с сетью 😅
Для меня открытием стала утилита netstat, она позволяет ответить на вопросы:
- Какая программа куда ходит по сети?
- Какая программа какой порт слушает?
Дисклеймер 1: приведённые команды работают на Linux и основаны на GNU-версии утилиты. На MacOS стоит BSD-версия netstat, он сильно отличается от GNU, поэтому на маке мои команды работать не будут 😞 Вместо netstat можно использовать lsof.
Дисклеймер 2: чтобы видеть PID’ы и имена программ в выхлопе netstat, нужно чтобы юзер, выполняющий команду, был овнером сокета или суперюзером. В общем, для лучшей наглядности выполняйте команду от рута 😉
1️⃣ Вывести список всех активных TCP-соединений:
2️⃣ Вывести список процессов, которые слушают порт (готовы принимать входящие TCP-соединения):
или то же самое, но дополнительно вывести имена столбцов в табличке:
3️⃣ Вывести список установленных соединений по процессу (как входящих, так и исходящих):
4️⃣ Какой на машине есть UDP-трафик:
А как вы дебажите работу с сетью? Напишите в комменты!
Ставьте огонёк, если было полезно 🔥
#hardskills #tools #Linux #networks #debug
Работа с сетевыми соединениями лежит в основе серверной разработки. Важность этой темы сложно переоценить, однако ни в универе, ни на курсах дополнительного образования никто толком не рассказывал, как отлаживать работу с сетью 😅
Для меня открытием стала утилита netstat, она позволяет ответить на вопросы:
- Какая программа куда ходит по сети?
- Какая программа какой порт слушает?
Дисклеймер 1: приведённые команды работают на Linux и основаны на GNU-версии утилиты. На MacOS стоит BSD-версия netstat, он сильно отличается от GNU, поэтому на маке мои команды работать не будут 😞 Вместо netstat можно использовать lsof.
Дисклеймер 2: чтобы видеть PID’ы и имена программ в выхлопе netstat, нужно чтобы юзер, выполняющий команду, был овнером сокета или суперюзером. В общем, для лучшей наглядности выполняйте команду от рута 😉
1️⃣ Вывести список всех активных TCP-соединений:
netstat -natp
2️⃣ Вывести список процессов, которые слушают порт (готовы принимать входящие TCP-соединения):
netstat -natp | fgrep LISTEN
или то же самое, но дополнительно вывести имена столбцов в табличке:
netstat -natp | head -2 && netstat -natp | fgrep LISTEN
3️⃣ Вывести список установленных соединений по процессу (как входящих, так и исходящих):
netstat -natp | fgrep ESTABLISHED | fgrep <pid | program name>
4️⃣ Какой на машине есть UDP-трафик:
netstat -naup
А как вы дебажите работу с сетью? Напишите в комменты!
Ставьте огонёк, если было полезно 🔥
#hardskills #tools #Linux #networks #debug
🔥3👍1
Что такое контейнеры и зачем они нужны? (часть 1)
Есть 2 группы бэкендеров: те, кто ещё ничего не знает о контейнерах, и те, кто применяет их везде, где только можно. Что это за технология и почему стала такой популярной? 🧐
Контейнер - это изолированный процесс ОС.
Это простое для запоминания определение, но оно мало что говорит о сути технологии. Предлагаю рассмотреть основные свойства контейнеров, чтобы семантика слова “изолированный” стала понятнее:
1️⃣ Контейнер видит только своё поддерево файлов, см. chroot
2️⃣ Все файлы, с которыми работает контейнер, находятся во временной директории, которая автоматически удалится после завершения контейнеризованного процесса, см. mktemp
3️⃣ У контейнера свой набор переменных окружения, см. execve
4️⃣ Контейнер можно (и нужно!) запускать от имени непривилегированного пользователя, см. setuid/setgid
5️⃣ Даже если контейнер запущен от рута, у него часто ограничен набор разрешённых системных вызовов, см. capabilities
6️⃣ PID контейнеризованного процесса всегда равен 1, при этом изнутри контейнера не видны другие процессы - только дочерние процессы контейнера, см. pid_namespaces
7️⃣ На работу с сетью тоже накладываются ограничения - контейнер может иметь свои фаерволы, выделенный IP, доступ к сетевым девайсам сервера может быть ограничен белым списком, hostname контейнера может отличаться от хостовой машины, см. network_namespaces, uts_namespaces
8️⃣ Ещё на контейнер могут быть наложены ограничения на потребление основных хардварных ресурсов сервера: оперативную память, и процессорное время, см. cgroups
В совокупности этих свойств, запущенный контейнер выглядит как виртуальная машина - он не видит никаких ресурсов хостовой машины, кроме тех, к которым доступ разрешён явно. При этом контейнеры более производительны, потому что им не нужен гипервизор.
Контейнер - довольно элегантная абстракция, наверное именно поэтому они стали так популярны ✨
Однако, когда начинаешь рассматривать свойства контейнеров внимательно, выясняется, что это довольно сложная технология, обеспеченная множеством хитрых механизмов ОС ⚙️
В части 2 рассмотрим преимущества и недостатки технологии и обсудим где её можно применять. Подпишитесь на канал, чтобы не пропустить!
А вы используете контейнеры? Напишите об этом в комментарии 👇
Ставьте огонёк, если узнали что-то новое 🔥
#theory #containers #tools #Linux
Есть 2 группы бэкендеров: те, кто ещё ничего не знает о контейнерах, и те, кто применяет их везде, где только можно. Что это за технология и почему стала такой популярной? 🧐
Контейнер - это изолированный процесс ОС.
Это простое для запоминания определение, но оно мало что говорит о сути технологии. Предлагаю рассмотреть основные свойства контейнеров, чтобы семантика слова “изолированный” стала понятнее:
1️⃣ Контейнер видит только своё поддерево файлов, см. chroot
2️⃣ Все файлы, с которыми работает контейнер, находятся во временной директории, которая автоматически удалится после завершения контейнеризованного процесса, см. mktemp
3️⃣ У контейнера свой набор переменных окружения, см. execve
4️⃣ Контейнер можно (и нужно!) запускать от имени непривилегированного пользователя, см. setuid/setgid
5️⃣ Даже если контейнер запущен от рута, у него часто ограничен набор разрешённых системных вызовов, см. capabilities
6️⃣ PID контейнеризованного процесса всегда равен 1, при этом изнутри контейнера не видны другие процессы - только дочерние процессы контейнера, см. pid_namespaces
7️⃣ На работу с сетью тоже накладываются ограничения - контейнер может иметь свои фаерволы, выделенный IP, доступ к сетевым девайсам сервера может быть ограничен белым списком, hostname контейнера может отличаться от хостовой машины, см. network_namespaces, uts_namespaces
8️⃣ Ещё на контейнер могут быть наложены ограничения на потребление основных хардварных ресурсов сервера: оперативную память, и процессорное время, см. cgroups
В совокупности этих свойств, запущенный контейнер выглядит как виртуальная машина - он не видит никаких ресурсов хостовой машины, кроме тех, к которым доступ разрешён явно. При этом контейнеры более производительны, потому что им не нужен гипервизор.
Контейнер - довольно элегантная абстракция, наверное именно поэтому они стали так популярны ✨
Однако, когда начинаешь рассматривать свойства контейнеров внимательно, выясняется, что это довольно сложная технология, обеспеченная множеством хитрых механизмов ОС ⚙️
В части 2 рассмотрим преимущества и недостатки технологии и обсудим где её можно применять. Подпишитесь на канал, чтобы не пропустить!
А вы используете контейнеры? Напишите об этом в комментарии 👇
Ставьте огонёк, если узнали что-то новое 🔥
#theory #containers #tools #Linux
🔥4❤1
Что такое контейнеры и зачем они нужны? (часть 2)
В части 1 мы рассмотрели, что такое контейнеры и какими свойствами они обладают. Вторую часть предлагаю начать с того, чтобы кратко рассмотреть жизненный цикл контейнера. Допустим, мы решили запустить какое-то свое ПО в контейнере, с чего нам начать? 🧐
1️⃣ Нам нужен имейдж. Имейдж - это архив, в который мы запакуем информацию об окружении (файлы, переменные окружения и т.п.), в котором будет запущено наше ПО. Сборка имейджа - первый этап жизненного цикла контейнера.
2️⃣ Имейдж надо отправить в реджистри. Реджистри - это файловый сервер, который хранит библиотеку собранных имейджей.
3️⃣ На машине, на которой мы хотим запустить контейнер, надо скачать имейдж из реджистри.
4️⃣ Теперь контейнер можно запустить. Как мы узнали из первой части, чтобы это сделать, надо выполнить десяток разных системных вызовов. Было бы чрезвычайно утомительно делать это каждый раз вручную, поэтому в нашей истории появляется специальная программа, которая сделает это за нас - контейнерный рантайм. Даём ему на вход имейдж, получаем на выходе запущенный контейнер. О, и ещё хорошая новость: имейджи и разные контейнерные рантаймы совместимы между собой благодаря стандартам OCI, давайте скажем коллегам спасибо 🤝
Плюсы контейнеров:
✅ Поставляем ПО на продакшен сразу вместе с окружением.
✅ ↳ Деньги - единый подход к поставке ПО должен снижать стоимость эксплуатации.
✅ Контейнеры изолированы, поэтому не конфликтуют между собой;
✅ ↳ Снова деньги - изолированные контейнеры можно “плотнее” набивать на сервера, так повышается утилизация железа ⇒ снова снижается стоимость эксплуатации ПО.
✅ Безопасность - повышение изоляции компонентов усложняет проникновение злоумышленника в систему.
💡 Именно из-за экономической эффективности, как мне кажется, IT-бизнес по всему миру драйвит переход на контейнерные и облачные технологии.
Минусы контейнеров:
❌ Не все приложения готовы к контейнерам - если вам нужно хранить состояние на диске (например, вы хотите запустить СУБД), или нужен какой-то специфичный девайс (например, GPU), или вы хотите выполнять экзотические системные вызовы - заехать в контейнеры может быть проблематично. Btw, вот тут есть список лучших практик, чтобы с контейнерами не было проблем.
❌ Сложность системы сильно возрастает. Вся та изоляция, накрученная вокруг ПО, усложняет жизнь не только “злоумышленнику”, но и разработчику с админом. Когда что-то ломается, разобраться в этом - отдельный квест.
❌ Необходимость в оркестрации - чтобы максимизировать экономический эффект от внедрения контейнеров, надо вместе с ними внедрять системы оркестрации, такие как Kubernetes. Это ещё сильнее усложняет систему.
В заключение, давайте рассмотрим варианты использования контейнеров:
☁️ Облачные инсталляции ПО
💻 Разработка ПО на локальном компьютере - контейнеры относительно удобно можно тестировать локально. Это работает как под Linux, так и под MacOS, и даже на Windows можно попробовать.
📦 Распространение ПО для разработчиков - если вы хотите поделиться своим ПО с другими программистами, то можно собрать его, запаковать в имейдж и выложить в реджистри с открытым доступом - так чтобы поиграть с вашим приложением не надо будет заморчиваться со сборкой из исходников под свою ОС.
Как вы думаете, какое будущее ждёт контейнерные технологии? Напишите об этом в комментарии 👇
Ставьте огонёк, если контейнеры топ 🔥
#theory #containers #tools #Linux
В части 1 мы рассмотрели, что такое контейнеры и какими свойствами они обладают. Вторую часть предлагаю начать с того, чтобы кратко рассмотреть жизненный цикл контейнера. Допустим, мы решили запустить какое-то свое ПО в контейнере, с чего нам начать? 🧐
1️⃣ Нам нужен имейдж. Имейдж - это архив, в который мы запакуем информацию об окружении (файлы, переменные окружения и т.п.), в котором будет запущено наше ПО. Сборка имейджа - первый этап жизненного цикла контейнера.
2️⃣ Имейдж надо отправить в реджистри. Реджистри - это файловый сервер, который хранит библиотеку собранных имейджей.
3️⃣ На машине, на которой мы хотим запустить контейнер, надо скачать имейдж из реджистри.
4️⃣ Теперь контейнер можно запустить. Как мы узнали из первой части, чтобы это сделать, надо выполнить десяток разных системных вызовов. Было бы чрезвычайно утомительно делать это каждый раз вручную, поэтому в нашей истории появляется специальная программа, которая сделает это за нас - контейнерный рантайм. Даём ему на вход имейдж, получаем на выходе запущенный контейнер. О, и ещё хорошая новость: имейджи и разные контейнерные рантаймы совместимы между собой благодаря стандартам OCI, давайте скажем коллегам спасибо 🤝
Плюсы контейнеров:
✅ Поставляем ПО на продакшен сразу вместе с окружением.
✅ ↳ Деньги - единый подход к поставке ПО должен снижать стоимость эксплуатации.
✅ Контейнеры изолированы, поэтому не конфликтуют между собой;
✅ ↳ Снова деньги - изолированные контейнеры можно “плотнее” набивать на сервера, так повышается утилизация железа ⇒ снова снижается стоимость эксплуатации ПО.
✅ Безопасность - повышение изоляции компонентов усложняет проникновение злоумышленника в систему.
💡 Именно из-за экономической эффективности, как мне кажется, IT-бизнес по всему миру драйвит переход на контейнерные и облачные технологии.
Минусы контейнеров:
❌ Не все приложения готовы к контейнерам - если вам нужно хранить состояние на диске (например, вы хотите запустить СУБД), или нужен какой-то специфичный девайс (например, GPU), или вы хотите выполнять экзотические системные вызовы - заехать в контейнеры может быть проблематично. Btw, вот тут есть список лучших практик, чтобы с контейнерами не было проблем.
❌ Сложность системы сильно возрастает. Вся та изоляция, накрученная вокруг ПО, усложняет жизнь не только “злоумышленнику”, но и разработчику с админом. Когда что-то ломается, разобраться в этом - отдельный квест.
❌ Необходимость в оркестрации - чтобы максимизировать экономический эффект от внедрения контейнеров, надо вместе с ними внедрять системы оркестрации, такие как Kubernetes. Это ещё сильнее усложняет систему.
В заключение, давайте рассмотрим варианты использования контейнеров:
☁️ Облачные инсталляции ПО
💻 Разработка ПО на локальном компьютере - контейнеры относительно удобно можно тестировать локально. Это работает как под Linux, так и под MacOS, и даже на Windows можно попробовать.
📦 Распространение ПО для разработчиков - если вы хотите поделиться своим ПО с другими программистами, то можно собрать его, запаковать в имейдж и выложить в реджистри с открытым доступом - так чтобы поиграть с вашим приложением не надо будет заморчиваться со сборкой из исходников под свою ОС.
Как вы думаете, какое будущее ждёт контейнерные технологии? Напишите об этом в комментарии 👇
Ставьте огонёк, если контейнеры топ 🔥
#theory #containers #tools #Linux
🔥2👍1
А как бы вы это сделали?
В универе у меня был один препрод, он вёл Операционные Системы. Тот ещё мудак на самом деле: про ОС из его курса я не узнал ничего нового - мы пробежались по самым базовым концепциям, много обсуждали, как что-то можно сделать в теории и ни разу не рассмотрели, как что-то сделано на самом деле в реально рабочей ОС. А ещё он постоянно повторял:
😡 Как же сильно меня бесила эта фраза! Какая разница, что я себе напридумывал? Пока это не подтверждено фактами, все мои предположения - это просто галлюцинации!
ℹ️ Дело было на старших курсах и к тому времени я уже работал в группе Системной разработки Mail.ru и имел некоторое профессиональное представление об ОС. Когда я сидел на лекциях и слушал непрерывный поток “А как бы вы это сделали?” фоном, параллельно занимаясь написанием кода на работе, я поймал себя на одной мысли:
🎯 И более того, делаю это достаточно точно, где-то 9/10 случаев! Оказывается, эта механика называется Educated guess. В контексте программирования это значит следующее:
🕵️ Когда у вас есть опыт в разработке ПО и насмотренность на реальные рабочие решения, на основании своих знаний вы можете сделать обоснованное предположение о принципах внутреннего устройства совершенно незнакомой вам системы.
🤔 Эта идея показалась мне весьма занятной и я начал применять educated guess в своей работе. Работая джуном в продукте с 20-летней историей развития, мне часто приходилось изучать новые системы: как 8-летнее legacy, которое надо поддерживать, так и state of the art технологии вроде контейнеров или Kubernetes, на которые надо перейти. Вонзаясь во все эти системы я делал предположение о том, как они устроены под капотом.
✅ Иногда я угадывал - это позволяло мне учиться быстрее. Всегда приятно, когда твоё предположение подтверждается - это значит, что вы с автором этого софта на одной волне 😉 🌊
❌ Но гораздо ценнее, когда предположение опровергается. Если ты рассматриваешь production-технологию и она работает не так, как ты предположил - это значит, что какой-то более опытный разработчик осознанно принял решение сделать по-другому. У него наверняка, были причины сделать именно так, и изучив технологию подробнее, у него можно чему-то научиться 📚 ✍️
В итоге, educated guess стал для меня одним из базовых инструментов при онбординге в любые новые технологии. Я убеждён, что этот подход позволяет мне учиться быстрее и развивает такие полезные качества, как любопытство и насмотренность. Так что, может быть мне стоит сказать своему университетскому преподу спасибо 😅
Будь вы Линус Торвальдс, как бы вы написали свою ОС? Расскажите об этом в комментариях 👇
Ставьте огонёк, если используете educated guess в работе 🔥
#softskills #selflearning #bestpractice
В универе у меня был один препрод, он вёл Операционные Системы. Тот ещё мудак на самом деле: про ОС из его курса я не узнал ничего нового - мы пробежались по самым базовым концепциям, много обсуждали, как что-то можно сделать в теории и ни разу не рассмотрели, как что-то сделано на самом деле в реально рабочей ОС. А ещё он постоянно повторял:
А как бы вы это сделали? Если это логично, то, скорее всего, так оно и сделано на самом деле!
😡 Как же сильно меня бесила эта фраза! Какая разница, что я себе напридумывал? Пока это не подтверждено фактами, все мои предположения - это просто галлюцинации!
ℹ️ Дело было на старших курсах и к тому времени я уже работал в группе Системной разработки Mail.ru и имел некоторое профессиональное представление об ОС. Когда я сидел на лекциях и слушал непрерывный поток “А как бы вы это сделали?” фоном, параллельно занимаясь написанием кода на работе, я поймал себя на одной мысли:
Я начинаю угадывать, что этот мудак скажет дальше!
🎯 И более того, делаю это достаточно точно, где-то 9/10 случаев! Оказывается, эта механика называется Educated guess. В контексте программирования это значит следующее:
🕵️ Когда у вас есть опыт в разработке ПО и насмотренность на реальные рабочие решения, на основании своих знаний вы можете сделать обоснованное предположение о принципах внутреннего устройства совершенно незнакомой вам системы.
🤔 Эта идея показалась мне весьма занятной и я начал применять educated guess в своей работе. Работая джуном в продукте с 20-летней историей развития, мне часто приходилось изучать новые системы: как 8-летнее legacy, которое надо поддерживать, так и state of the art технологии вроде контейнеров или Kubernetes, на которые надо перейти. Вонзаясь во все эти системы я делал предположение о том, как они устроены под капотом.
✅ Иногда я угадывал - это позволяло мне учиться быстрее. Всегда приятно, когда твоё предположение подтверждается - это значит, что вы с автором этого софта на одной волне 😉 🌊
❌ Но гораздо ценнее, когда предположение опровергается. Если ты рассматриваешь production-технологию и она работает не так, как ты предположил - это значит, что какой-то более опытный разработчик осознанно принял решение сделать по-другому. У него наверняка, были причины сделать именно так, и изучив технологию подробнее, у него можно чему-то научиться 📚 ✍️
В итоге, educated guess стал для меня одним из базовых инструментов при онбординге в любые новые технологии. Я убеждён, что этот подход позволяет мне учиться быстрее и развивает такие полезные качества, как любопытство и насмотренность. Так что, может быть мне стоит сказать своему университетскому преподу спасибо 😅
Будь вы Линус Торвальдс, как бы вы написали свою ОС? Расскажите об этом в комментариях 👇
Ставьте огонёк, если используете educated guess в работе 🔥
#softskills #selflearning #bestpractice
🔥3😁2
Про зону ответственности
В первый год работы в Mail.ru мне повезло услышать выступление CTO моего бизнес-юнита на квартальной презентации. Там он сказал примерно такую фразу:
👌 “Прикольно” подумал я и пошёл дальше работу работать. Однако, эта мысль настолько простая и важная (денег-то побольше всем хочется, ага ;) что она крепко отложилась у меня в голове.
⏳ Прошло 4 года, я теперь сеньор, и оглядываясь назад не могу не думать: черт, а ведь он был абсолютно прав! Каждое моё повышение проходило по одному и тому же фреймворку:
1️⃣ Ты нифига не вдупляшь. Очень стрессовый этап, но в то же время интересный, потому что именно на этом этапе мы учимся. Я хз что тут сказать, очень хочется быть оптимистом и написать что-то в духе “вы со всем справитесь” и “всё будет хорошо”, но я вот сейчас вспоминаю, как сам проходил периоды “невдупления”, и у меня язык не поворачивается такой булшит выдать 😶 Если вы сейчас на этом этапе - держитесь. Учиться сложно, у вас тысячу раз будет желание бросить это дело, но результат того стоит. Ну и можете пробежаться по тегу #selflearning на этом канале, может найдёте что-нибудь полезное 😉
2️⃣ Ты делаешь свою работу хорошо. Вот такой вот естественный исход после всех мучений на этапе обучения. Тимлид ставит задачки, ты их выполняешь, никакого стресса. Кофе по утрам, пиво по пятницам - красота 😊 И если на этом этапе ты достиг того уровня дохода, который тебе нужен, то всё замечательно - тебя можно только поздравить! Однако, если хочешь забраться выше, то на этом этапе тебя ждёт одна незаметная ловушка - стагнация, т.е. боковой тренд, без роста и без снижения 🚧🕳
3️⃣ И вот тут самое время вернуться к цитате, с которой я начал этот пост. Если уровень дохода не устраивает, то нужно проявить инициативу и взять на себя бо́льшую ответственность. Теоретически, есть 2 пути:
- интенсивный - в рамках текущей зоны ответственности делать свою работу более качественно;
- экстенсивный - расширить зону ответственности, например, стать мейнтенером ещё одного компонента системы или реализовать новое техническое решение.
На практике я видел, пожалуй, только второй вариант. Возможно, потому что в IT-корпорациях и так высокий запрос на уровень ответственности для попадания на этап 2 ¯\_(ツ)_/¯
4️⃣ Как только вы начинаете перформить выше ожиданий от вашей роли, вы становитесь кандидатом на повышение. Мне в этом плане очень повезло с руководством - мои результаты были заметны и предложение о повышении поступало сверху. Многие коллеги (особенно на старте карьеры) меняют работу, чтобы получить повышение. Как мне кажется, это оверкилл: начать всегда следует с диалога со своим текущим руководителем. Если вам не предлагают повышение, сходите и продайте свои достижения тимлиду сами! В конце концов, ваш рост - это ваша личная ответственность, ведь он нужен только вам 😉
5️⃣ Ну а вместе с повышением к вам естественным образом попадут новые, более сложные задачи. Так что, добро пожаловать обратно на этап 1, всё, карьерный цикл замкнулся 🤗
Эта простая мысль на 4 года вперёд определила мой карьерный путь. Возможно, она же поможет вырасти и вам 😉
Ставьте огонёк если вам интересно читать про карьеру 🔥 Не считаю себя экспертом в этой области, но, думаю, найду, что ещё рассказать ;)
#career #softskills
В первый год работы в Mail.ru мне повезло услышать выступление CTO моего бизнес-юнита на квартальной презентации. Там он сказал примерно такую фразу:
Расширение зоны ответственности - единственный путь к повышению вознаграждения и должности.
👌 “Прикольно” подумал я и пошёл дальше работу работать. Однако, эта мысль настолько простая и важная (денег-то побольше всем хочется, ага ;) что она крепко отложилась у меня в голове.
⏳ Прошло 4 года, я теперь сеньор, и оглядываясь назад не могу не думать: черт, а ведь он был абсолютно прав! Каждое моё повышение проходило по одному и тому же фреймворку:
1️⃣ Ты нифига не вдупляшь. Очень стрессовый этап, но в то же время интересный, потому что именно на этом этапе мы учимся. Я хз что тут сказать, очень хочется быть оптимистом и написать что-то в духе “вы со всем справитесь” и “всё будет хорошо”, но я вот сейчас вспоминаю, как сам проходил периоды “невдупления”, и у меня язык не поворачивается такой булшит выдать 😶 Если вы сейчас на этом этапе - держитесь. Учиться сложно, у вас тысячу раз будет желание бросить это дело, но результат того стоит. Ну и можете пробежаться по тегу #selflearning на этом канале, может найдёте что-нибудь полезное 😉
2️⃣ Ты делаешь свою работу хорошо. Вот такой вот естественный исход после всех мучений на этапе обучения. Тимлид ставит задачки, ты их выполняешь, никакого стресса. Кофе по утрам, пиво по пятницам - красота 😊 И если на этом этапе ты достиг того уровня дохода, который тебе нужен, то всё замечательно - тебя можно только поздравить! Однако, если хочешь забраться выше, то на этом этапе тебя ждёт одна незаметная ловушка - стагнация, т.е. боковой тренд, без роста и без снижения 🚧🕳
3️⃣ И вот тут самое время вернуться к цитате, с которой я начал этот пост. Если уровень дохода не устраивает, то нужно проявить инициативу и взять на себя бо́льшую ответственность. Теоретически, есть 2 пути:
- интенсивный - в рамках текущей зоны ответственности делать свою работу более качественно;
- экстенсивный - расширить зону ответственности, например, стать мейнтенером ещё одного компонента системы или реализовать новое техническое решение.
На практике я видел, пожалуй, только второй вариант. Возможно, потому что в IT-корпорациях и так высокий запрос на уровень ответственности для попадания на этап 2 ¯\_(ツ)_/¯
4️⃣ Как только вы начинаете перформить выше ожиданий от вашей роли, вы становитесь кандидатом на повышение. Мне в этом плане очень повезло с руководством - мои результаты были заметны и предложение о повышении поступало сверху. Многие коллеги (особенно на старте карьеры) меняют работу, чтобы получить повышение. Как мне кажется, это оверкилл: начать всегда следует с диалога со своим текущим руководителем. Если вам не предлагают повышение, сходите и продайте свои достижения тимлиду сами! В конце концов, ваш рост - это ваша личная ответственность, ведь он нужен только вам 😉
5️⃣ Ну а вместе с повышением к вам естественным образом попадут новые, более сложные задачи. Так что, добро пожаловать обратно на этап 1, всё, карьерный цикл замкнулся 🤗
Расширение зоны ответственности - единственный путь к повышению вознаграждения и должности.
Эта простая мысль на 4 года вперёд определила мой карьерный путь. Возможно, она же поможет вырасти и вам 😉
Ставьте огонёк если вам интересно читать про карьеру 🔥 Не считаю себя экспертом в этой области, но, думаю, найду, что ещё рассказать ;)
#career #softskills
🔥6👏1
Чтение кода > написание кода
Чем на работе занимается профессиональный программист? “Пишет код!” - ответит любой студент или новичок в профессии. “А ещё?” - спрошу я его 😉
🛠 Кодирование, безусловно, важно. Однако, это далеко не единственный вид работы, которую профессиональному программисту требуется выполнять ежедневно. Например, каждый день приходится читать код, причём почти всегда он написан другими людьми. В рамках своей работы я читаю код не реже, а может быть и чаще, чем пишу сам. И я не побоюсь сказать, что это самый настоящий стандарт индустрии.
👀 Первый раз я услышал этот тезис на 2-ом курсе универа, когда поступал в Технопарк Mail.ru (сейчас ОЦ VK в МГТУ. им. Н.Э. Баумана). Я тогда тоже думал, что программисты “Пишут код!”, поэтому для меня было настоящим шоком увидеть на вступительных задачу на чтение кода. Мне тогда предложили прочитать вот эту функцию из утилиты strings и рассказать, что она делает. Читая её вдоль, поперёк и по диагонали за 20 минут я так и не смог выдавить из себя чего-то внятного 🤡
❗️ Профессиональный программист читает код чаще, чем пишет. Этот навык не менее важен, чем навык кодирования. Его можно и нужно развивать. Единственный способ прокачать чтение кода - практика, например:
1️⃣ Проводить код ревью, особенно более опытных коллег. Да, джунам полезно ревьюить работу сеньоров. При этом важно не просто просмотреть код по формальным критериям типа кодстайла, а найти ответы на следующие вопросы:
- Какую задачу решал автор патча?
- Каким образом он её решал, как работает этот код?
- Решена ли задача, будет ли этот код работать?
В общем, главная цель код ревью - это поиск багов. У меня на ревью одного патча в среднем уходит где-то 1 час. Если вы тратите на первую итерацию ревью меньше 30-40 минут, то, скорее всего, вы избегаете действительно важных вопросов 🙅♂️
2️⃣ Нет возможности читать код коллег - читайте код из OpenSource. Задача с утилитой strings как раз относится к этому упражнению 🙂 Разобраться в проекте - не то же самое, что разобраться в патче. Не получится прочитать весь проект, слишком много информации. Вместо этого, нужно посмотреть на него более высокоуровнево:
- Зачем нужен проект, какую задачу он решает?
- Какое API предоставляет проект?
- Какие в проекте есть модули, как они взаимодействуют между собой?
- Какие в проекте ключевые сущности (классы, структуры данных, таблицы БД)?
3️⃣ Ищите ответы на вопросы в своём софте - не в головах коллег. При выполнении задач в проектах, написанных другими разработчиками, часто появляются вопросы типа “как работает вон та штука?”. В этот момент появляется соблазн пойти к старшему коллеге, задать вопрос в лоб, получить ответ и пойти дальше код писать. Я считаю такой подход безответственным и непрофессиональным. Вместо этого, первое, что разработчику следует сделать - выполнить поиск по кодовой базе проекта, например так:
👆 Это мощнейший драйвер роста твоих навыков! Даже если ты в итоге не найдёшь то, что ищешь, ты придёшь к коллегам уже с другим вопросом:
☝️ Так ты найдёшь не только ответ, но и навыки поиска прокачаешь, и с проектом по-ближе познакомишься. Профит x3 🔥
🧐 Многие недооценивают навык чтения кода, и это большая ошибка - его можно и нужно тренировать.
🕹 Интерактив: у моей компании есть вот такой код в на гитхабе: https://github.com/mailru/tntlua/blob/master/spammerdb.lua
Дано: Там есть 2 функции
Вопрос: что такое
Ответ:`flags` - это число размером в 1 байт. Там хранится массив из 4-ёх элементов размером 2 бита каждый. Каждый элемент - это `stype`, так что `flags` - это массив из 4-ёх `stype`’ов.
Ставьте , если читаете код каждый день 🔥
#hardskills #codereading #selflearning
Чем на работе занимается профессиональный программист? “Пишет код!” - ответит любой студент или новичок в профессии. “А ещё?” - спрошу я его 😉
🛠 Кодирование, безусловно, важно. Однако, это далеко не единственный вид работы, которую профессиональному программисту требуется выполнять ежедневно. Например, каждый день приходится читать код, причём почти всегда он написан другими людьми. В рамках своей работы я читаю код не реже, а может быть и чаще, чем пишу сам. И я не побоюсь сказать, что это самый настоящий стандарт индустрии.
👀 Первый раз я услышал этот тезис на 2-ом курсе универа, когда поступал в Технопарк Mail.ru (сейчас ОЦ VK в МГТУ. им. Н.Э. Баумана). Я тогда тоже думал, что программисты “Пишут код!”, поэтому для меня было настоящим шоком увидеть на вступительных задачу на чтение кода. Мне тогда предложили прочитать вот эту функцию из утилиты strings и рассказать, что она делает. Читая её вдоль, поперёк и по диагонали за 20 минут я так и не смог выдавить из себя чего-то внятного 🤡
❗️ Профессиональный программист читает код чаще, чем пишет. Этот навык не менее важен, чем навык кодирования. Его можно и нужно развивать. Единственный способ прокачать чтение кода - практика, например:
1️⃣ Проводить код ревью, особенно более опытных коллег. Да, джунам полезно ревьюить работу сеньоров. При этом важно не просто просмотреть код по формальным критериям типа кодстайла, а найти ответы на следующие вопросы:
- Какую задачу решал автор патча?
- Каким образом он её решал, как работает этот код?
- Решена ли задача, будет ли этот код работать?
В общем, главная цель код ревью - это поиск багов. У меня на ревью одного патча в среднем уходит где-то 1 час. Если вы тратите на первую итерацию ревью меньше 30-40 минут, то, скорее всего, вы избегаете действительно важных вопросов 🙅♂️
2️⃣ Нет возможности читать код коллег - читайте код из OpenSource. Задача с утилитой strings как раз относится к этому упражнению 🙂 Разобраться в проекте - не то же самое, что разобраться в патче. Не получится прочитать весь проект, слишком много информации. Вместо этого, нужно посмотреть на него более высокоуровнево:
- Зачем нужен проект, какую задачу он решает?
- Какое API предоставляет проект?
- Какие в проекте есть модули, как они взаимодействуют между собой?
- Какие в проекте ключевые сущности (классы, структуры данных, таблицы БД)?
3️⃣ Ищите ответы на вопросы в своём софте - не в головах коллег. При выполнении задач в проектах, написанных другими разработчиками, часто появляются вопросы типа “как работает вон та штука?”. В этот момент появляется соблазн пойти к старшему коллеге, задать вопрос в лоб, получить ответ и пойти дальше код писать. Я считаю такой подход безответственным и непрофессиональным. Вместо этого, первое, что разработчику следует сделать - выполнить поиск по кодовой базе проекта, например так:
fgrep -re "some interesting stuff" ./src | fgrep -v "filtering out boring stuff, like third_party"
👆 Это мощнейший драйвер роста твоих навыков! Даже если ты в итоге не найдёшь то, что ищешь, ты придёшь к коллегам уже с другим вопросом:
Я решаю задачу X, для этого мне нужно знать Y. Я поискал в проекте запросами A и B, но ничего не нашёл. Что я упускаю?
☝️ Так ты найдёшь не только ответ, но и навыки поиска прокачаешь, и с проектом по-ближе познакомишься. Профит x3 🔥
🧐 Многие недооценивают навык чтения кода, и это большая ошибка - его можно и нужно тренировать.
🕹 Интерактив: у моей компании есть вот такой код в на гитхабе: https://github.com/mailru/tntlua/blob/master/spammerdb.lua
Дано: Там есть 2 функции
get_value
и set_value
, они работают со структурой данных, которая называется flags
. Известно, что переменная stype
может принимать только 4 разных значения: 0
, 1
, 2
или 3
Вопрос: что такое
flags
, какой тип данных там хранится?Ответ:
Ставьте , если читаете код каждый день 🔥
#hardskills #codereading #selflearning
🔥5
Паттерн early exit
Какие задачи стоят перед программистом, когда он реализует какую-то функцию? Обеспечить корректность алгоритма, при минимальной сложности кода. Именно в этом помогает паттерн early exit.
📍 В чём суть: когда в вашем алгоритме появляется оператор ветвления (
ℹ️ Пример:
- Без early exit
- То же самое, но с early exit:
У early exit подхода есть ряд преимуществ:
1️⃣ Снижается вложенность операторов - это упрощает чтение кода.
2️⃣ Повышается фокус на основной путь выполнения функции - часто, когда дочитываешь длинную (вероятно, главную) ветвь выполнения кода, уже забываешь, зачем выше было ветвление и в чём смысл короткой ветви. Early exit позволяет быстро прочитать короткую ветвь и забыть о ней, сфокусировавшись на длинной ветви. В итоге, программисту нужно меньше “оперативной памяти” чтобы прочитать код 😊
3️⃣ Повышается корректность алгоритма - все граничные условия можно рассмотреть в самом начале функции, по моему опыту такой подход снижает количество ошибок.
4️⃣ Если в вашем языке нет
^ такой подход особенно популярен в ядре Linux: раз, два, три. Думаю, авторы этого кода что-то знают о программировании 😉
💡 Итого: при использовании операторов ветвления короткие ветви алгоритма следует обрабатывать перед длинными. Этот подход называется early exit. Он позволяет писать более простой и корректный код.
Ставь огонёк, если используешь early exit в своей работе 🔥
#hardskills #coding #pattern #bestpractice #codereading
Какие задачи стоят перед программистом, когда он реализует какую-то функцию? Обеспечить корректность алгоритма, при минимальной сложности кода. Именно в этом помогает паттерн early exit.
📍 В чём суть: когда в вашем алгоритме появляется оператор ветвления (
if
, switch
и т.п.), короткую ветвь вычислений надо обработать перед длинной ветвью.ℹ️ Пример:
- Без early exit
if user.isAuthorized() {
// Do
// some
// business
// logic
} else {
return errors.New("403 Anauthorized")
}
- То же самое, но с early exit:
if !user.isAuthorized() {
return errors.New("403 Anauthorized")
}
// Do
// some
// business
// logic
У early exit подхода есть ряд преимуществ:
1️⃣ Снижается вложенность операторов - это упрощает чтение кода.
2️⃣ Повышается фокус на основной путь выполнения функции - часто, когда дочитываешь длинную (вероятно, главную) ветвь выполнения кода, уже забываешь, зачем выше было ветвление и в чём смысл короткой ветви. Early exit позволяет быстро прочитать короткую ветвь и забыть о ней, сфокусировавшись на длинной ветви. В итоге, программисту нужно меньше “оперативной памяти” чтобы прочитать код 😊
3️⃣ Повышается корректность алгоритма - все граничные условия можно рассмотреть в самом начале функции, по моему опыту такой подход снижает количество ошибок.
4️⃣ Если в вашем языке нет
defer
'ов и сборки мусора, разновидность early exit упрощает корректную деаллокацию ресурсов. Пример:void foo() {
void *a = malloc(1024);
if (!a)
goto out_a;
void *b = malloc(1024);
if (!b)
goto out_b;
void *c = malloc(1024);
if (!c)
goto out_c;
/*
* Метки позволяют деаллоцировать только те ресурсы,
* которые были успешно аллоцированы
*/
free(c);
out_c:
free(b);
out_b:
free(a);
out_a:
return;
}
^ такой подход особенно популярен в ядре Linux: раз, два, три. Думаю, авторы этого кода что-то знают о программировании 😉
💡 Итого: при использовании операторов ветвления короткие ветви алгоритма следует обрабатывать перед длинными. Этот подход называется early exit. Он позволяет писать более простой и корректный код.
Ставь огонёк, если используешь early exit в своей работе 🔥
#hardskills #coding #pattern #bestpractice #codereading
🔥5
Всё есть файл
Эта широко известная концепция лежит в основе UNIX-подобных операционных систем. Но что это значит? 🤔
📍 Начнём с того, что такое файл. Каноническое определение такое:
☝️ Другими словами, файл - это фрагмент информации, который можно идентифицировать.
ℹ️ Под “всё есть файл” имеется в виду, что разные по своей сути фрагменты информации обладают одинаковым интерфейсом доступа и сходными свойствами.
🤔 Что за “разные фрагменты информации”?
1️⃣ Данные на жёстком диске - то, что пользователям привычнее всего называть словом “файл”.
2️⃣ Директории (каталоги, папки) - тоже разновидность файлов.
3️⃣ Сетевые соединения - обладают теми же свойствами, что и открытые файлы.
4️⃣ Стандартные потоки ввода/вывода
5️⃣ Интерфейсы межпроцессного взаимодействия - пайпы, сокеты
6️⃣ Интерфейсы взаимодействия с железом - девайсы
7️⃣ Даже с сигналами можно работать как с файлами 0_o
🤔 Окей, а чего между всеми этими сущностями общего, что за “одинаковый интерфейс и сходные свойства”?
1️⃣ Общий жизненный цикл:
- Cначала надо открыть файл (
- Потом с ним можно будет работать
- В конце его надо закрыть (
2️⃣ Каждый открытый файл идентифицируется числом - файловым дескриптором. Вне зависимости от типа файла, в ядре ОС все файловые дескрипторы процесса хранятся в одной таблице.
3️⃣ В процессе работы с открытым файлом для ввода/вывода информации мы используем одни и те же инструменты:
-
-
-
-
4️⃣ Свойства операций ввода-вывода тоже похожи. Ввод/вывод может быть:
- Синхронным/асинхронным
- Буферизированным/прямым (direct)
- Блокирующим/неблокирующим
💡 Подсистема ввода/вывода - это непросто, но важно. С её инструментами и свойствами нужно разбираться, в работе мы с ними сталкиваемся каждый день. Но вы только посмотрите, как всё это красиво устроено! Столько разных задач решено единым подходом - почти никаких частных случаев, и все выигрывают от общего инструментария. Именно к такому дизайну в своих системах, как мне кажется, и надо стремиться.
Ставь огонёк, если всё есть файл 🔥
#theory #Linux #fs #networks
Эта широко известная концепция лежит в основе UNIX-подобных операционных систем. Но что это значит? 🤔
📍 Начнём с того, что такое файл. Каноническое определение такое:
Файл - это именованная последовательность байт
☝️ Другими словами, файл - это фрагмент информации, который можно идентифицировать.
ℹ️ Под “всё есть файл” имеется в виду, что разные по своей сути фрагменты информации обладают одинаковым интерфейсом доступа и сходными свойствами.
🤔 Что за “разные фрагменты информации”?
1️⃣ Данные на жёстком диске - то, что пользователям привычнее всего называть словом “файл”.
2️⃣ Директории (каталоги, папки) - тоже разновидность файлов.
3️⃣ Сетевые соединения - обладают теми же свойствами, что и открытые файлы.
4️⃣ Стандартные потоки ввода/вывода
5️⃣ Интерфейсы межпроцессного взаимодействия - пайпы, сокеты
6️⃣ Интерфейсы взаимодействия с железом - девайсы
7️⃣ Даже с сигналами можно работать как с файлами 0_o
🤔 Окей, а чего между всеми этими сущностями общего, что за “одинаковый интерфейс и сходные свойства”?
1️⃣ Общий жизненный цикл:
- Cначала надо открыть файл (
open
, opendir
, connect
, pipe
и т.п.)- Потом с ним можно будет работать
- В конце его надо закрыть (
close
)2️⃣ Каждый открытый файл идентифицируется числом - файловым дескриптором. Вне зависимости от типа файла, в ядре ОС все файловые дескрипторы процесса хранятся в одной таблице.
3️⃣ В процессе работы с открытым файлом для ввода/вывода информации мы используем одни и те же инструменты:
-
read
/write
- прочитать/записать данные-
fcntl
- настройка свойств ФД (блокировки, подписка на события, установка флагов и т.п.)-
dup
- дублирование ФД-
mmap
/munmap
- отображение файла в оперативную память4️⃣ Свойства операций ввода-вывода тоже похожи. Ввод/вывод может быть:
- Синхронным/асинхронным
- Буферизированным/прямым (direct)
- Блокирующим/неблокирующим
💡 Подсистема ввода/вывода - это непросто, но важно. С её инструментами и свойствами нужно разбираться, в работе мы с ними сталкиваемся каждый день. Но вы только посмотрите, как всё это красиво устроено! Столько разных задач решено единым подходом - почти никаких частных случаев, и все выигрывают от общего инструментария. Именно к такому дизайну в своих системах, как мне кажется, и надо стремиться.
Ставь огонёк, если всё есть файл 🔥
#theory #Linux #fs #networks
🔥5