Привет, Хабр! На связи команда «МТС Аналитика»: техлид Саша Бобряков и ведущий разработчик Рома Захаров. Со дня на день мы в MWS запустим собственный комплексный курс по Java, который создали в рамках внутренней образовательной платформы МТС Тета. Он предназначен для внутренних разработчиков и поможет вырасти из уровня middle в senior. 

Зачем мы вообще его затеяли? Нам хотелось систематизировать «коллективный опыт» компании, выровнять грейды, чтобы мидл в условной команде X владел теми же навыками, что и мидл в команде Y, а еще — дать коллегам надежную базу, чтобы они росли в своем направлении. Работая над курсом, мы и сами многому научились. Например, выступать перед камерой, беспощадно отсекать избыточное, а еще — находить общий язык с дизайнерами (да, разрабам это не всегда дается легко).

Сейчас мы на финишной прямой, и пока впечатления о процессе работы еще свежи, нам захотелось ими с вами поделиться. Расскажем, в чем вообще польза от таких курсов для компании, как мы строили программу, какие сложности были. И посоветуем, на что стоит обратить внимание, если в вас тоже не умер преподаватель (да и ученик).

Зачем нужны внутренние курсы

Рассказывает Александр Бобряков

Итак, почему у нас вообще родилась потребность сделать курс? Основные цели были такие:

  • подготовить структурированный материал для внутренней матрицы компетенции;

  • помочь руководителям сформировать индивидуальный план развития своих разработчиков;

  • позволить каждому сотруднику провести самодиагностику и целенаправленно закрыть разрыв между текущим уровнем и целевым грейдом;

  • расширить кругозор разработчиков, чтобы они познакомились с темами, в которых пока не сильны;

  • для бизнеса — решить боль передачи сотрудников между командами и снизить риски проекта;

  • продвигать культуру наставничества — опять же для обмена опытом.

Дальше подробнее раскрою некоторые тезисы.

Объединить опыт команд и создать общий майндсет

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

Бывает, на работе я слышу от коллег: «Ой, а зачем нам знать, как работают виртуальные потоки в Java? Бери и используй! Везде говорят, что получим только плюсы». Или: «Ой, а зачем понимать, как работают индексы в БД? Нам важно знать только зоны их применений! Это же голая теория». Но именно задачи на анализ проблем показывают связь теории и практики. Условно, если ты не углубляешься в производительность, то с трудом сможешь понять, почему твой код обработки http-запросов в отдельном пуле работает медленнее, чем ожидалось, а сервер при этом потребляет только 10% выделенного CPU.

Мы в MWS хотим, чтобы наши сотрудники не только понимали задачи с практической точки зрения «бери и действуй», но и имели теоретическое подкрепление, как именно сделать правильно. А еще — могли аргументировать свое решение.

Это мы и решили показать в курсе: практика сильно связана с теорией. Мы считаем, что хорошая теоретическая база дает возможность более профессионально решать задачи, замечать проблемы еще на старте разработки, а не постфактум. 

Нужно развеять миф, что теоретические знания никогда не пригодятся в работе.

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

Выровнять уровень разработчиков

Каждый руководитель хотел бы видеть в своей команде мидлов и сеньоров, которые полностью отвечают его представлениям о грейдах. Но в реальной жизни у всех свой опыт, сильные и слабые стороны — все это приводит к тому, что навыки мидлов из смежных команд могут отличаться, и это нормально. И все же если у вас работает человек, который позиционирует себя как мидл, его навыки должны отвечать четким критериям. Они, в свою очередь, должны быть прописаны в матрице компетенций.

Недавно я собеседовал внутреннего кандидата на повышение уровня с middle до senior, и мы пробежались по множеству вопросов, начиная с жизненного цикла разработки и заканчивая паттернами микросервисной архитектуры. По факту кандидат с трудом тянул даже на уровень junior матрицы и не мог ответить на самые простые вопросы в духе «Какие коллекции и для каких задач ты использовал в Java?» или «Что такое immutable-объекты?». После просмотра интервью и обратной связи руководитель смог трезво проанализировать сильные и слабые стороны своего сотрудника и понять, какие навыки нужно подтянуть, чтобы достичь желаемого уровня.

Учиться — это сложно и энергозатратно. Не у всех есть время анализировать рынок, сравнивать программы курсов и искать для себя самый выгодный вариант. Но когда программа разрабатывается прямо в твоей компании с оглядкой на внутреннюю матрицу компетенций, тебе будет легко включить обучение в план своего развития. А еще ты не рискуешь купить продукт «из воздуха» от инфоцыган: твои преподаватели — это внутренние сотрудники, которые прошли множество технических ревью и с которыми ты, возможно, уже работал на проектах. Ты знаешь, к кому и зачем идешь учиться, и всегда можешь обратиться с вопросом или за консультацией.

Здесь и дальше по тексту — несколько рандомных скринов из уроков
Здесь и дальше по тексту — несколько рандомных скринов из уроков

Помочь отстающим и подтолкнуть лидеров

За последнюю сотню проведенных собеседований Java-разработчиков как с внешнего рынка, так и при внутренних повышениях мы замечаем одни и те же сложности. В основном это:

  • Неумение аргументировать свое решение. Например, даешь человеку решить задачу на атомарность инкрементации счетчика, а он не понимает, как сделать выбор между Atomic и synchronized.

  • Нехватка опыта в проведении CodeReview. У большинства возникают трудности с тем, чтобы посмотреть код и подсветить любые замеченные проблемы. Кандидаты не видят даже самые очевидные проблемы уровня junior.

  • Неумение смотреть на задачу комплексно. Человеку трудно описать полный цикл — от локализации проблемы до ее исправления.

Внутренний курс поможет подтянуть наших сотрудников в этих направлениях, если они все-таки попали к нам на работу. И поможет расти нашим сотрудникам внутри компании. Пройдя его, они смогут оценить свой текущий уровень и понять, что прокачивать дальше, чтобы получить новый грейд.

Повысить лояльность и снизить текучку кадров

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

Менторам преподавание тоже помогает развиваться и повышать компетенции. У нас был случай, когда один из преподавателей взял в проработку тему, потому что сам хотел максимально в ней прокачаться. В результате он глубоко погрузился и собрал качественный структурированный материал.

Развивать культуру наставничества

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

Упростить жизнь разработчикам и повысить инженерную культуру

Когда я был мидлом, информацию приходилось собирать по крупицам из разных источников. Однажды знакомый архитектор посоветовал: «Читай любую техническую литературу, которая попадается под руку по твоей специализации и не только. Главное — не прекращать этого делать». И я упорно следовал этому совету. Вот только в некоторых книгах не хватало глубины или, наоборот, подача была настолько сложной, что я даже представить не мог, как все это применить в реальных задачах. Чтобы разобраться, приходилось много (нет, очень много) гуглить: искать публикации по теме, смотреть кейсы. Осознание пришло только со временем, когда на практике из разрозненных знаний у меня наконец начала складываться общая картина. И тогда я стал замечать, как теоретические принципы помогают принимать верные решения и аргументировать подходы в коде. 

Здорово, что теперь коллеги могут прийти к результату быстрее и комфортнее, не теряя времени на серфинг в интернете. Мы упаковали разносторонний опыт экспертов в осмысленную готовую программу и показали, как теория и различные практики работают на реальных задачах в бигтехе, дали готовый код — бери и внедряй у себя. Конечно, это не значит, что мы разобрали все темы в мельчайших подробностях, но точно собрали мощный базис для дальнейшего развития. 

Пример модуля веб-серверы. Что разбираем:

  1. Как работает веб-сервер

  2. Архитектура веб-серверов

  3. Веб-сервер на Netty

  4. Сравнение веб-серверов: Tomcat, Jetty, Netty, Undertow и так далее

  5. Spring Actuator

  6. Инструментирование приложения: добавление метрик (часть 1/2)

  7. Инструментирование приложения: добавление метрик (часть 2/2)

  8. Решаем задачи: «Плавный старт приложения на примере прогрева кеша с использованием Health Indicator»

  9. Решаем задачи: «Реализуем кастомную логику с Graceful Shutdown

  10. Тестирование механизма Graceful Shutdown с использованием TestContainers

Повысить инженерную культуру разработчиков мы решили через отдельный модуль под названием «Команда». На нем погружаем коллег в CodeReview, OnBoarding, работу с инцидентами и Postmortem, проработку архитектурных решений в виде ADR, Proof of concept и так далее. Опять же, на практике я регулярно сталкиваюсь с огромным количеством кандидатов, которые не знают или просто не используют ничего из перечисленного, хотя за плечами десятилетний опыт работы в разных компаниях.

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

Рубрика «любимые уроки»

Мой любимый модуль — по устройству памяти. Мне захотелось создать его после того, как я провел множество собеседований, где, по статистике, только 1–2% кандидатов в курсе, что есть что-то кроме Heap и Stack. У нас даже родилась шутка, что если кандидат назвал Heap и Stack — на общем фоне это смело мидл, а если произнес «Metaspace», точно сеньор. Других областей памяти обычно никто не знает.

В этом модуле мы подробно рассматриваем, какие есть области памяти, как их посмотреть, какие флаги настройки бывают. Пр��водим примеры с разбором, какая информация и куда будет записываться по мере выполнения кода. Обсуждаем всевозможные утечки памяти (не только в Heap), анализ метрик областей, показываем проблемы из нашего опыта и подходы к их решению. Например, разбирали утечку памяти при использовании библиотек для инференса ML-моделей: она происходит именно при вызове JNI-кода. Главная фишка модуля в том, что весь материал основан на собственном опыте. 

Как создать понятный и действительно полезный курс: лайфхаки

Рассказывает Рома Захаров

Разработать собственный внутренний курс — не поле перейти. Нужна команда заинтересованных специалистов, которые готовы серьезно вложиться временем и силами. При этом до финального результата может пройти немало времени. Спойлер: процесс хоть и долгий, но жутко интересный. Пока думаешь, как и чему обучать других, сам многому учишься.

Дальше я поделюсь основными советами, которые мы сами использовали при разработке курса. Возможно, вам они тоже пригодятся.

Анализируйте рынок

Чтобы подготовить нашу программу, мы погружались в тренды в IT, проводили собственное большое исследование: что сейчас популярно и востребовано, какие вопросы задают на тех же собеседованиях, с чем чаще всего возникают сложности у кандидатов. Серьезно копнули в программы других похожих курсов: изучили их сильные и слабые стороны, посмотрели, на чем авторы сделали акценты, брейнштормы, как бы мы могли усилить такую программу, чего в ней не хватает. 

Ну и еще нам было с чего начинать. Новый курс мы разработали для мидлов и сеньоров, но в компании уже был комплексный курс по Java — Junior to Middle. Разрабатывала его не наша команда, но для нас он стал берегом, от которого можно оттолкнуться. В нем была база, так что мы ориентировались на то, что у слушателей уже есть необходимые знания, и смогли сосредоточиться на реально интересных и глубоких концепциях с примерами из практики. Мы сами прошли его, кажется, несколько раз, чтобы зафиксировать, что получилось хорошо, а что — не очень. Какие темы разобраны детально, какие — подкачали.

Для нас было важно выстроить курс так, чтобы человек, который проходит его, точно понимал, зачем он впитывает именно эту информацию. Как она может применяться в работе, зачем изучать теорию, если кажется, что на практике это не пригодится? Поэтому в начале каждой лекции мы описываем решаемую проблему и мотивируем слушателя погрузиться в предлагаемые решения детальнее, чтобы спроецировать информацию на свой проект. Так что разработке курса предшествовала серьезная аналитическая работа, касающаяся не только самих знаний, но и рынка обучения в целом. 

Составьте четкий список навыков и компетенций, которые вы хотите развить у ваших студентов

Считайте, это ваша дорожная карта. Поможет в этом, опять же, анализ рынка и прежде всего — ваш опыт. Мы собрали свой список из пробелов, которые замечали в работе при проведении межкомандного CodeReview (когда писали всем очень похожие замечания) и на собеседованиях. 

Продумайте структуру и избегайте длинных уроков

Мы хотели, чтобы курс развивался постепенно — от сравнительно простого материала до более сложного. Сам сталкивался с таким: вот проходишь какой-то материал, первый урок у тебя понятный, второй — вроде бы тоже, а третий как будто вообще вырван из контекста, он даже по стилю не бьется с двумя предыдущими. Так происходит потому, что над курсом может работать большая команда авторов, редакторов, дизайнеров и других специалистов. Опять же, если не смотреть на программу в комплексе, получится как в басне «Лебедь, Щука и Рак». 

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

Мы очень старались проработать структуру так, чтобы уроки плавно перетекали друг в друга и чтобы у студентов не было пробелов, чтобы они открывали следующий урок уже подготовленными. Приведу в пример, как делали модуль по JIT-компиляции. 

Начинаем с предыдущего модуля про память, где затрагиваем различные области, включая Jit CodeCache. То есть тут у студента формируется общая картина, мы его подготавливаем и закидываем тезисы на будущее, а уже в следующем модуле отдельно рассматриваем JIT. Сначала даем самые простые вещи — например, разбираем компилируемые и интерпретируемые языки, это важно для контекста. Затем переходим к Java: к каким языкам она относится, в чем ее особенности, в какой момент появляется JVM, JIT и какие этапы проходит исходный код, прежде чем преобразуется в машинный код. Дальше идет уже погружение в устройство JVM и как устроена JIT-компиляция, но все развивается последовательно и сопровождается примерами.

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

Другой важный момент по поводу структуры — лучше, когда уроки недлинные. На полуторачасовые лекции сложно выделить время, а сконцентрировать внимание — еще сложнее. Поэтому мы ограничили длительность урока получасом.

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

Опыт — это круто, но важно уметь приоритизировать материал, оставлять только самое важное и не перегружать студентов. 

В конце концов мы пришли к такой структуре: лучше подробнее разобрать основной материал и дать отсылки на те или иные темы, в которые можно погрузиться самостоятельно в факультативном формате. 

Готовьте текст для уроков (или нет). Для нашего курса мы выбрали онлайн-формат. А это значит, что нужно было записать видеоуроки. 

Важно понимать: от подготовки лекции до ее записи может пройти существенное время, так что имеет смысл готовить сразу текст для суфлера или опорные примечания к слайдам, чтобы повторить накануне съемок. Можно, конечно, фристайлить, но формулировать мысли и тут же рассказывать бывает непросто, особенно на долгой дистанции. В этом смысле кому как удобнее: Саша, например, текст для суфлера не писал. А я подготовил, и мне это показалось достаточно удобным. С учетом того, что запись была не сразу после подготовки самого урока, мне перед выходом к камере можно было просто пробежаться по тексту для суфлера — и ничего не забылось.

Но сказать про минусы тут тоже стоит. Все-таки без суфлера речь и интонация получаются более живыми. Если производишь много контента, с суфлером в какой-то момент можешь поймать себя на мысли, что уже сам перестал вникать в то, что произносишь. Читаешь машинально. И если тебя кто-то отвлек и пришлось прерывать съемку, сложно складно стартануть с того же места. Придется читать все заново.

Смотрите на картинку в целом. Если вы создаете программу, ее уроки должны между собой сочетаться. Казалось бы, простая мысль, но на практике бывают инциденты. Иногда мы снимали лекции непоследовательно — например, если дизайнеры еще не з��кончили с версткой, а другие лекции уже были готовы или если мы могли уложиться в тайминг только с более короткой лекцией. И вот однажды у нас произошла забавная ситуация: у Саши были лекции подряд, на первой он с длинной стрижкой и в кофте, на второй — коротко пострижен, в деловой рубашке, а на третьей — снова с длинными волосами и в футболке. Как будто три персонажа из разных вселенных в одной и той же аудитории на одном фоне. Визуал не сложился, хотя сам рассказ получился складным, без потери мысли между лекциями, а ведь между ними прошло пару месяцев. 

Репетируйте текст лекции. Мне кажется, любому преподавателю будет полезно потренироваться перед тем, как записывать урок. Не все учителя на курсе могут иметь большой опыт публичных выступлений или преподавания. Даже если читать с суфлера, в какой-то момент можешь «залагать». Так что я старался репетировать заранее. 

Закладывайте время на запись — его всегда не хватает. Мы были ограничены двумя часами в студии: в авральном темпе можно записать четыре урока, но это нам ни разу не удавалось. Поэтому советую закладывать время с запасом. Чем больше есть времени в студии — тем более свободно и легко идет запись. Можно что-то переснять, отработать какие-то ошибки. Это всегда полезно, потому что прежде чем ваш курс увидят студенты и дадут обратную связь, пройдет немало времени. Так что надо записаться качественно. 

Всегда проверяйте сохранения. Совет написан кровью болью: однажды наши коллеги-операторы случайно удалили запись целого дня съемок. Пришлось сниматься заново.

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

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

Вносите как можно больше реальных примеров. Если объяснять, как информация, которую вы даете, помогает на практике лично вам или вашим коллегам, удержать внимание студента будет легче. Реа��ьные кейсы всегда работают. И да, кейс с разбором ошибок — еще лучше. Если расскажете, как из-за нехватки информации произошла проблема и как этого можно было бы избежать — сразу 100 плюсов к карме.

Помните про софт-скилы. У разработчиков с этим бывают сложности, хотя сейчас ситуация, кажется, лучше, чем лет 10 назад. Чтобы расти по карьерной лестнице, нужно не только писать код. Ты все равно так или иначе коммуницируешь с командой. Чтобы упростить эту задачу для разработчиков, мы включили в курс модуль «Команда» — Саша говорил о нем выше.

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

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

Если студент что-то не понял — значит, мы недостаточно понятно объяснили и программу нужно улучшить.

Привлекайте тестовую группу. Если разработка уроков затягивается на месяцы и даже годы, преподаватели могут потерять мотивацию от недостатка ОС. Процесс тянется, вам еще снимать и снимать, а хорошо получается или нет — неизвестно. Поэтому через каждые 2–3 модуля можно запускать тестовую группу, чтобы сразу получать обратную связь и обрабатывать ее. В следующий раз мы сделаем именно так.

Продумайте, когда и как именно будете выпускать модули. Мы сначала засняли все уроки, а теперь планируем выпустить их скопом. Но, возможно, есть смысл выпускать курс частями по мере готовности, сразу собирать ОС и отражать ее в уроках, над которыми еще работаете.

Делайте «независимые» модули. Так студенты могут учиться более точечно, смотреть только конкретную часть, которая их интересует. Сейчас у нас все модули тесно связаны, пока не усвоишь один — не поймешь другой. Но в будущем мы попробуем и другой формат.

Бонусом совет тем, кто проходит курс. Главное — не делайте долгих пауз между занятиями. Все уроки связаны друг с другом, и все они работают на раскрытие целого модуля. Завершили модуль — можно немного отдохнуть, взять паузу, поделать задания по модулю. 

Между модулями — отдыхаем, а внутри них — двигаемся уверенно, без остановок. 

Рубрика «любимый урок»

Мне больше всего понравился урок про JIT-компиляцию, и этому несколько причин. Во-первых, это первый модуль, который я стал готовить. Тогда я сам еще не до конца понимал, как лучше оформлять лекции и презентации, поэтому экспериментировал с форматами. Что лучше — сначала набросать все слайды, а потом прорабатывать каждый подробно или идти последовательно от одного слайда к другому? Оказалось, мне по душе первый подход, хотя, возможно, он более трудозатратный.

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

Если подытожить все вышесказанное, становится понятно, что внутренний курс — это не «просто поучить». Мы считаем, что он закроет пробелы в знаниях, поможет сильным специалистам расти внутри компании и создаст живой, постоянно пополняемый архив лучших практик. Да, путь от идеи до студии занял много сил и времени, но мы надеемся, это того стоило.

Если в вашей компании тоже зреет идея своего курса, наш вам совет — дерзайте! Это долгий, но окупаемый путь. 

Комментарии (0)