Junior — роскошь

.. а не ресурс разработки Junior — человек, которому вы не можете выдать задачу сложностью выше некоторого уровня, если хотите, чтобы задача была решена в нужные вам сроки. Таким макаром в разных монастырях один и тот же человек может быть ранжирован не одинаково. В Кукусофте он middle, в Почтоваре он junior, а в учреждении для общественного воспитания детей дошкольного возраста и вовсе senior. Зависит от задач и сроков.
Ещё три исходящих пункта.
Раз. Джуниор (впрочем, как и любой другой) интересен тогда, когда для него есть фронт задач его уровня. Иными словами, стоимость их решения адекватна.
Два. Джуниор интересен тогда, когда из него хотят и могут [почти] любой ценой сделать что-нибудь другое. Характерно для больших компаний, выращивающих себе кадры, особенно штучные (тот же ШАД Яндекса примером).
Три. Джуниор интересен тогда, когда интересен не задачами и не ростом. Бывают занятные схемы. Скажем, вы аутсорсер, по контракту оплачивают работу с учётом занятых на проекте голов, выгодно эти головы набрать и демонстрировать. Это Вася. У него димплом МГУ, он джавист, уважаемый Джон Смит, похлопайте Васе и перечислите нам очередной транш. Что там за знания у Васи, чем он реально занят… никого не волнует. Такие схемы обсуждать не будем, достаточно того, что оно бывает и к разработке не относится.

Ещё ремарка про стоимость джуниоров. Давайте на пальцах следующую формулу зарплаты изобретём (почти по рынку, хоть для красоты округлил): J(unior) = n, M(iddle) = 2*J, S(enior) = 2*M. Это вот зарплата. Но работодателя интересует стоимость решений. Если junior делает софт 4 месяца, а senior тот же софт за 1 месяц, видим смешное: junior выпустил продукт на три месяца позже при senior’ной стоимости решения.
Слишком чистенько. На деле живые джуны делают ещё дольше и требуют ещё больше вложений. Они перетягивают на себя внимание middle+ (code review, консультации). Плохо интегрируются с нужной бюрократией (тексты коммитов, тикеты в JIRA). Плохо понимают командную работу (тусить в изоляции, забив на состояние мира вокруг — штатное состояние). Понимание ответственности на нуле (для них часто по воображаемым последствиям примерно равны «мама, я застелил постель» (не застелил) и «Аристарх Петрович, я протестировал все изменения перед выкаткой» (не все, не протестировал)), что добавляет рандома в production.
Всё это вместе с исправлением, обучением и банальным надзором замедляет работу остальных, что влияет на стоимость уже их решений. И, что прикольно, всё это в какой-то момент может оказаться пустотой — то вдруг оказывается, что чувак не подходит профессии. Или у него прошло увлечение и теперь он хочет на лыжах кататься. Или просто зайку не ценят и потому зайка уходит в монастырь. Или начитался про успешные стартапы и уходит в загул пилить Super Duper ToDo Tracker, который обязательно поглотит рынок.

Также нередко джуниоров, если они прям юные, надо учить:

  • жить («Сань, давай в будний вечер ты не будешь бухать до похмелья с утра, тебе два критикала срочно разрулить»),
  • общаться («Олег, заказчик не твой друзяшка со двора, давай не бычить и вообще полезно быть вежливым»),
  • взрослеть («Стёп, ты же обещал? Обещал. Не выполнил и знал заранее, что не выполнишь. Давай в следующий раз ты подойдёшь и скажешь заранее, что не успеваешь, чёт придумаем»)
  • и матереть («Филь, вот чего ты молча в пол смотрел? Тебя Иваныч сожрать собирался шоле? Нет. Голову поднять, факты озвучить, логикой задавить, в глаза смотреть спокойно, задачу не ты просрал, не тебе отвечать»).

И ещё куче шняг. Нет, в целом-то это не так уж напряжно, если не вспоминать, что окружающие на работу нанимались не любящими родственниками приёмным детишкам, но разработчиками / лидами. А то же лидство вопреки сладким фантазиям не включает в себя изготовление мужей из мальчиков.


Теперь подумайте и себе честно ответ: нафига всё это работодателю? Обычной софтварной конторе от гаражика до «это здание всё наше». Не приюту. Не благотворительному фонду. Не школе для одарённых детей. Не яростной молотилке кадров, в которой в день сто страниц копипасты. Вот нафига? Middle и senior выгоднее. Головняка с ними заметно меньше. Рандома в проде заметно меньше. Ставить их на путь истинный тоже проще, бойцы уже биты жизнью, могут гонор в карман спрятать и таки сделать то, что надо, а не «я так вижу». Прогноз работы с ними тоже проще — если до middle добрался, есть куда толкать и выращивать. Потому в общем случае джуниоров не нанимают. Убыточно. Проблемно. Результат не спрогнозировать. Нафиг надо.
Исключения бывают, безусловно (особенно когда у исключения «глаза горят», учебники от зубов отлетают и в анамнезе годный код на GitHub’е, тут прям удовольствие смотреть, как талант раскрывается). Но меня подбешивает, когда на голубом глазу говорят «а чё, ну наберите роту джуниоров, воспитайте, вот вам и будут кадры». Нет, спасибо. Сами набирайте. Все люди хорошие, братья, друзья и ромашки, но иногда полезнее тикеты вовремя закрывать, а не переоткрывать по десять раз, выполняя гражданский долг матери Терезы.
PS. Конечно, вы не такой junior. Это какие-то другие такие. А вы самый умный, самый хороший, самый клёвый junior в мире.

Python для собеседований

Однажды задолбался задавать на собеседованиях одни и те же вопросы без fun’а, родил функцию на Python. Веселился, придумывая. Кажется, решавшие задачку тоже получали свою порцию.
Собсно, вот код (Python 3.x):

import 'os'

func readFileId(names=[], mode):
    _ = ''
    id = -1
    for n in names:
        with os.open(n, 'w') as f:
            _ += f.read()
        f.close()
    print 'default: ' + id + ', actual: ' + _
    return id ? _ : id

Надо найти в нём ошибки. В зависимости от упоротости и перфекционизма количество ошибок от X до Z (подумал и решил таки не публиковать числа, лишняя подсказка получается). Кому и игнор PEP8 спать не мешает.

Суть упражнения (вполне типового, похожим джавистов на сертификациях кошмарят) в следующем:

  • Проверка знания языка.
  • Проверка внимательности.
  • Проверка умения думать над кодом.
  • Иногда показывает уровень чувства прекрасного.

Т.к. собираюсь написать более задорный вариант, этот «палю». Применять его больше не буду. Развлекайтесь.

PS. Тем, кто не согласен и у кого что-то не получается: пжлст, не пишите мне, что вы не поняли код, что это плохое упражнение и прочее. Значит, не для вас. Не беда.

Профессиональная самооценка

Один из неловких моментов: человек считает себя senior’ом, а ты по итогам считаешь, что он в лучшем случае серединка middle, и вот надо как-то это обосновать. Неудобно всё это, травмирующе для обеих сторон. Лучше, когда человек оценивает себя адекватно, актуально, объективно. Чтобы после десяти «не знаю» и «не помню» не собеседующего странным считал, но задумался о повышении квалификации.
Сузим контекст. Пусть Java (язык), JDK (библиотеки), JVM (виртуальная машина). Как джависту понять, на каком уровне он всё это знает?

Во-первых, сертификация. У Oracle три уровня: Associate (junior), Professional (middle), Master (senior). Попробуйте их сдать. Как вариант, можно купить mock certification у Enthuware и потренироваться. Или осилить книги вроде OCA: Oracle Certified Associate Java SE 8 Programmer I Study Guide: Exam 1Z0-808 или OCA Java SE 8 Programmer I Certification Guide. После чтения задуматься: да, обо всём этом спрашивают и всё это считается нужным для подтверждения уровня. Если вы не согласны и можете несогласие аргументированно оформить в текст, напишите в Oracle. Быть может, к вам прислушаются.
Слышал мнение, что никто сертификацию не сдаёт, никому не надо и т.п. Так вот, количество сертифицированных приближается к миллиону. Последнюю статистику нагуглить не удалось, но вот текст от Oracle времён семёрки: Java Programmer Certification: Java SE 7 Certified Programmers И да, работодатели тоже с интересом смотрят на сертификат.

Во-вторых, собеседования. Если вы являетесь senior’ом, для вас не составит труда за несколько месяцев пройти senior собеседования в top 20 работодателей. Вроде бы мороки много, но уверяю, оно того стоит. Сначала может оказаться больно и обидно, но после здравого размышления всё становится на свои места. И, грубо говоря, либо 20 человек признают ваш уровень, либо вы спуститесь на землю. Ну или затаите обиду непризнанного гения, что тоже бывает.
В top надо идти потому, что у них есть выбор, а вокруг десятки разработчиков, с которыми можно сравнить. И если местные senior’ы среди ночи легко ответят на вопрос «как выглядит integer underflow в Java», сам собою формируется некоторый стандарт уровня. Вы не можете на подобное отвечать? Окей, возможно, вы и senior, но не нашей мануфактуры.

В-третьих, актуальные учебники. Ну т.е. вот лично мне персонально индивидуально кажется странным, когда специалист, декларирующий знание языка, плавает уже в букварных темах, но знаю, есть считающие это нормальным. Каждому своё, конечно, а всё же рекомендую память подновлять. Открываете. Читаете. Чем больше «ого», «ух ты» и «вона как», тем больше «мда» в голове вас собеседующего.
Сюда же включите ознакомление с профильными курсами топовых вузов США. Они регулярно обновляются, ну и качеством выше отечественных. Сравните их требования знаний студента с вашими требованиями к себе.

В-четвёртых, конференции. Их полезно смотреть и слушать. Умные люди отбирают доклады умных людей, чтобы умные люди послушали. Послушайте и вы. После каждого доклада говорите вслух: «озвученная тема не нужна, не интересна, никто не использует, да что за бред вообще, это не надо знать». Чем менее смешной вам будет казаться эта фраза, тем дальше вы от senior Java, например.
Понимаю, тот ещё показатель. Но умиляет же, когда Шипилёв, например, собирает сотни слушателей, зал впитывает, статьи пишутся, софт делается, а потом мимоидущий senior expert guru Java developer роняет, шо то никому не надо. В общем, на этом оселке тоже не мешает после всего остального сверить себя с внешним миром.

В-пятых, определение. Подумайте и последовательно сформулируйте собственные определения senior, middle и junior. Именно в таком порядке. Опишите обязательные знания и умения уровней. Только честно и злобно. Словно перед вами сто кандидатов, надо нанять двоих и от этих двоих зависит, выйдет ваш бизнес на IPO завтра или через год. Сделали? Ожидаемо примените к себе. Всё хорошо? Теперь то же объективно примените ко всем своим знакомым разработчикам. Откалибруйте шкалу, попробуйте посмотреть на каждого через оценку его знаний в каждой области. И снова примеряйте к себе.
Надеюсь, что вы определили уровни не через скорость гугления неизвестного. И здорово, если вам хватило мудрости не определять через «о, я не умею в рекурсию, значит, настоящим senior’ам рекурсия не нужна».

Всё это я в какой-то степени прошёл. Разве что собеседований мне хватило и трёх, чтобы понять, что после двухлетнего перерыва был самоуверенным бревном, а не Java senior’ом. Правда, сейчас тоже вряд ли потяну полновоенное собеседование, ведь есть ещё Spring, Hibernate, NoSQL, RDBMS, алгоритмы, Linux, сети… Да-да, всё то, что вы обязательно нагуглите, если вдруг понадобится. ^_^

Архитектура костыля

В учебниках и разговорах постоянно про гибкую архитектуру. Гибкость то, гибкость сё. И толком не формализовали, особенно если взглянуть уровнем выше: какую объясняющую формулу (и понятную всем) дать, чтобы она работала для любого софта? Вот чтобы для разлапистых бекендов, для фронтового фреймворка, для мобильного приложения, для десктопной игрушки и т.д.
Для себя я всё же вывел такое и применяю. Правда, потом бывает сложно коллегам пояснить, почему код выглядит так, а не эдак, ну да всяко лучше иметь работающий код, а не довольных коллег при неработающем коде.
Внимайте:

Архитектура является тем более гибкой, чем больше в ней мест, в которые вы можете воткнуть костыль без переписывания остального кода. Костыль — ветвление, хардкод, жесть категории «if user == petrov { kill all }».

И никак иначе. Остальное не работает.


Фигня в том, что реальный мир, с которым соприкасается ваш софт, с его реальными людьми и прочими занятными явлениями является миром костылей. Мы вынуждены компенсировать чужие ошибки, например. Вынуждены учитывать, что в окружении сервиса любой элемент может упасть в любой момент времени. Мы должны учитывать пьяного дядю Васю на буровом тракторе в Кукуевке, испокон веков стоящей на трансгалактическом кабеле связи. Бухгалтеров. Детей с их разрушительными лапами. Распинаться так могу ещё долго.
И вот всё это хоть как надёжно друг с другом интегрируется только потому, что в каждом сервисе есть вёдра if’ов. Даже если вы по наивной прозрачности мозга выпустили в свет хрустальный сервис, уже через год в нём будет вот это вот всё. Окажется, что в стороннем API ошибка (или ошибки, если считать таковыми разработчиков API). Или к вам зайдёт очень грустная помощница очень главного директора с просьбой больше не делать с её директором то, что мы задумали делать со всеми. Или вам очень-очень надо оптимизироваться, ужимаясь в худенькую квоту серверов. Или клиент пишет «отправлять вам запросы могу ТОЛЬКО ТАК, всего вам хорошего, держитесь». Или бага в базе данных (тикет болтается с 2013 года), а вы это обнаружили за минуту до выкатки. Или от вас очень захотели работающего рендеринга сайта на IE под Mac OS образца 2007 года.
Так нафига страдать нервами по факту? Заранее, всё можно предусмотреть заранее. Не упарываться по фабрикам, возвращающим фабрики (привет джавистам). Не унифицировать всё до нечитаемой одной строчки. Не стремиться избавлять код от лишнего (что нередко не лишнее, но те части нужной реальности, что не попадают в вашу чистую модель). Не городить тонну абстракций. Пара лет эксплуатации и на активно живущем сервисе вас проклянут, пытаясь не убиться в попытках сберечь красоту (забьют болт и начнут запросто костылить, что будет гораздо уродливее на фоне ваших абстракций).
Архитектура (и код) должна отражать реальный мир. Реальную задачу и её прогнозируемые вариации. API отдаёт пять видов ошибок (не смогли разработчики в унификацию, потому в одном случае код есть, в другом нет, в третьем список ID хардкодом в тексте сообщения, в четвёртом списка нет аще, в пятом код ошибки в некоторых случаях является кодом удачной операции)? Делайте пять классов на каждый вид. Не, блин, унифицируйте, блин. Завтра они добавят шестую ошибку. Послезавтра заказчик попросит в третьем варианте ошибки дополнять своими данными. И всё, хана вашим красотам.

Чем чаще пробую этот подход на проектах, тем больше нравится. Да, при первом и втором взглядах возникает ощущение избыточности кода. Наивности. Излишней прямоты. Ахаха, вместо фабрики абстрактных ящиков копипаста десяти ящиков, отличающихся… ну… тут породой дерева, тут гвоздиком, тут наклеечкой, а здесь немножко круглый. А могла быть фабрика! Могла бы. И, возможно, будет. Только через год-другой эксплуатации в бою. А то и три. А лучше десять. И то при достаточном экономическом обосновании. Ведь, что смешно, нередко эти десять ящиков ещё и работают лучше фабрик.
Слава костылю! Костылику слава!