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

Покоцанные, но не сломленные, мы представляем проект, над которым работали полтора года по ночам. Курсы по программированию с задачами в online IDE и прагматичной теорией. Никаких сертификатов и гарантий трудоустройства. Сплошной хардкор и опенсорс!



Зачем это нужно?


Выучить новый язык – приключение дольше, чем на 20 минут. А раз так, возникает естественное программистское желание этот процесс оптимизировать. Чтобы за кратчайшее время получить максимум знаний для идиоматичной разработки на новом языке, свободного погружения в чужие проекты и код-ревью.

Напрашивается идея площадки с опенсорсными курсами, заточенными под разработчиков. Какое у нее принципиальное отличие от вайтишных морковок а-ля «питон за 3 месяца в рассрочку»? Площадка не вкладывает знания в клювик. Все, что она делает – не мешает учиться!

А выглядит это так. Разработчик читает актуальную теорию без воды и упрощений. И непрерывно выполняет практические задания. Их много. Но подаются они маленькими порциями.

Представьте: прямо по тексту глав курса идут online IDE с задачами. Прочитал абзац про незнакомую концепцию и тут же заполировал написанием кода! Причем для каждой задачи доступны краткая подсказка и полное решение.


Фрагмент главы «Функции высших порядков» курса по питону.

Так и родилась концепция проекта Senior Junior. Почему такое название? Да потому что каждый сеньор немного чувствует себя джуном, когда учит новый язык ;)

От идеи до запуска


Для воплощения идеи в жизнь собрались четыре бэкендера. С тех пор мы – C++ программисты днем, а ночью… все те же C++ программисты, но бороздящие мутные воды фулстека.

Первым делом мы определились, в каком формате хранить главы курсов и задачи. В приоритете – удобство для сторонних контрибьютеров, ведь курсы должны быть опенсорсными. Выбор пал на язык разметки markdown.

Чтобы в вебе рендерить markdown в HTML, мы воспользовались js-библиотекой markdown-it.


Слева – сырой md-файл главы по питону. Справа – то, как выглядит отрендеренная глава на сайте. И да, мы подвезли на сайт темную тему!

Чтобы разметить по тексту глав якори для ссылок, примеры кода и задачи, нам потребовалось расширить спецификацию markdown. И в этом нам помогла библиотека markdown-it-attrs: она позволяет навешивать на результирующий HTML свои CSS-классы, id и атрибуты.

Научившись конвертировать md-файл в размеченный HTML, мы занялись расстановкой по странице главы компактных online IDE. В них пользователи могут решать задачи и запускать тесты. Для этого подошла библиотека CodeMirror. При загрузке страницы скрипт находит размеченные HTML-элементы, скармливает их CodeMirror и встраивает IDE на страницу:


Online IDE для решения задачи в главе курса по расту.

…Однако сайт у нас появился далеко не сразу. Ибо нет худшей кары для бэкендера, чем выравнивать div по высоте. Фронтендом никто из нас заниматься не хотел, поэтому вначале мы вместо него запилили телеграм-бота.

Идея простая: в боте, как и на сайте, пользователь выбирает курсы, перемещается между главами, читает их и… пишет код! Для решения задачи нужно просто отправить свой код в сообщении.


В боте удобнее проходить курсы со смартфона, а на сайте – с десктопа.

Бота мы писали, конечно же, на питоне. Шучу. На C++, так интереснее. Более того, была велика тяга сделать свой велосипед для общения с сервером телеграма. Но мы взяли себя в руки и вместо этого подключили библиотеку tgbot-cpp. Запустили бота на арендованном VPS и вчетвером принялись тестировать весь цикл прохождения курса.

Сайт у нас тоже появился, но позже. Для этого пришлось приобщиться к клепанию темплейтов на django.

И вот во что превратилась наша площадка с курсами:



Код пользователей вместе с тестами запускается в изолированных контейнерах. Этим заведует специальный C++ сервис, который взаимодействует с движком докера. Общение происходит по HTTP.

Для нас это было новостью, но docker server предоставляет REST API (Docker Engine API), а консольные команды вроде docker run – всего лишь обертка над ним. За каждой из этих команд стоит один или даже несколько HTTP-запросов к движку докера.

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

На тот момент мы уже начали думать, как бы такой подход максимально обезопасить. Но не успели подрезать права учетки, из-под которой запускается код. Как результат – в контейнере легко было удалить часть важных файлов. Что и было с удовольствием проделано. Естественно, это привело к аварии при следующем запуске задач.

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

Запуск!


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

Поступили мы так, конечно же, напрасно.

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

Тут-то и начались голодные игры. Точнее, бескомпромиссные фаззи-тесты нашего бэка.

Первым пал телеграм-бот. Он ковался в жерле вулкана Modern Cpp и был готов к любым нагрузкам. Но не к изобретательности одного юного дарования. Оное вместо самостоятельного решения задачи и отправки кода в сообщении отыскало похожий пример в каком-то обучающем телеграм-канале. И форварднуло его боту.

Бот рассчитывал получить сообщение с заполненными полями chat и from. У пересылаемого из канала сообщения оба эти поля равны null. На проверку которого мы, конечно же, забили.

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

В таком состоянии мы и обнаружили нашего бота: валяющимся среди собственных core dump’ов и обрывков с логами “ERROR: Too Many Requests”. Интрига! Разматывать этот клубок и гадать, с какого перепуга телеграм нас заблокировал, было увлекательно. И поучительно.

Едва мы реанимировали телеграм-бота, тут же ринулись разбираться, почему примерно у одного пользователя из ста не получается зарегистрироваться. Затем фурами отгружали на прод исправления фактологических ошибок в курсах.



В сухом остатке «мягкий запуск» нам принес 700+ регистраций, несколько десятков постоянных пользователей и 100+ ценных отзывов. Ого, на наше детище позарились не только вайтишники, но и разработчики! У нас моментально открылось второе дыхание для работы над курсами.

Сейчас у нас уже готовы курс по питону и 6 глав курса по расту.

Python. Лучший для обучения. Худший для обучения


Как только питон ни называют. Универсальный клей – за удобство написания скриптов автоматизации и всякого рода обвязок.

Лучший язык для обучения – за внешнюю простоту и низкий порог входа.

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



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

Светлые и темные стороны языка мы постарались исследовать в 39 главах и 200+ задачах курса по питону. Нельзя сказать, что это удалось нам на 100%. Например, было трудно балансировать между прагматичным подходом к изложению и широким выбором тем, раскрывающих pythonic way во всей красе. Уважаемые питонисты, не стесняйтесь указывать нам на недочеты!

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

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

1. Сокращение объема кода и сужение области видимости переменной.
while (res := calc_next_val()) >= 0:
	print("Next iteration of calculation...", res)

2. Создание переменных «на лету», в том числе прямо при вызове функций.
min(a := 8, b := -2, c := 4, d := 0)

3. Переиспользование расчетов без заведения переменной в локальном скоупе. Например, при формировании коллекций.
query_stats = [q := query.strip().lower(), len(q), q.split()]

4. Ускорение list comprehensions.
normalized = [n for w in words if len(n := normalize(w)) > 1]


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

Rust. Самый обожаемый язык, не захвативший рынок


С 2016 года раст лидирует как «самый любимый» язык в опросах от Stack Overflow. Однако бурного роста вакансий для разработчиков на расте как-то не заметно.



Кто-то считает, причиной тому высокий порог входа в язык. А кто-то загадочно улыбается и отвечает, что всему свое время и нужно просто подождать.

Так или иначе, но раст столь же производителен как C и C++ благодаря отсутствию сборщика мусора. Но при этом гарантирует безопасность работы с памятью, безопасность типов и безопасность работы с данными из нескольких потоков.

Огромное количество ошибок отлавливается в расте еще на этапе компиляции. Уже и не говорю про такие плюшки языка как алгебраические типы данных, удобный подход к обработке ошибок, менеджер пакетов Cargo… Все это позволяет писать и рефакторить проекты на расте быстрее, чем на C++ и порой даже чем на питоне!

У нас готовы пока только 6 глав курса по расту. Но уже их хватит, чтобы составить первое впечатление о возможностях языка.

Например, вы узнаете, что условия и циклы в расте – это выражения. То есть условие или цикл возвращает некое значение. Хаскелистов этим не удивить, но выходцам из ООП-мира это порой сносит крышу.

Рассмотрим пример. Возьмем очень простую последовательность чисел, называемую «сиракузской последовательностью». Чтобы ее получить, нужно:
  1. Взять любое натуральное число n.
  2. Если n четное, поделить его на 2, а если нечетное — умножить на 3 и прибавить 1.
  3. Повторить шаг 2.

Гипотеза Коллатца гласит, что для любого числа n все закончится на единице. Эту гипотезу мы и проверим для значения 16. Напишем цикл, который возвращает количество шагов до получения 1 и максимальное значение последовательности, полученное во время вычислений.

fn main() {
    let mut value = 16;
    let mut max = value;
    let mut step = 1;
    let (step, max) = loop {
   	 if value == 1 {
   		 break (step, max);
   	 } else if value % 2 == 0 {
   		 value /= 2;
   	 } else {
   		 value = 3 * value + 1;
   		 max = std::cmp::max(max, value);
   	 }
   	 step += 1;
    };

    println!("total steps: {step}, max value: {max}\n");
}

total steps: 5, max value: 16

Обратили внимание, как цикл-выражение влияет на стиль кода? И это только цветочки с поляны раста. Далее вас ждут ягоды и грибы с удивительными свойствами.

Что дальше?


Итак, курс по питону у нас готов целиком. Работа над курсом по расту в самом разгаре. А недавно к проекту присоединился автор, приступивший к курсу по go. Stay tuned!

Курсы на нашей площадке мы будем развивать по нескольким направлениям.
  • Языки программирования, фреймворки, библиотеки. Kotlin, С++, C#… А как насчет щепотки функциональщины в виде Haskell?
  • Глубокое погружение в конкретный аспект языка. Например, для C++ напрашиваются темы «Конкурентность и асинхронность» и «Метапрограммирование».
  • Прикладные вещи. А вы когда-нибудь интересовались, как устроены современные поисковые движки? Нужно ли быть богом, чтобы написать компилятор? Что из себя представляет разработка СУБД?
  • Полезные ништяки – bash, git, vim. Многие ли владеют ими в достаточной степени, чтобы и работать продуктивно, и выпендриться при случае?

А что насчет новых фичей? Есть у нас парочка на примете: «вопросы с собесов» и «песочница» для экспериментов с кодом.

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

Присоединяйтесь к опенсорс проекту


Приглашаем поучаствовать в развитии курсов Senior Junior! В каком формате – выбор за вами:
  • Проходите курсы на сайте, в боте. Делитесь фидбэком. На сайте для этого в конце каждой главы есть специальная форма, а в боте — команда /help.
  • Присоединяйтесь к обсуждению проекта в нашем комьюнити.
  • Предлагайте свои варианты задач на замену неудачным. Мы рады новым issue и пул-реквестам на гитхабе.
  • Попробуйте себя в роли автора курса или ревьюера. Делиться знаниями – это офигенно!

Это – первый наш пост про Senior Junior на Хабре. А значит, самое время высказать свое мнение о проекте. Вэлком в комментарии ;)

? Спасибо всем, кто тестировал наши курсы, репортил баги и оставлял фидбэк! Отдельная благодарность Тиграну Басеяну (Black product owner) за ценные советы и критику. А также Владиславу Радченко, Михаилу Шварцбурду, Евгению Боровкову, Вадиму Демидову за поддержку запуска на Product Radar! И, разумеется, Диме Беговатову tw0face за возможность рассказать о проекте на его чудесной площадке для продвижения стартапов!

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


  1. Virviil
    11.04.2024 07:50
    +11

    Будучи сеньором, я:

    • Во первых могу поднять окружение с новым языком сам

    • Могу попросить написать простой алгоритм любую Copilot.

    Мне не надо учить синтаксис нового языка - я могу его в крайнем случае загуглить.

    Мне нужно знать экосистему и распространенные паттерны программирования. Те самые, которые показывают в твоем коде на Go, пришел ты из мира Java или из PHP.

    Ни того ни другого, как я понимаю, тут нету. Вот и напрашивается риторический вопрос: ...?


    1. Serine Автор
      11.04.2024 07:50
      +5

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

      В курсах по языкам мы не отвлекаемся на объяснение алгоритмов, каких-то классических структур данных и паттернов проектирования. Упор на особенности языка.

      Паттерны разработки на конкретном языке у нас в курсах есть, причем в количестве. Как раз чтобы не было такого "Программист на фортране может на любом языке написать программу на фортране" ;)

      Информацию про экосистему мы тоже даем.


      1. Sergey_Kovalenko
        11.04.2024 07:50
        +2

        Хочу послужить живым примером. Я ни разу не синьор. Все алгоритмические рассчеты могу сделать на плюсах после самостоятельного прочтения Лафоре, но вот беда, подключить библиотеку или вывести какую-нибудь картинку, тем более анимированную - это для меня нерешаемая задача. Я не хочу тратить годы, чтобы по экрану запрыгал мячик и при этом у меня есть прикладная задача (https://habr.com/ru/articles/738388/), которую я решил и хочу презентовать в виде анимированной картинки. Я предполагаю как-то нарисовать упрощенную дорожную сеть города, синими кружочками обозначить движущиеся по ней автобусы, красными и зелеными - появляющихся пассажиров и их места назначения, автобусы должны объезжать пары из зеленого и соответствующего ему красного кружочка. На плюсах могу для каждого кадра вычислить положения всех кружочков на карте. Но как это все нарисовать? Посоветуйте мне что-нибудь. Сколько времени займет обучение такому умению по вашим курсам?

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


        1. NemoVors
          11.04.2024 07:50
          +1

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


          1. Sergey_Kovalenko
            11.04.2024 07:50
            +1

            Спасибо Ваш за совет. Пару часов - это конечно очень оптимистично.
            .... 9 месяцев спустя )))
            Все специалисты думают о своих годами приобретаемых знаниях: "Да, ерунда, за пару часов освоить можно". Я вам так из любого известного мне курса математики за пару часов все его центральные результаты опишу. Только конструкции в голове за 2 часа не возникают: 3-4 страницы в день - уже хороший результат. Мне кажется странным, что нет какой-нибудь простой рисовалки, которая дополняет С++ просто абстракцией "альбомного листа" с каким-то набором базовых фигур и координатной сеткой.

            Если не найду решения полегче, придется, видимо, осваивать godot.
            Кстати, я смогу потом преобразовать мой результат в Gif?


            1. vavp123
              11.04.2024 07:50

              рисовалки, которая дополняет С++ просто абстракцией "альбомного листа" с каким-то набором базовых фигур и координатной сеткой.

              Возможно, вам поможет Фреймворк Qt для c++. Конкретно альбомный лист и базовые фигуры - QPainter. Для анимаций тоже есть инструменты


            1. NemoVors
              11.04.2024 07:50

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


        1. Serine Автор
          11.04.2024 07:50
          +1

          Я - математик, не программист и очень не хочу им становится

          В таком случае эти курсы вам не помогут. Они ориентрованы на разработчиков.

          По поводу описанной вами задачи. Финальная цель - анимированная картинка. А самостоятельное создание этой картинки именно путем программирования самоцелью не является. Так?

          Тогда напрашивается вариант задизайнить и анимировать картинку в каком-нибудь Adobe After Effects, Photoshop или одном из других инструментов. Второй вариант - составить ТЗ и отдать на откуп студии/фрилансеру.

          Ну и третий вариант. Посмотреть в сторону анимации в питоне. Вы упомянули C++ и намерение рендерить каждый кадр. Это 100% оверкил. А вот питон - язык, при разработке которого учитывается удобство для ученых. То есть тех, кто не хочет погружаться в программистские дебри, а хочет решить какую-то конкретную задачу.


          1. Sergey_Kovalenko
            11.04.2024 07:50

            Питон пробовал, как-то там все запутанно, что даже примеры из книжки не запускались. Ладно, разбогатею - отдам на откуп: пусть другие седеют )))


        1. hapcode
          11.04.2024 07:50
          +2

          Попробуйте Processing. Возможно, он подойдет под ваши задачи.


          1. Sergey_Kovalenko
            11.04.2024 07:50

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


        1. va1eb
          11.04.2024 07:50

          Чтобы не сильно погружаться можно попробовать это сделать в Wolfram Mathematica или в MATLAB.


          1. Sergey_Kovalenko
            11.04.2024 07:50

            Не знал, что Wolfram Mathematica позволяет делать программные анимации. Спасибо, гляну.


        1. Qvxb
          11.04.2024 07:50

          Можно попробовать скачать qt и посмотреть какие уже готовые примеры там есть, скорее всего там будет пример виндовс приложения с графическим интерфейсом с кнопками /картинками/анимациями и далее можно будет попробовать сделать свое на его основе.


        1. Shokweiv
          11.04.2024 07:50

          Для Вашей проблемы существует две графические библиотеки - SDL и SFML.

          Первая написана на C и использует процедурный подход к написанию кода. Вторая написана на C++ и использует ООП.

          Лично я пробовал только SFML и в нем из коробки есть всё необходимое вроде создания окна в пару строчек, система ивентов окна/мыши/клавиатуры, звуковая система, подгрузка изображений/спрайтов. Всё это ещё и кроссплатформенное


          1. Sergey_Kovalenko
            11.04.2024 07:50

            Здорово, что она еще и бесплатная.
            Честно, думал уже PNG нагенерировать проще, чем подходящий инструмент найти.

            В описании SFML меня, правда, пугает вот это:

            You might have noticed from the table that SFML modules can also depend on one another, e.g. sfml-graphics-s.lib depends both on sfml-window-s.lib and sfml-system-s.lib. If you static link to an SFML library, make sure to link to the dependencies of the library in question, as well as the dependencies of the dependencies and so on. If anything along the dependency chain is missing, you will get linker errors.

            If you are slightly confused, don't worry, it is perfectly normal for beginners to be overwhelmed by all this information regarding static linking. If something doesn't work for you the first time around, you can simply keep trying always bearing in mind what has been said above. If you still can't get static linking to work, you can check the FAQ and the forum for threads about static linking.

            If you don't know the differences between dynamic (also called shared) and static libraries, and don't know which one to use, you can search for more information on the internet. There are many good articles/blogs/posts about them.

            Ладно, есть знакомые программисты, зайду к ним в кармический долг ))))


        1. poogach
          11.04.2024 07:50
          +1

          Проект создания математических анимацией на питоне https://github.com/3b1b/manim

          Примеры анимаций https://github.com/3b1b/videos

          Человек, который это делает, ведёт канал на YouTube https://youtube.com/@3blue1brown?si=vCx4-h810Hfyoisj


          1. Sergey_Kovalenko
            11.04.2024 07:50

            Спасибо, если не получится по-другому придется изучить питон.


    1. Irkest
      11.04.2024 07:50
      +2

      Разработчик рано или поздно приходит к одному факту, что код приходится чаще читать, чем писать. Даже если тебе везет, и ты переходишь от одного нового проекта к другому, то всё равно потребуется смотреть чужой код: на code review, исходники используемых библиотек. Но гораздо чаще приходишь в проект, который существует уже не первый год, и в нём тонна кода, в которой придется разбираться. Как это делать без знания языка? На мой взгляд никак.


      1. nick00
        11.04.2024 07:50

        Проблема сейчас не с обучением, а с созданием новых контор в айти. То есть с рабочими местами. Их нет. Сайты типа hh ru маскируют отсутствие рабочих мест, размещают фейковые вакансии, принимают резюме на фейки, проводят собеседования. Создается видимость нормального рынка труда. Вакансий нет. Существующим конторам выгодно поддерживать видимость открытых вакансий, чтобы программисты без работы не создавали своих компаний, потому что они станут конкурентами в будущем. Короче hh ru это такой ...отрон, который просто защищает интересы владельцев текущих компаний айти. Если людей учат, то рынок должен РАСТИ, должно увеличиваться количество компаний и вакансий. Стагнация означает, что всех выгоняют.


        1. Serine Автор
          11.04.2024 07:50
          +2

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