В недавнем разговоре с моим другом мы подняли интересный вопрос, с которым наверняка сталкивался каждый senior и lead при приеме нового человека на работу, в команду или даже просто в своей команде: как оценить реальный уровень программиста. Мой друг высказал интересную, но все же шуточную идею: junior хочет все переписать заново, middle и выше уже начинают понимать, что переписыванием заново проблема не решается, а за само переписывание клиент/руководство деньги просто так платить не будет. Однако в каждой шутке, как известно, лишь доля шутки: я сам работал с ребятами, которые хотели переписать весь проект или какую-то его часть за несколько недель или дней, аргументируя это тем, что их вариант будет работать лучше. Я на собственном опыте не раз убеждался, что навыков у подобных junior/middle людей просто не хватит на реализацию задумки, а предложение переписать возникает лишь за отсутствием других навыков, кроме написания кода с нуля. Люди посильнее никогда не стремятся переписать все. Они более трезво оценивают сложность задачи, свой уровень и уровень команды в целом, и, что самое важное, обладают навыками рефакторинга, которыми еще не обладают junior'ы и многие midlle'ы. То есть они могут, при необходимости, просто изменить нужную часть приложения, причем, как правило, в процессе имплементации новой функциональности, чтобы а) не напрягать никого оплатой/продажей отдельных тасков на рефакторинг, б) протестировать измененный функционал в комплексе вместе с тестированием нового. Второе, конечно, не всегда возможно, так как изменения могут быть глубоко в ядре, но тогда на помощь приходят unit-тесты, о которых эти люди, опять же, знают и умеют применять.
Итак, к чему это длинное вступление? К тому, что оценка уровня программиста очень сложная штука и очень сложно загнать кого-то в существующие рамки junior, middle, senior, lead, architect, etc. У меня есть свое видение данного вопроса, которое я сейчас изложу, но наверняка у читающих этот пост людей будет свое, дополняющее или опровергающее мое, и мне будет интересно его услышать.
Я не хотел бы сейчас останавливаться на моменте принятия незнакомого человека на работу или проект и попытке определить его уровень. Во-первых, для начала нужно выработать какие-то критерии оценки уровня в своей голове, чтобы потом умело их применять, а, во-вторых, пост тогда превратиться в сборник советов для собеседования, а их и так вагон и маленькая тележка. Также я специально не буду затрагивать личные качества программиста, такие как ответственность, исполнительность, коммуникабельность, быстрая обучаемость и др. Эти качества также можно и нужно развивать, но это тема отдельного разговора. Поэтому коснусь лишь непосредственно понимания уровня специалиста, которое потом можно использовать в различных ситуациях.
В данный момент в различных фирмах существуют разные подходы к оценке. Где смотрят лишь на технические знания, заставляя сотрудников сдавать тесты, где опираются на мнение руководителя, где проводят комплексную оценку, опрашивая сотрудников, руководителя и подчиненных по различным пунктам. Но практически везде забывают одну важную вещь, которая вроде бы лежит на поверхности, но ведет себя как потерянные очки, которые потом оказываются на носу: в программировании, как и во многих других сферах деятельности, нельзя давать единственную оценку уровню человека, можно давать лишь среднюю, выведенную определенным образом из менее общих оценок. Это как в английском языке: человек с reading и listening на уровне upper-intermediate может иметь pre-intermedite в общении и vocabular’е. Такого человека и обучать нужно соответствующим образом: с большим упором на менее развитые области. То есть, алгоритм оценки должен выглядеть приблизительно следующим образом: разбиваем необходимый набор знаний/умений на группы (критерии), оцениваем независимо каждый критерий и затем собираем все воедино в соответствии с необходимой формулой, используя те или иные коэффициенты усиления для критериев различной степени важности.
Второй ошибкой является сам набор критериев оценки. Почти всегда в таких случаях рассматривают лишь знание человеком различных технологий, паттернов, подходов, методологий, на оценку чего направлены различные тесты. В то время как оценивать нужно не знание, а понимание этих вещей. Хороший программист может не знать технологии JSP или JSF, т.к. он никогда в глаза не видел Java, но при этом, хорошо понимая принципы web-программирования и имея опыт ASP.NET или PHP, он с легкостью сможет разобраться со сложной проблемой и изучит новую технологию или язык очень быстро. Это как в школе: щелкать однотипные задачки может научиться практически любой, а вот понимать предмет на уровне, достаточном для решения нестандартных олимпиадных задач, могут единицы. То есть если человек знает, что есть определенный набор событий в жизненном цикле ASP.NET-страницы, это хорошо, но это junior уровень. Middle уже должен не просто использовать эти события, но и понимать, что происходит до них, и что их вызывает и с какой целью (что такое http-запрос и http-ответ, как они выглядят, что такое конвейер и что такое класс страницы вообще). Задача senior'а же уметь видеть полный поток выполнения запроса, знать особенности, понимать на более глубоком и абстрактном уровне все процессы, происходящие здесь, чтобы суметь в случае надобности разобраться со сложной проблемой. Именно на уровне понимания, на мой взгляд, и проходит одна из важнейших границ оценки специалиста.
Еще одним важным умением, которое приходит лишь с повышением уровня и может рассматриваться как некоторый критерий этого уровня, является умение перемещаться между уровнями абстракции. Junior-программисты часто не видят дальше своей маленькой задачи и куска кода, который они сейчас пишут. Из-за этого их код и отличается некоторой непродуманностью и их часто приходится поправлять, просить перенести тот или иной код в другой класс или даже на другой уровень приложения. С опытом, программист учится выходить на более высокие уровни абстракции: сначала на уровень понимания класса, потом на уровень взаимодействия между классами и объектами, как правило, при этом на ходу изучая паттерны проектирования. Затем приходит видение слоев и частей приложения, взаимодействия между ними и, наконец, умение видеть архитектуру и дизайн приложения в целом, с высоты птичьего полета. Если оценивать очень грубо, я бы сказал, что на этом этапе программист выходит уже на уровень middle+ или даже senior. Самое важное здесь: умение быстро перемещаться с уровня высокоуровневой архитектуры до уровня какого-нибудь куска кода и обратно, комплексная видимость кода приложения. Конечно, в крупных и даже средних приложениях очень сложно знать весь код, но это и не нужно – достаточно просто понимать, что делает тот или иной модуль или слой, а лезть ниже стоит лишь тогда, когда это действительно нужно. С этим сильный программист справляется без особого труда. Кроме того, умение видеть приложение в целом, пусть даже без особой степени детализации – это одно из самых важных умений lead'а и architect'а, без него далеко не уедешь.
С предыдущим умением также тесно связан т.н. системный анализ: умение анализировать задачу/требования, разбивать их на подзадачи, оценивать последние и создавать архитектуру приложения (то есть еще и выполнять некоторый синтез). Здесь также нужно уметь видеть взаимосвязи между задачами, требующими выполнения, и существующим либо будущим кодом. На этом уровне мыслят в основном программисты с уровнем senior и выше, которым часто приходится заниматься подобными вещами.
Еще один важный навык – умение писать качественный и продуманный код. Этот навык включает в себя целый комплекс других умений: знание и применение объектно-ориентированного дизайна и архитектуры, паттернов проектирования (естественно, в меру), рефакторинга, best patterns and practices в той или иной технологии, умение читать код глазами и смотреть наперед, предупреждая возможные ошибки и предусматривая дальнейшее расширение приложения. Все это приходит с опытом и желанием учится и в разной степени развито у программистов всех уровней, начиная от junior'а и заканчивая lead'ами и architect'ами.
Также нельзя оставлять в стороне и понимание процесса разработки. Процесс разработки серьезного ПО – это в 99% случаев командная работа, которой нужно управлять. Неуправляемые проекты очень часто превращаются в проекты разной степени безнадежности (привет всем «камикадзе»). Выбор правильной методологии, планирование работ в соответствие с ней – задача программистов не всех уровней, это работа людей уровня senior+, но понимание этой методологии, своей роли и задач в разработке очень полезно. Если мы сейчас пишем код, значит, мы пишем код, если фиксим баги, значит, фиксим баги, а не кто в лес, кто по дрова. В слаженно работающей по определенному плану команде, как правило, здоровая рабочая атмосфера и авралы случаются очень редко. По уровню данного понимания также можно оценить уровень специалиста.
И напоследок скажу еще об очень важном навыке: это навык постоянного саморазвития и расширения собственного кругозора. Развит этот навык у всех в различный степени. У кого-то есть желание изучать новые технологии и языки, читать книги, статьи, новости, технические блоги, слушать подкасты, смотреть вебкасты, ездить на конференции, постоянно быть в курсе событий и пробовать что-то новое, у кого-то – нет. Или да, но в меньшей степени. Однако тем, кто пренебрегает этим навыком, стоит сказать лишь одно: в индустрии, где действует закон Мура, нужно стараться двигаться с той же скоростью, иначе рискуешь остаться на обочине. Не в ущерб семье, личной жизни и хобби, ни в коем случае. Это вещи более важные и никакая работа не должна заменять человеку его настоящего развития, становления как личности или даже просто отдыха. Мы все же должны соблюдать разумный баланс в известном противоречии: жить, чтобы работать, или работать, чтобы жить. Но если уж мы все как минимум 8 часов проводим на работе, то пусть хотя бы малая толика этого времени уйдет на ваше развитие, как специалиста – это будет выгодно и вам, и вашему работодателю. Если не текущему, значит, следующему, который будет понимать подобные простые вещи.