Как мы делали стартап

Oct 07, 2012 19:23

Как и обещал, рассказываю о стартапе, которым сейчас занимаюсь. Справедливости ради замечу, что под замком я уже показывал очень сырую альфу, но сейчас - это то, что можно показывать ширкой публике, по крайней мере - с технической стороны.
Итак: http://banionline.ru. Большой, подробный и удобный каталог бань города Самары. Он реально клёвый, даже если вы не из Самары и ненавидите бани - посмотрите, как у нас всё по человечески сделано, и как быстро работает.

Поскольку я занимался всей технической частью проекта, то и расскажу о том, как, что и почему делается и делалось.

С чего всё началось

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

Естественно, от джумлы я отказался. Эту CMS я знал довольно поверхностно, плюс ко всему у джумлы есть фатальный недостаток, с которым нельзя мириться. Решено было взять все наши идеи, и писать движок, реализующий только их, с нуля. Генерацией идей мы занимались все вместе, написанием - я один.

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

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

Как это делалось

Серверный код движка я решил писать на PHP 5.3 (последняя, на тот момент, стабильная версия), не используя никаких фреймворков. Почему без фреймворков? Потому, что я ни одного не знал, поскольку раньше просто не было необходимости их изучать. Хотя писать на PHP приходилось много, в основном это были интерфейсы к базам данных, где основную сложность составляли генераторы запросов, либо скрипты, слишком специфические для того, чтобы использовать какой-либо существующий фреймворк. Изучать, выбирать, осваивать - на это не было времени.
Итого - голый PHP. Ну и AJAX для пущей интерактивности - то есть javascript.
Хотя уровень знания JS у меня на тот момент был небольшим, я твёрдо знал, что всё, что мне понадобится, уже кем-то, в том или ином виде, сделано и описано в интернетах. В том, что я смогу разобраться с чем угодно, сомневаться не приходилось. И хотя ни одного JS-фреймворка я тоже на тот момент не знал, основной причиной, по которым я не стал их использовать, было не это. Я посчитал, что негоже использовать тяжёлую артиллерию там, где можно обойтись снайперской винтовкой. Сами посудите: минимизированный код, например, jQuery весит почти 100 Kb - 10% от размера индексной страницы сайта со всей графикой и CSS! При этом вряд ли мне понадобилось бы больше 10% функций этого фреймворка.
В итоге я оказался прав, но только частично: хотя мой самописный JS в оптимизированном виде занимает около 20 Kb, для создания некоторых красивостей я всё равно использовал script.aculo.us, который требует фреймворк Prototype, весящий те же 100kb. С другой стороны, использование Prototype дало мне возможность реализовать некоторые дополнительные фишки, кроме украшательных.
А с третьей - использование сжатия в apache совсем нивелирует разницу в размере.

Поскольку единственным разработчиком был я, то изначально никакой модели разработки не предполагалось. Но получилось ближе всего к спиральной модели, и вот почему:
- Во-первых, хотя основной список задач был утверждён изначально, кому-то из нас могла попасть вожжа под хвост в виде новой идеи, меняющей требования к проекту. Получалось, что эту идею я закладывал в следующий виток разработки.
- Во-вторых, попутно с созданием кода, должно было идти наполнение ресурса информацией, что требовало хотя бы каких-то, пусть несовершенных, средств работы с ней. Приходилось реализовывать базовые функции, на следующем витке возвращаясь к ним, и улучшая.
- В-третьих, я не стал писать дубовый код, который напрямую делал всё, что мы хотели. Исходя из моего опыта программирования, дубовый код можно писать только для мелких задач, вроде консольных скриптов или прикладных утилит. Если проект большой или предполагается, что он будет развиваться - лучше потратить время на написание гибкого кода (например, функций с гибким набором параметров, или класса, реализующего всестороннее взаимодействие с задачей), который потом позволит внедрять новые функции очень быстро и без изменения текущей архитектуры. Это всегда себя оправдывает, не исключая и данного случая - хотя первый месяц могло казаться, что работа не двигается с места, позже функционал и интерфейс стали развиваться взрывными темпами. Сейчас же практически любая новая функция требует минимума усилий по внедрению; например я планирую интегрировать в движок комментирование через фейсбук/вконтакт/disqus, и вряд ли потрачу на это больше дня-двух, включая тестирование и изучение чужого API.

Кстати, о тестировании

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

Отдельно стоит сказать о головной боли любого веб-разработчика: кроссбраузерном тестировании. И вы знаете, какой браузер я имею в виду.
Когда я узнал, что дизайнера у нас пока нет, то пожал плечами, решив писать интерфейс по минимуму (спиральная модель, помните?), а уж потом, когда у нас будет представление что и как должно выглядеть, то тогда и буду возиться с этим всем. Примерно так и получилось: до определённого момента всё писалось так, чтобы корректно отображаться в Опере (практика показывает, что в таком случае в Хроме, Фаерфоксе и мобильных браузерах странички будут выглядеть без косяков). Когда у нас появился дизайн, я просто сел и переписал все стили так, чтобы IE8 и старше отображали страницу нормально. На удивление, обошлось без отдельных стилей для IE, и почти без заплаток в движке - с большой долей вероятности потому, что я твёрдо решил не поддерживать IE7, не говоря уж о IE6. Даже под восьмую версию этого ужаса я заставил себя писать стили с большим трудом.
Когда же появилась необходимость отлаживать JS, тестирование плавно сместилось в сторону Хрома - именно в нём оказался самый удобный отладчик.

Кстати, о тестировании javascript: с IE снова приходится ломать голову. Нет, я не говорю о том, что у него собственное понимание JS, это все знают, и я, в том числе, знал. Кроссбраузерный код под любую задачу пишется без особых сложностей, чаще всего сводясь просто к ветвлению if (IE) {} else {}. Но всё оказалось куда хуже: например у эксплорера своя логика работы некоторых событий. Причём частенько получается так, что эта логика вроде и не нарушает стандарт w3c; скажем, стандартом не определено поведение события onchange для инпута checkbox. Во всех браузерах это событие происходит аналогично onclick, а в IE - аналогично onchange для других элементов, для которых это событие стандартизировано - то есть после потери элементом фокуса. По привычке грешишь на глюки недобраузера, а разберёшься - и даже обидно становится: недобраузер-то формально оказался прав.
Но бывает и иначе: как оказалось, работа с сервисом Яндекс.карты в IE требует особого подхода. Некоторые API-функции этого сервиса в IE просто не работают, в лучшем случае не давая задействовать какой-то функционал, а в худшем - просто останавливая выполнение всего JS-кода. И об этом нигде не упоминается; впрочем я уже жаловался на документацию API, а отдельно о приключениях с разработкой модуля картографии расскажу ниже.
Вот таких примеров межбраузерных различий - множество, и я вовсе не уверен, что всё обнаружил.

Дизайн

Скажу пару слов о дизайне - только затем, чтобы потом к этому не возвращаться.
Общую концепцию интерфейса мы определили как-то сразу. Одна колонка почти фиксированной ширины по центру экрана, в которой располагаются разные блоки. Никакой резиновой вёрстки - я не спорю, что "резиновые" сайты иногда смотрятся гораздо внушительнее, но это, обычно, бывает, когда на экране должно находиться много данных. Мы же хотели сделать очень простой интерфейс - и для него такой вид оказался идеален.
Почему ширина колонки почти фиксированная? Очень просто: хотя все данные умещаются в блок шириной 1024px, вокруг него - симпатичный белый бордюр, который как раз резиновый, до определённой степени. Очень удачная находка, на мой взгляд (хотя, конечно, не оригинальная).
Все внутренности свёрстаны плавающими блоками (таблицы используются только для вывода табличных данных), что позволяет размещать их как угодно. То, как это сделано в коде, мне очень нравится: я написал функцию, которая принимает в себя всего один параметр (являющийся, правда, ассоциативным массивом =)), и на его основе генерирует оформление такого блока. Возвращаясь к разговору о модели разработки: хотя такую функцию пришлось писать и отлаживать несколько дней, зато позже она позволила мне строить интерфейс на лету и с минимальным количеством кода. Например, главная страница сайта состоит всего из 50 строчек PHP-кода, а страничка просмотра любой бани - из десяти (и её размер - триста байт).

Долгое время у нас не было дизайнера, потом он появился, сделал очень классный вариант оформления, и снова пропал. Это долгая и не интересная история, рассказывать которую я не очень хочу. Её итог в том, что настоящего оформления у нас, по сути, нет - за исключением тех крох, что успел сделать дизайнер. Иконки, большей частью, - чужие, а те, которые наиболее ужасны - самодельные. К счастью, задуманная минималистичность интерфейса не наводит на мысль о том, что задумано-то было вовсе не так =).
С другой стороны - UI вышел ну просто отличный. Пользоваться сайтом очень удобно, всё легко и интуитивно.

Интеграция с внешними сервисами

Думая над выполнением тех или иных задач, я видел, что самый лёгкий, быстрый и интересный способ это сделать - воспользоваться чужими сервисами. Например, взять те же карты, без которых нам никак нельзя было обойтись - кто сейчас будет писать собственную картографию, когда можно воспользоваться решениями Google и Yandex? Зачем изучать API авторизации кучи сайтов, когда есть сервисы ulogin и loginza? Зачем писать собственную систему сбора отзывов, когда есть reformal? Капча - reCAPTCHA. Шаринг - Yandex.share. И т.д., и т.п. В этом прелесть современного веба.
Каждый удобный сервис я по возможности прикручивал к движку, давая возможность выбирать, использовать его, или нет. Процесс этот ещё движется - постоянно попадаются те или иные сервисы, которые могли бы сделать движок мощнее.
Но надо сказать, что некоторые фичи я реализовал в движке нативно. К примеру, хотя гораздо проще авторизоваться по OpenID с любого сайта, который это поддерживает, движок даёт возможность регистрироваться локально со всеми фишками, вроде смены пароля и восстановления забытых учёток по почте. Крутотенюшка!

Карты-карты-карты

Как я уже говорил выше - без картографии нам было совсем никак. Выбирая между сервисами от Google и Yandex я остановился на последнем по очень простой причине - русскоязычный интерфейс самих карт, и, вроде бы, большая детализированность для территорий этой страны. В остальном оба сервиса были для меня одинаковы по причине абсолютной неизвестности. Учитывая, что и яваскриптинг я знал достаточно посредственно - пришлось узнавать и разбираться со многим прямо в процессе реализации задумок. Мало-помалу я выяснял, как сделать то или другое, даже находил баги в сервисе и документации, и, через пару месяцев, мог сделать с картами уже почти всё. При этом от того кода, что я писал в самом начале, меня воротило - я видел, насколько он ужасен... но он работал и переписывать его не было уже ни желания, ни времени. Из-за этого реализация новых фишек с картографией просто встала: обходимся тем, что есть, говорил я, а уж потом я переделаю всё, как надо.
Не знаю, переделал бы или нет, скорее всего - это зависело бы от того, "пошёл" бы стартап или нет.
Но тут вышла вторая версия Yandex.Maps API. А попутно у меня в голове созрела концепция того, как отказаться от написания картографического кода на JS - и я, отложив на время разработку движка, стал писать фреймворк для работы с Yandex.Maps API 2.0 на PHP, благо для второй версии это оказалось куда проще, чем для первой.

Для тех, кто не работал с этим API, попробую объяснить: оно состоит из кучи JS-функций, параметрами которых, чаще всего, являются сложные объекты, в свою очередь хранящие ещё какие-то параметры. Естественно, имеется множество внутренних констант, куча упрощённых вызовов, свои какие-то классы, события и даже аллах. И хотя API 2.0 получилось куда логичнее первой версии, но теперь любая задача, уровнем сложнее примеров из справки, требеут куда большего вовлечения. То есть совсем простую карту вы сделаете легко, а вот для сервис средней сложности приходится разбираться так же, как и для самых сложных задач. На первом API сложность возрастала всё-таки прогрессивно.
И да - это JS. То есть приходится переключаться всё время с PHP; это не проблема, если у вас есть отдельный JS-разработчик, но в нашем случае было не так. Вот я и подумал: а сделаю-ка я такую штуку, чтобы писать код карт на PHP, а он уж пусть сам переводится в JS прямо в рантайме.
И написал. Очень клёво написал, правда. После того, как картография движка был переведёна на этот мой мини-фреймворк, код управления картами стал на порядок нагляднее, на два порядка быстрее и на три - экономичнее.
Дабы не быть голословным обещаю в самое ближайшее время выложить эту разработку на github, только вот документирую, как следует.

Времечко

Сколько времени я потратил на создание движка?
начал им я заниматься десять месяцев назад, через три месяца после начала работы была готова альфа версия (кое-кто её тут даже видел), а в статусе беты мы запустились неделю назад. Долго?
Долго. Но занимался движком я в свободное время в качестве хобби пару дней в неделю; несколько летних месяцев я не занимался им вовсе. К тому же "тормозил" стартап вовсе не я - долго не могли начать сбор информации, искали дизайнера, решали другие проблемы.
Уверен, сосредоточься мы только на стартапе, занимайся только им - за три месяца запустились бы в том же статусе, что и сейчас. Но мы как-то не торопились.

Что ещё предстоит сделать

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

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

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

it, tl;dr

Previous post Next post
Up