Pull to refresh
312
0
Владимир Маслов @HotWaterMusic

Руководитель, автор ТГ-канала Сеньор Юникорн

Send message

Хочу сказать пару слов про первую книгу. Я нашел ее буквально случайно, когда я первый раз стал менеджером. С тех пор я рекомендую эту книгу всем своим подчиненным - будь они менеджеры менеджеров, линейные менеджеры, тимлиды или просто инженеры которые думают о переходе на лидерские позиции.

Почему мне так нравится эта книга? По ряду причин.

  • Она написана очень простым и понятным, no-bullshit языком, инженером для инженеров. Многие книги по бизнесу и лидерству (особенно американских авторов) грешат тем, что первые три главы тебе рассказывают о том, как этот подход изменил жизнь многих известных людей, потом еще две о том, как автор пришел к этому подходу, и только в конце, кратенько - в чем, собственно, подход заключается.

  • Ее можно читать в любом порядке, в том числе - как справочник. Может показаться, что если ты TL, то глава The Big Leagues тебе пока не нужна - но это не так. Чтение поможет понять, как мыслят люди в таких позициях, что для них важно и как выстраивать разговор и аргументацию с ними.

  • В том числе, если ты менеджер менеджеров, читая главу про TL-ов, можно лучше понять как растить людей, как давать им stretch goals (задачи по силам, но на пределе, которые стимулируют развитие)

  • В книге довольно много конкретных примеров и рекомендаций, в стиле "попробуй так, а не получится, попробуй еще вот так".

  • Наконец, эта книга описывает не сферический менеджмент в вакууме, а менеджмент именно инженерных команд - в этом (как, пожалуй, и везде) очень много специфики, и ее нельзя не учитывать.

Короче, это отличная книга и я настоятельно рекомендую ее всем, кому интересно лидерство именно в технической сфере.

ваш рост зарплаты не связан с ростом зарплат на рынке - это хороший рост как специалиста, обусловленный низкой базой. Если бы вы были senior или tech/team lead с опытом 10+ лет, ваш рост зарплаты в процентах был бы совсем не таким впечатляющим.

Shameless plug: проект code-review-checklists/java-concurrency на Гитхабе содержит много советов из JCIP упакованных в форму применимую во время ревью кода с многопоточностью.

Спасибо за отличное интервью.


Олег: Интересно. Если взять, к примеру, какое-нибудь сообщество питонистов, то у них куда меньше культ производительности. Как получилось, что именно в нашем сообществе так происходит? Может, это вы спровоцировали культ перформанса своими докладами? Ты, Шипилев, Паньгин, Иванов и так далее.

Мне кажется, это очень интересный вопрос.


Во-первых, культ производительности определенно есть не только в Джаве: посмотрите доклады на конференциях по Go, С++, JavaScript — там тоже очень много докладов про производительность, и зачастую это самые посещаемые доклады.


Думаю, культ во многом связан с эго: "если я написал код быстрее, чем коллега, значит я круче/умнее". Посмотрите на заголовки проектов на Гитхабе: многие имеют вид "Fast(est) [Thing] for [Language]". Вдобавок, производительность относительно легко сравнивать.


Было бы интересно видеть в индустрии больше проектов с заголовками типа:


  • "Very robust [Thing] for [Language]"
  • "[Thing] for [Language] with minimum configuration parameters/completely automatic tuning"
  • "[Thing] for [Language] with minimum resource (disk/memory/network) usage". Такое, кстати, иногда встречается, хотя реже, чем "fastest". Например, люди любят писать очень компактные реализации libc, см. musl и друзей.
  • "[Thing] for [Language] with > 90% mutation testing coverage"
UFO landed and left these words here
Какой смысл разделять в статье объяснения механизмов работы HashSet и HasMap, если можно просто сказать что HashSet внутри себя содержит HashMap и все вызовы проксирует к нему?

Изначально был выбран неправильный тип метрики для решения задачи. Стандартный джентльменский набор для веб-сервисов:


  1. cumulative counter для числа обработанных запросов, отображать как rate
  2. cumulative counter для числа ошибок (с разбивкой по типу ошибки), отображать как rate
  3. histogram для времени обработки запросов, отображать как процентили
  4. gauge для requests in flight, отображать, как есть

Сочетание 3 и 4 дало бы вам совершенно четкую картину вашей аварии: рост latency и рост числа запросов in flight.

UFO landed and left these words here

Мой личный список вопросов работодателю (если не было освещено на собеседовании).


Чем я буду заниматься? Только узкими обязанностями или еще и смежными?
Какой стек на моём проекте? Есть ли легаси?
Что с тестированием
Есть ли CI/CD и девопс инженер?
Будет ли единый ПМ и четко заданный жизненный цикл таска?
Есть ли БА?
Системы мониторинга, сборщик логов?
Переработки бывают? Оплата?
Системы трекинга времени и руткиты на рабочем компе?
Отпуска: дробление отпуска, включены или нет выходные, за сколько нужно предупреждать, отказы
За что и как часто получаются премии? Кто определяет их размер?
Есть ли СБ? Какие требования у СБ?
Почему открыта вакансия? Если не новая, то куда ушел предыдущий разработчик?
Аналогично про гибкий график, карьерный рост. Что это значит и в чем выражается.
Ретроспектива.
Код ревью в компании: кто, как долго, что если пожар.

В случае с опционами обычно контракт предполагает 4 года на весь пакет акций, с возможностью забирать частями после первого года ("one year cliff"). Т.е. всегда есть возможность выйти с 3/4, если после трех лет. Рассматривали такой вариант? Ведь всех денег не заработаешь, а опцион, даже реализованый, еще не дает гарантий, что компания будет успешной и эту инвестицию можно будет реализовать.


Я работал около трех в стартапе, контрактором. Опцион на момент моего ухода из компании стоил около $27k (поскольку стартап все время своего существования был прибыльным, нет возможности ставить цену акции в опционе нулевой). В этом случае даже опцион рассматривается как инвестиция — мне необходимо вложить $27k чтобы превратить опцион в акции, затем со временем, если компания выйдет на IPO или будет куплена (событие "exit"), я смогу продать эти акции, заплатить налоги и получить прибыль. Т.е. даже в случае рабочего, прибыльного стартапа с продающимся продуктом для опционов остается много "если", прежде чем этот вид "компенсации" превращается из ваших часов на роботе и денег в прибыль.


Для тех, кому интересна тема опционов, вот пара хороших ссылок:


Для решения это проблемы, некоторые компании в США ввели два больших типа сотрудников: non-exempt и exempt
Первый тип отличается следующими вещами
— как правило это не инженеры
— у них строгий график работы
— у них может быть строгий дресскод
— их задачи и цели имеют четкое описание и как правило их можно легко контролировать
— любая переработка оплачивается как сверхурочные

Второй тип
— здесь как правило все инженеры/синьоры/менеджеры
— нет строгого графика работы, но он часто регулируется фиктивно, путем назначения регулярных митингов в определенное время, не обязательно в «нормальные» рабочие часы. Но присутствие в офисе во время митингов не является обязательным, хотя и желательно(живое общение всегда лучше)
— может не быть дресскода
— задачи ориентированы на достижение цели в определенном временном промежутке (недели или месяцы)
— переработка отсутствует как класс, из-за того что требуют решить задачу, а не просидеть на работе
Мне очень нравятся простые примеры какой-то новой фичи, когда наглядно показывается, как раньше было всё плохо, а с новым нововведением стало всё хорошо. Пример с суммой чисел — это не то, чтобы я хотел видеть для асинхронных потоков.
Исправляем ситуацию… Допустим, у вас есть следующий метод
IEnumerable<FileResult> ReadFiles(string[] fileNames)
{
  foreach(var name in fileNames)
  {
    yield return ReadFile(name);
  }
}

Видите ключевое слово yield? В нем все дело.
Теперь вы узнали о чудесной конструкции async await и хотели бы применить ее к данному методу. И у вас даже есть новый метод ReadFileAsync.
Вы хотели бы, конечно, написать что-то такое
async IAsyncEnumerable<FileResult> ReadFilesAsync(string[] fileNames)
{
  foreach(var name in fileNames)
  {
    yield return await ReadFileAsync(name);
  }
}

Так вот! Раньше так нельзя было написать. А в C# 8 можно.
Я так и делал. Там нету «Services».

Сейчас опытным путем смог найти этот «Services».
Судя по всему для того чтобы это окно было доступно и видно (в том числе при поиске команд), нужно чтобы существовал хотябы один сервис.
То есть нельзя открыть «пустое» окно сервисов.

Я в новом проекте сделал себе коннекшн к базе. После того как его создал, это окно сразу появилось (и также опция Services в поиске стала доступна).
Они у вас и без маркетинга, кхм, довольно популярны.
git-awards.com/users/search?login=0xd34df00d
Блин, про контекст в ответе — я лет пять учился. У нас даже был жанр писем «почему нахер», когда я сначала давал ответ, а потом объяснял длинным письмом, почему так. Так вот, правильно делать наоборот, сначала объяснять, потом давать ответ. И этому нас научил иностранный партнёр, который отказал по 10 лицензиям из 10, и по каждой сделал это так красиво, как будто подписывал с нами миллионный контракт.
Ну на пальцах основные отличия для новичка, который не знает, что «потрогать» первым.

1. Vue не требует вообще никакой инфраструктуры, его можно воткнуть в существующий сайт с вордпрессом на шаред php хостинге, особенно если вы в курсе, что ослик сдох. Для реакта и ангуляра надо где-то поднимать ноду, npm/yarn, webpack/parcel, а потом два дня разбираться, чем babel/core отличается от babel/core и почему на первом create-app не заводится. Ну то есть какой-нибудь бандлер потом, перед выпуском в прод, настроить придётся, но это будет потом, и для vue достаточно будет parcel с нулевой конфигурацией.

2. Vue не требует изучать новые языки, работая на чистом HTML и JS. Гипотетически реакт тоже так может, но по факту 99% примеров и готовых react компонентов используют JSX и ~50% — Typescript. Это всё заметно увеличивает порог входа.

3. Vue не настаивает на функциональной парадигме, его вполне устраивает ООП. Если вас пугают выражения типа
let b = f => g => h => x => f(g(x))(h(x))
в реакте будет сложновато. При этом, если вам нравятся god object-ы на 100500 полей и методов, которые отвечают за всё, включая состояния кнопок, то vuex (аналог redux/flux/...) вполне себе есть, берите и пользуйтесь.

4. Следствие п. 3 — двусторонние биндинги. Они просто работают. Вам не надо, как в 90-ых, писать handleChange/handleKeyUp/… для каждого html элемента, а потом городить UNSAFE_ComponentWillRecieveProps и делать прочие приседания в скафандре. В результате наличию этой и других мелких сладких плюшек (например, стандартного роутера из коробки) кода на vue получается стабильно раза в 2-3 меньше, чем в таком же проекте на реакте, а пишется он быстрее.

При всём при этом реакт, конечно, дико распиарен.

Я спустя 3-4 года возни с redux пришёл к таким выводам:


  • Action types не только не нужно хранить отдельно от action creators. Их вообще не нужно делать. Для чего они могут пригодится? Для того чтобы иметь в рамках одного типа несколько фабрик action-ов. На моей практике такой случай не наступил ни разу. Могу смело сказать, что в 99% это просто бойлерплейт. Мусор. Мусору нечего делать в кодовой базе. Хотите глоссарий экшнов — автоматизируйте это. Как связывать reducer-ы с action-ами? Очень просто импортировать actionCreator-ы там где у вас reducer-ы и цепляться к ранее установленным (автоматически) actionCreator.type. Эти не сильно простые шаги уменьшат боль при написании redux приложений раза в 2.


  • Держите в простых случаев reducer-ы там же где и actionCreator-ы. А сложных случаев избегайте (дробите). Может показаться странным, но это радикально уменьшает количество бойлерплейта и упрощает поддержку кода. При этом различные слои не путаются, просто лежат ближе. Недостатков пока не выявил. А вот разного рода селекторы бывает полезным вынести отдельно, т.к. их иногда может 3\4 от кода набраться и они не привязаны ни к каким экшн-тайпам.


  • Используйте proxy в reducer-ах. Это невероятным образом улучшает как кодовую базу, так и экономит ваше время. Мутабельный код с преимуществами иммутабельного. Лучшее что я видел для redux. Реализация довольно простая, да и есть готовые решения. После внедрения бизнес-логика перестаёт выглядеть как тихий ужас.


  • Забудте про switch-case. Ден привёл в качестве примера и понеслась. Преимуществ у них похоже никаких, но все их пишут и пишут. Куда удобнее держать привязку action-type -> handler(state, action, rootState)


  • 1 action = 1 handler. Не прогонять каждый action через все reducer-ы. Принудительно привязывать обработку задачи к одному handler-у. Делает код куда более предсказуемым. Это одна из важнейших вещей в redux-е. Как это обеспечить? Ну например держать путь к reducer-у в action.type. Хотя тут много вариаций.


  • Поменяйте сигнатуру каждого редьюсера с (state, action) на (state, action, rootState). Это позволит избежать тех хаков, когда вам для изменения под-части стора не хватает данных из другой ветви стора, и вы жутко извращаясь пихали эту логику прямо в actionCreator или выше. Это бессмысленный бред. При этом разумеется из одной ветки стора на другую повлиять нельзя. Цепляться не обязательно к rootState, тут надо смотреть на ваш IoC


  • Используйте нормализацию. Ну тут много про это писали. Это архиважно


  • Используйте memo, useAutoCallback, useAutoMemo, PureComponent и прочие примитивы с shallowComparison. Это азбука производительности вашего приложения. Очень помогут weakMemoize-ы разного рода. Селекторы, линзы и прочее. Обычно в серьёзном приложении таких утилит\помощников скапливается много.


1
23 ...

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Registered
Activity