Skip to content
Copy of Программа обучения MetaLamp
Share
Explore
Программа обучения MetaLamp

Back-end

Intro
Заданий по Haskell в целом 5 штук, они довольно объемные, даже при усиленном прохождении это займет около 5 месяцев. Формат задач нацелен на то, чтобы системно и по порядку изучать основы и принципы разработки. Мы считаем, что очень грубая ошибка при изучении — кинуться в омут реальных практических задач и штудировать кучу конкретных высокоуровневых технологий (веб-фреймворки, как отличный пример, где помимо языка еще столько же времени надо потратить на изучение документации самого фреймворка). Мы сторонники того, что без фундаментальных знаний в технологии лучше не лезть :) Поэтому базис — сам язык, основные паттерны и принципы архитектуры. Далее самые базовые технологии (простейшие веб-сервера, простейшие обертки для работы с базами данных и тд). Ну а на выходе - большой рефакторинг на основе кучи разных источников и проверка нами ваших github-репозиториев с созданием issues.

Также мы сторонники подхода, при котором новичков нельзя ставить на реальные проекты, пока они не сделали несколько своих средних проектов минимум на 2-3 тысячи строк. Если сразу подключаться к реальным проектам, то есть огромный риск утонуть в чужом и непонятном легаси, потерять мотивацию, но главное — получить несистемный, очень отрывистый опыт, так как задачи будут довольно узконаправленные и кривая обучения будет неоднородной. В итоге, даже если стажер не растеряет всю мотивацию, его опыт за тот же промежуток времени будет гораздо слабее, чем у коллеги, который системно с нуля делал парочку своих проектов.

В целом это должно быть отличной стажировкой для вас, мы готовы с радостью отвечать на ваши вопросы (задавайте их в блипах под описанием каждого задания), а сами задания я постарался сделать такими, чтобы на выходе у вас был максимум полезных практических и теоретических знаний. Еще нам бы очень хотелось видеть, как вы сами кооперируетесь друг с другом и решаете вместе возникающие проблемы. На вашу коммуникацию мы тоже будем обращать внимание - в первую очередь мы ожидаем увидеть в вас приветливого хорошего человека, с которым приятно совместно работать по 8 часов в день минимум :)
Почему именно Haskell
Предыстория. До этого мы довольно много разрабатывали на JavaScript (фронт с React и бек на Node.JS, +Typescript), Python (плюс Django), Elixir (присахаренный Erlang), у многих ребят из команды есть опыт с C/C++/C#. Однако в каждом языке есть свои недостатки, а у нас довольно высокие требования к тому, чтобы язык позволял быстро написать бизнес-логику, которую было бы легко понять коллегам и поддерживать. Именно требование легкой поддержки и надежности у нас всегда были в приоритете.
Haskell — чистый функциональный язык с ленивой моделью вычислений и статической типизацией. Причины, почему мы выбрали именно этот язык:

Haskell имеет, пожалуй, самую мощную систему типов среди промышленных языков на данный момент Haskell — единственный язык, на котором можно спокойно писать коммерческий софт, и который при этом позволяет четко отделять от . У Haskell уникальная экосистема, предлагающая не просто паттерны, а формальные абстракции (такие, как функторы и монады), которые на данный момент хорошо изучены в научной сфере, которые легко комбинировать, и которые позволяют описать огромное количество разного рода взаимосвязей между частями программы. Haskell, несмотря на свои академические зачатки, очень хорош в продакшене (и куча тому ), он быстр, у него отличный механизм для concurrency, его поддерживают почти все популярные редакторы кода и для него есть огромное количество программ, помогающих нам: repl, линтеры, форматтеры и тд. Также в плюсы можно добавить колоссальную выразительность языка и его гибкость (например, операторы можно использовать, как в инфиксной, так и в префиксной записи, а также определять свои: ). И один из главных бонусов, которые вытекают из всего вышеперечисленного, и который нас очень сильно приманил — легкость рефакторинга. Коммерческая разработка лишь на 10-15% состоит из написания абсолютно нового функционала, чаще же это либо добавление чего-то к уже существующим частям, либо рефакторинг после того, как опыт показал, где были ошибки в проектировании. На рефакторинг всегда нужно делать ставку, если планируется долгое развитие проекта (а нашему проекту уже почти два года, и он продолжает активно разрастаться), с Haskell же мы имеем кодовую базу, которая если скомпилировалась, то с 90-95% вероятностью она работает корректно. А значит во время рефакторинга компилятор сам будет за нас делать самую грязную работу — находить регресионные ошибки, замечать упущенные по невнимательности детали, помогать проектировать стройную систему (так как закрыть костылем, как можно было бы это сделать в Python, тут уже нельзя).
Куча примеров использования Haskell в продакшене
Два списка компаний, использующих Haskell в продакшене: и
Плюс еще более конкретные описания (это только быстро вспомнившиеся, еще много примеров можно нагуглить):
Facebook борется со спамом с помощью Хаскеля и напилили опенсорсную либу:
Github написали Semantic на Haskell,
Конечно, есть и свои недостатки, которые мы отлично понимаем, и с которыми готовы были смириться: высокий порог входа (хотя, возможно, и не сильно выше тех же C++ или C#, если изучать их с нуля), отсутствие единого гайдлайна с best practices, отсутствие мощных IDE (хотя они и не особо нужны при таком выводе типов и таком компиляторе, который и так все подскажет, если правильно спросить).
Еще недостатки, на которые нам пофиг: экосистема не изобилует монструозными фреймворками и разного рода "энтерпрайзными" библиотеками, хотя нам конкретно это совсем не мешает, так как все равно фреймворки блистают лишь в задачах уровня "сходить в базу, вытащить из базы, показать в html/json/xml", а у нас же много бизнес-логики, которую никакая библиотека за нас не напишет.
Все это можно подытожить простым выводом — будь у нас простенький проект с адски малыми сроками, то Haskell был бы не лучшим выбором. Но наш проект долгоживущий и активно разрастающийся, а значит нам нужен язык, который бы позволял писать максимально прозрачный и понятный код, который можно легко поддерживать и рефакторить. Функциональный, чистый, статически типизированный Haskell как нельзя лучше подходит на эту роль, поэтому мы его и выбрали.
Первое задание (Теория)
Изучить:
Для начала минимум, необходимый для написания самых простых проектов
Параллельно выполнять каты из
После того, как изучены вышеназванные источники, можно одновременно выполнять дальнейшие задания и понемногу изучать следующие ресурсы:
Обязательно: системное описание почти всех самых популярных тайпклассов —
Обязательно: учебник чуть более глубоко описывающий Haskell —
Обязательно: видео-курс на степик от Дениса Москвина
Очень рекомендуется: книга для начинающих с хорошим практическим уклоном Get Programming with Haskell
По желанию: сделать упражнения из глав , которые помогут освоиться с приближенными к реальным задачам
По желанию: часто рекомендуемая многими новичками книга
По желанию: Write Yourself a Scheme in 48 Hours

Статьи по различным темам, которые могут оказаться полезными для понимания того или иного материала
Важное требование — отчеты:
При прохождении этого и следующих заданий мы будем ждать от вас отчетов с текущим прогрессом и вашим личным отношением к изученному/сделанному. Отчеты лучше писать под конец дня, когда что-то делали (ну или в начале следующего), настолько часто, насколько вы будете работать. График у нас гибкий, так что можно спокойно делать любые перерывы в отправке отчетов и в любой момент возвращаться и писать их снова.
Отчеты шлем в телеграм в общую группу: .
Там же можно спрашивать совета, самим помогать и узнавать о новостях нашей программы обучения. Формат неформальный, пишите, как душа пожелает, чем больше личного фидбека, тем лучше :)
Второе задание (Задачки по языку)
Выполнить следующие каты:
Обязательно попробуйте найти и пройти еще от 3-х кат (1, 2 или 3) самостоятельно.
Обязательные для прохождения:
Бесконечные структуры:
Создание своих инстансов для 5 базовых монад:
Монадный стек Maybe + List + State:
Представление структур данных из функций:
Изоморфизм (на самом деле довольно простая и интересная ката):
Третье задание (Бот)
Написать эхо-бота, который умеет просто отправлять сообщение от пользователя ему же в ответ.
Бот должен иметь возможность работать через несколько мессенджеров, пока как минимум сделать имплементацию для Telegram и для Vk
Описание функциональных требований:
Пользователь может отправить команду /help и увидеть текст, описывающий бота
Пользователь может отправить команду /repeat и в ответ бот отправит какое сейчас выбранно значение повторов и вопрос, сколько раз повторять сообщение в дальнейшем. К вопросу будут прилагаться кнопки для выбора ответа (кнопки с цифрами от 1 до 5). После выбора пользователем, все ответы бота должны дублировать указанное кол-во раз. Кол-во повторов должно быть индивидуальным для каждого пользователя, т. е. если один пользователь выбрал 3 повторения, то второму мы по-прежнему показываем начальное кол-во сообщений.
Все должно быть максимально кастомизируемо через конфиги:w
Сообщение, отправляемое в ответ на /help.
Вопрос по команде /repeat.
Начальное кол-во повторов на каждый ответ.
Описание технических требований:

Специфичные правила для третьего задания (бота):
Для основного кода проекта (не тестов) использовать только библиотеки из стандартной поставки haskell-platform (bytestring, text, mtl etc, ) и три сторонние:
1) для отправки http-запросов
2) для парсинга json
3) для работы с конфигом.
Все остальное должно быть сделано по максимуму без библиотек. Для тестов можете использовать любой удобный вам инструмент (HSpec, HUnit, etc)
Источники:
Для начала можно посмотреть про то, как начать собирать первое приложение по отправке HTTP-запроса и получению одного нужного поля из JSON

Четвертое задание (Веб-сервер)

Создать проект новостей (представим, что это сервер для мобильного приложения).
REST API, который принимает HTTP запросы и отдает ответы в формате JSON
Описание функциональных требований:
Проект содержит следующие сущности:
Пользователь
имя
фамилия
аватарка
логин
пароль
дата создания
админ (булевая переменная)
Авторы
Ссылка на пользователя (то есть все авторы — пользователи, но не все пользователи — авторы)
Краткое описание
Категории (могут быть вложенными, то есть одна категория является подкатегорией для другой)
Допустим, есть категория "Языки программирования", и у нее может быть подкатегория "Динамически Типизированные ЯП", и далее, соответственно, подкатегория подкатегории "Python" — и таких уровней вложенности может быть произвольное количество
Теги
Новости:
краткое название
дата создания
один автор
одна категория
множество тегов
текстовый контент
одна главная фотография
множество дополнительных фотографий
Комментарий к новости
У каждой новости может быть множество комментариев
Черновики
Новость должна иметь возможность иметь черновики — то есть мы должны иметь возможность вносить изменения, но не опубликовать их.
По АПИ отдаем только опубликованные новости.
Только автор может видеть черновик к новости и изменять его.

API:
Когда по API запрашиваем новости, в каждой новости должны быть вложены все сущности (автор, категория (рекурсивно), теги и тд).
API новостей должно поддерживать фильтрацию по полям:
день создания (созданные ранее даты, созданные после даты, созданные в тот же день),
Примеры:
/posts?created_at=2018-05-21
/posts?created_at__lt=2018-05-21
/posts?created_at__gt=2018-05-21
имя автора,
категория по айди,
тег по айди
Примеры:
/posts?tag=123
/posts?tags__in=[123,124,125]
/posts?tags__all=[123,124,125]
поиск по конкретному тегу
найти статьи, в которых есть хоть один тег из списка
найти только те статьи, в которых есть все теги одновременно,
название (вхождение подстроки)
контент (вхождение подстроки)
API новостей должно поддерживать поиск по строке, которая может быть найдена либо в текстовом контенте, либо в имени автора, либо в названии категории/тега
API новостей должно поддерживать сортировку по:
дате,
автору (имя по алфавиту),
по категориям (название по алфавиту),
по количеству фотографий
Должно быть отдельные API для сущностей:
авторов — и создание, и редактирование, и получение, и удаление, только для админов,
категории — получение всем, создание, удаление и редактирование только для админов,
теги — получение всем, создание, удаление и редактирование только для админов,
черновики — создание, редактирование, получение, удаление всем авторам только своих черновиков, плюс отдельный метод publish, чтобы апдейтнуть публикацию
пользователей — создание, получение всем (редактирования нет), удаление только админам
Что доступно только админам, при запросе не админам возвращать 404, не 403, чтобы не показать само наличие такого API.
Запросы по всем остальным урлам должны возвращать 404.
Аутентификация:
при создании пользователя генерировать и возвращать токен
добавить эндпоинт, который будет проводить аутентификацию по логину и паролю и будет выдавать новый токен при необходимости. При этом старый токен становится недействительным
аутентификацию в остальном API проводить по токену
хешировать пароли в базе данных
Все API, возвращающие список данных, должны быть пагинированы
Описание технических требований:
В качестве веб-сервера под капотом использовать Warp
Обязательно прочесть описание, как он работает:
В целом эту книгу (AOSA Book) очень рекомендуем, там огромное количество инсайтов по многим крутым опенсорсным проектам.
Чтобы использовать Warp, необходимо понимать WAI, так что еще по нему прочитать —
В качестве базы использовать PostgreSQL
Для работы с базой можно использовать любые библиотеки, главное — самим создавать и поддерживать миграции
Миграции — код, который задает структуру базе (то есть создание таблиц, изменение, переименование, удаление полей и тд).
Обязательно держите в голове, что после того, как проект выпускается в продакшен, база на проде заполняется данными, которые ни в коем случае нельзя потерять. Но требование менять структуру базы регулярно появляется за время развития проекта, и надо уметь развивать базу без потери данных. Для этого нужно как можно тщательней формализовать все изменения, которые вы проводите над базой от версии к версии.
Должна быть предоставлена отдельная команда, которая позволит применить все миграции к локальной базе данных и создать всю нужную структуру для бд.
В отдельной папке проекта сделать sh скрипты со всеми возможными CURL запросами, чтобы мы могли быстро склонировать проект и потестить его. Сделать по sh файлу на каждый CURL запрос
Источники
Не всем рекомендациям отсюда мы бы советовали следовать, но почитать про релевантный опыт автора статьи будет однозначно полезно.
Пятое задание (Ревью)
В рамках этого этапа наши сотрудники проведут строгое ревью github-репозиториев для предыдущих двух проектов: бота и веб-сервера. Перед этим вам необходимо привести код репозитория к следующим требованиям:
Весь проект скомпилирован с флагами -Wall и -Werror и нет ни одной ошибки и ни одного варнинга от компилятора.
Весь код проверен через hlint и не вызывает ни одного варнинга.
Весь код отформатирован через hindent.
Не используются нетотальные функции (Partial functions).
Вложенность условных операторов и операторы выбора не должна превышать 2х уровней.
Не используются длинные кортежи, когда удобнее использовать ADT.
Ошибки внимательно обрабатываются и не глушатся
Не используются error и undefined.
Названия функций выбраны в соответствии с проблемой, которую эти функции решают.
Каждая функция решает только одну проблему.
Использовать паттерны проектирования (Service Handle или tagless final на выбор).
Основной функционал должен быть покрыт чистыми юнит-тестами. E2E тесты в рамках программы обучения писать не требуется.
Проект должен запускаться и работать с конфигом проверяющего (например, чтобы можно было проверить работу бота с другим токеном).

Рекомендуемые источники по оформлению кода:
(правила про Haddock можно игнорировать)
HaskellerZ - Feb 2018 - Getting things done in Haskell and Zurich Friends of Haskell
— смотреть первую часть до 51 минуты, там идет набор разных правил по разработке на Хаскеле. Паттерн Handle стоит рассмотреть, но необязательно применять.
Обязательно изучить репозиторий, который там есть в ссылке, там то приложение, о котором рассказывал спикер: Fugacious.

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





Want to print your doc?
This is not the way.
Try clicking the ⋯ next to your doc name or using a keyboard shortcut (
CtrlP
) instead.