Хочу представить вам свой проект, над которым я трудился последние несколько месяцев, а также рассказать как это происходило. bookradar.org — поисковик книг по интернет магазинам. Сервис рассчитан на людей, которые любят читать книги, с помощью сервиса они могут узнать, где можно купить нужную книгу, а также сэкономить на покупке. Чем больше стоит книга, тем больше ее цена разниться в магазинах.
Так например книга Фил Розенцвейг «Эффект ореола…и другие восемь иллюзий, вводящие менеджеров в заблуждение.» стоит в разных магазинах от 537 до 885 руб. Разница довольно существенна.
От идеи к результату далее …
Пример запроса по книге:
Идея
Я люблю читать книги, и часто их покупаю. Чесно говоря, я их покупаю чаще чем, успеваю прочитать. Некоторые книги могут лежать у меня на полке по 3 года, прежде чем я до них доберусь. У меня есть читалки Kindle Paperwhite и Nook Simple Touch, также много книг я прочитал на компе во всяких pdf. Несомненно у электронных книг, есть преимущества — их можно быстро купить и читать в темноте, но всеже я предпочитаю бумажные.
Была середина ноября 2012, я записался на онлайн курс “MongoDB for Developers”. Прошла пара недель от его начала. Хотя я еще не представлял всех возможностей MongoDB, мне уже очень нравилась эта технология. Было желание как-то применить новые знания на практике. И тут мне пришла идея сделать сайт по поиску книг.
На тот момент я уже видел один подобный сайт, но чесно говоря, он был не очень удобный, и не всегда выдавал достоверные результаты. Возможно стоило поискать еще другие сайты, но в тот момент я этого не сделал. Смотреть на другие сайты я стал уже после того как запустил свой. Их оказалось намного больше чем я мог предположить. Таких сайтов более десятка. Однако это меня нисколько не смутило. Я могу предложить пользователям более удобный поиск, а в перспективе надеюсь более точный и более широкий. Да и вообще недостатка идей не наблюдается)
Реализация
Сначала я решил, что мне хватит пары выходных, чтобы осуществить задуманное, но как это часто бывает, потребовалось гораздо больше времени. На работе я использую Django, но чесно говоря, за пару лет работы с ней она мне несколько наскучила. Django отличный фреймворк, но просто хотелось чего-то нового, и я решил делать проект на Flask. Почему именно Flask? Случайный знакомый скинул ссылку на туториал создания блога на Flask+mongoDB и сказал, что он уже давно использует Flask в своих проектах. Было интересно попробовать.
Попросил жену нарисовать дизайн (Полина привет!), уточнив что дизайн нужен максимально простой, без всяких теней и градиентов. На тот момент это позволило мне сэкономить время на верстке и легче вносить изменения.
Прошел месяц… Чесно говоря я очень сильно устал все вечера и выходные посвящая программированию, и энтузиазм стремительно гас. Мне нужно было срочно получить обратную связь от реальных людей. Я выложил проект в минимально рабочем виде. Проект уже работал, реально искал книги в магазинах, но сильно страдал от множества мелких багов и недоработок. Все это было сделано умышленно, чтобы ускорить выкладку первой версии. Не было даже таких элементарных вещей как обработка ошибок 404 и 500, не говоря уже о всяких history API.
Получив положительную оценку коллег, я вдохновился на продолжение работы. Следующий месяц был посвящен в основном доработке, во этих самых мелких косяков.
К томуже выяснилось, что реальные данные не соответсвуют тому, к чему я готовился изначально. Пришлось менять схему документов в БД, разделять коллекции, изменять алгоритмы.
С реальными данными много приколов. Например я расчитывал, что ISBN может быть уникальным идентификатором для книги. На деле оказалось не так. У одной книги может быть множество ISBN’ов. Уж не знаю кто в магазинах занимается наполнением базы, но мало того, что ISBN могут быть невалидными, дак вместо ISBN может оказаться вообще черти что, от произвольных цифр, до каких-то фраз на русском языке. Вместо цифры ноль может быть забит символ “О”, а вместо английской “Экс” может быть русская “Ха”.
Более того, у двух совершенно разных книг, может оказаться один ISBN. В теории такое невозможно. Некоторые книги издатели объединяют в комплекты. Например в такой якобы книге оказываются ISBN’ы от двух разных книг и авторы от двух разных книг.
А дальше я столкнулся с проблемой производительности. Python как и любой другой динамический язык работает не так быстро как хотелось бы. Для веб-приложений как правило это не играет роли, т.к. если у вас тормозит сайт значит это тормозит БД, дисковые операции или сеть. Я долго профилировал код, оптимизировал алгоритмы. Пришел к выводу, что алгоритмы нормальные, тормозят Python и БД.
Нужно было переписывать существенную часть проекта на более быстром языке, очевидно со статической типизацией. Так в проекте появилась Scala, неведомый доселе мне язык программирования)
Почему собственно Scala? Я выбирал между C, C++ и Scala. Первый Segmentation Fault заставил меня вычеркнуть из этог списка Си. Си хороший язык, но явно не оптимальный для данной задачи. Конечно я смотрел тесты производительности языков, но чесно говоря я не верил, что скорость Java/Scala близка к скорости С++. Поэтому я написал свой тест производительности. Я взял небольшой кусок парсера и написал реализацию его на Python, Scala и С++.
Вот результаты парсига 1,5 Гб файла:
CPython 4 мин 12 сек
PyPy 2 мин 48 сек
Scala 57 сек
C++ 47 сек.
Алгоритм везде одинаковый, для парсинга, используются лишь строковые операции. В Scala также пробовал юзать какой-то стандартный XML парсер, но это работало намного медленнее.
Как видим скорость Scala действительно близка к плюсам. А писать и отлаживать Scala проще. К томуже у меня было с кем проконсультироваться, в случае возникновения непоняток (Иван привет!).
При написании кода на Scala часто ловил себя на мысли “так этот код выглядит неправильно, нужно выяснить как это сделать правильно”. Такой перфекционизм мог существенно затормозить разработку. Я говорил себе “чувак, ты не знаешь этот язык, и поэтому не можешь писать сразу правильно, поэтому просто пиши, чтобы работало!”. Психологически было сложно заставить себя писать “чтобы работало”, хотелось делать “красиво”. Но в конечном итоге я брал себя в руки и писал “чтобы работало”.
TDD. Все парсеры с самого начала были покрыты тестами, что на Python, что на Scala. Это именно то место, где тесты сразу ускоряют разработку. С другой стороны на форнтэнде до сих пор нет ни одного теста.
Монетизация
В первый же день после запуска коллеги спросили меня, когда я собираюсь сделать поиск платным. А я и не собирался этого делать. Монетизация простая и понятная — партнерские программы магазинов. Рекламу размещать не планирую.
Настоящее
Сейчас уже исправлена целая гора недочетов присутствовавших при запуске, хотя они еще присутствуют в заметном количестве. Одна из интересных задач с которой пришлось столкнутся это склейка книг из разных источников. Сейчас алгоритм склейки работает уже достаточно хорошо, но иногода все-таки дает сбои. Если вы столкнулись с этим, напишите мне.
Фронтэнд написан на Python/Flask, бакэнд на Scala, в качестве базы — MongoDB.
Планы на будущее
Идей достаточно много, но в ближайшее время я планирую работать над качеством поиска и исправлением мелких недочетов. Новые фичи это прикольно, и они обязательно появятся, но чуть позже. Кстати, ваши комментарии могут повлиять на порядок их появления.
Надеюсь вам понравился мой сервис,
буду крайне признателен за советы, критику и пожелания.
Заходите — www.bookradar.org!
Автор: un1t