Что я понял и с какими проблемами столкнулся, создав клон Hacker News

9d22a8a7c00b7d82fb381a39ec725b64.jpg

От переводчика: эта статья — сокращенный перевод оригинального поста веб-разработчика Джесси Хорна. Его работа и одновременно хобби — веб-дизайн. Своими наработками и полученным опытом Джесси частенько делится с другими программистами, как опытными, так и начинающими.

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

Skillbox рекомендует: Практический годовой курс PHP-разработчик.
Напоминаем: для всех читателей «Хабра» — скидка 10 000 рублей при записи на любой курс Skillbox по промокоду «Хабр».


Изначально это казалось мне отличной целью, где набор инструментов и тактика работы были предопределены. Ранее я работал над менее крупными задачами, используя разные языки и фреймворки. Единственное, чего не было, — это крупного проекта, который бы позволил собрать все это вместе.

Работать над новым проектом я решил с нуля, используя язык Crystal. Это удобный инструмент, который к тому же еще и новый. Он быстрый, принципы работы с ним похожи на Ruby. Он статистически типизирован плюс является open source. Но просто нового языка тоже недостаточно, поэтому я решил усложнить свою задачу, и сделать не клон Hacker News, а усовершенствованный вариант этого ресурса.

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

Не метьте слишком высоко

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

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

Я даже не могу выразить словами, насколько важно разделить большую задачу на несколько более мелких.

В моем случае я столкнулся с различными новыми проблемами, с которыми не встречался ранее. Во-первых, я работал Crystal лишь однажды — когда создавал приложение, сложность которого ненамного превышала сложность программы типа «Hello, world!». В прошлом я использовал Python, Lua, PHP. Новый язык был первым препятствием на пути к реализации проекта.

Вторым стал фреймворк. Crystal, будучи новым языком, пока еще имеет не слишком много фреймворков и документации для них. Я решил использовать Kemal для своего клона. Я надеялся на то, что фреймворк интуитивен, поскольку в своей работе встречал именно такие. Но здесь оказался другой случай — отдельные вещи было нелегко понять. Например, некоторые участки кода выглядели вполне нормально, но почему-то не работали. И найти причину проблемы в интернете было сложно все по той же причине — новизна языка и самого фреймворка. В некоторых случаях мне приходилось подолгу останавливаться и разбираться с причиной проблемы. До настоящего момента я никогда не заглядывал в исходники, например, того же Flask.

Третье препятствие — специфические цели, которые я выбрал для проекта. Для того чтобы сделать мой клон полезнее, я решил добавить ряд функциональных особенностей. Я работал с Hacker News ранее, поэтому знаю многое о достоинствах и недостатках этого ресурса. Мне пришло в голову, что будет хорошо задействовать аналитические данные, предоставляемые GitHub. Используя их, я бы мог добавить статистику по количеству просмотров и активности пользователей на сайте.

Таким образом, я решил, что мой клон должен показывать по крайней мере просмотры и клики для каждого поста. Такая функция, возможно, была бы полезна для пользователей, а ее реализация стала бы хорошей практикой для меня. Но я не думал, что это займет столько времени! Сейчас проект представляет собой скорее proof-of-concept, чем готовый ресурс. Кроме просмотров и кликов, я также решил добавить отображение появляющихся комментариев, чтобы они показывались в real-time. Если бы не эта дополнительная задача, проект был бы завершен гораздо быстрее.

Сейчас проект поддерживает авторизацию, размещение и сортировку постов, взаимодействие с другими пользователями путем комментирования и просмотра профилей и т.п.

Четвертая проблема, с которой я столкнулся, — хаос. Миграции, модели, просмотры, API-контроллеры, CSS и JavaScript-код накапливаются очень быстро. И все это превращается в кашу. Я попробовал решить проблему, и у меня почти получилось. Но отчасти проблемные места в коде моего проекта еще встречаются — вы можете без проблем это заметить. Так, во многих местах код повторяется, эндпоинты не организованы, нейминг усложнен, что приводит к росту объема кода и большому количеству запросов к базе данных. Постепенно я решаю эту проблему.

Во многих местах код повторяется

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

fafa2b142f94d3d413c25c8889938de6.jpg

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

Нейминг эндпоинтов и организация

Раньше я разрабатывал API в команде Pioneer. Мы использовали REST — стиль архитектуры, которому я фактически присягнул, будучи новым членом команды Pioneer. В этой команде я работал над небольшими элементами огромного приложения. А вот в своем новом проекте мне все пришлось писать с нуля.

«RESTful API» должен иметь Uniform Interface, так сказано в «Вики». В своем проекте я организовал все так, что эндпоинты определялись в source-файлах, которые назывались соответственно функции или назначению. Регистрация и выход из приложения были прописаны в «auth.cr». Логин пользователя прописывался в «user.cr».

Несомненно, эта часть требует переработки. В дальнейшем я организую все так, чтобы действия относились к эндпоинту »/user», просто потому, что все это имеет отношение к «User». Например, для улучшения структуры проекта разделю код на более удобные и управляемые части с большим числом файлов. Создам папку «src/user/auth/», в которой будут содержаться функции логина, регистрации и выхода пользователя из приложения.

1_6dy_OCE7_Cjj_Df7_A0s_Aj_3i_Q

Слишком много запросов

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

270faffe964e6f1e60721f8b9a6d4dc2.jpg

Все, что описано выше, — лишь примеры проблем, с которыми я все время сталкиваюсь. Я не могу описать их в полном объеме. Тем не менее сейчас я размышляю над тем, чтобы документировать мои проблемы и решения. Надеюсь, что все это поможет другим программистам увидеть и понять мои ошибки и избежать собственных. Я знаю, что если буду использовать комбинацию Redis и MySQL или Postgres, то смогу ускорить выполнение запросов. Но пока что остановлюсь на этом.

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

Skillbox рекомендует:

© Habrahabr.ru