![image](https://habrastorage.org/getpro/habr/post_images/b7b/95b/2f5/b7b95b2f558d6ad32a6710e1d5f5224b.jpg)
За четыре года работы над онлайн консультантом WebConsult мы накопили достаточно большой опыт, и оказалось, что изначально мы не учли многих вещей, которые потом приходилось переделывать – в итоге это стоило нам массы времени, средств и нервов. Эта статья, а возможно и цикл статей, будут посвящены аспектам, которые необходимо продумать еще до начала разработки, дабы будущие стартаперы изначально закладывали грамотную основу в свои веб-приложения. Этой статьи нам очень не хватало четыре года назад, когда создание системы только начиналось, и мы надеемся, что она поможет вам не повторить наших основных ошибок. Многие приведенные советы кому-то покажутся очевидными, однако часто разработчики их упускают, поэтому мы считаем необходимым еще раз напомнить о простых вещах.
1. Мультиязычность
При разработке мы думали, что день когда наш проект станет международным настанет совсем не скоро. Целью было сначала запуститься в России и посмотреть, что из этого получится, а если проект пойдет – то мы сможем быстро перевести всё на другие языки. Мы ошибались и в итоге получили огромное количество текстов, зашитых непосредственно в шаблоны проекта и JS код, а кое-где логика самого приложения вообще не очень способствовала локализации.
Сейчас мы начали работу по переносу всех текстов в lang-файлы, в том числе и из javascript (благодаря замечательной библиотеке i18next), однако если бы мы подумали об этом изначально, то сделать это было бы гораздо проще. Конечно же, все новые возможности и интерфейсы мы теперь сразу готовим к локализации.
2. Часовые пояса
Не забывайте, что только в нашей стране существует 9 часовых поясов, поэтому мы рекомендуем сразу дать возможность пользователю выбирать часовой пояс и применять его ко всем датам на сайте, статистическим выборкам и т.п. Потом это будет тяжело переделать.
3. Подумайте о масштабируемости
Если ваш стартап будет успешен, то рано или поздно настанет момент, когда вам не будет хватать мощности одного сервера. Как правило не возникает никаких проблем с распределением нагрузки на HTTP-сервер: ставим сервер-балансировщик и направляем трафик на несколько одинаковых HTTP серверов. Гораздо интереснее ситуация с масштабированием БД. Конечно, существует репликация, но, как показала практика, она крайне ненадежна в случае c MySQL. Лучше выносить логически независимые части проекты на разные сервера БД (шардинг), однако об этом лучше подумать до разработки самого приложения. Например, особенно тяжелые модули можно вынести на отдельный сервер БД и нагружать основной. Даже если вы изначально хотите запускать все на одном сервере, то предусмотрите возможность легкого переноса некоторых модулей на отдельный сервер, когда такая необходимость возникнет.
4. Выводите все в API
Если ваше приложение подразумевает в будущем наличие общедоступного API – подумайте об этом сразу. Работая над модулем, который теоретически должен быть доступен сторонним разработчикам, сразу сделайте API методы работы с ним. При правильной архитектуре приложения сделать это очень легко, гораздо сложнее делать это потом. У нас до сих пор нет полноценного API только потому, что мы не подумали об этом изначально – сейчас мы ведем работу, чтобы исправить эту ситуацию.
5. Лавинообразные запросы – в Redis
Кнопка нашего онлайн консультанта располагается на тысячах сайтов, а количество показов кнопки исчисляется десятками миллионов в сутки. Каждый показ кнопки генерирует запрос к БД, который сохраняет переход посетителя – это необходимо, чтобы консультанты могли видеть полный путь клиента по сайту в процессе разговора. Сначала эти данные записывались в MySQL, что оказалось в итоге совершенно некорректным. Во-первых, это был самый главный источник на нагрузки на БД. Во-вторых, mysql крайне негативно относился к такому бешеному количеству одновременных запросов на изменение таблицы и иногда даже возникали кратковременные блокировки БД – запросы скапливались, и все приложение начинало жутко тормозить. В-третьих, процесс очистки этих данных по истечении срока давности был достаточно ресурсоемким. Мы очень много экспериментировали с настройками MySQL и добились немногого. В процессе поиска альтернатив было решено перейти на Redis, который записывает данные в память в формате «ключ»: «значение», обеспечивая высокую скорость чтения-записи и отсутствие блокирующих запросов, а данные можно очищать, задав time-to-live. Нам такая модель подходила идеально.
Не скажу, что переход был гладким: пришлось плотно покопаться в настройках Redis'а, переписать кучу скриптов, пережить несколько даунтаймов, но все же мы это сделали и в результате сократили нагрузку на БД почти вдвое. Опять же, если бы мы подумали об этом заранее, все было бы гораздо проще. Поэтому если у вас планируются подобное «лавинообразные» запросы, лучше переведите их на Redis сразу: когда-нибудь вы скажите себе за это спасибо.
Кроме Redis существуют и другие подобные продукты, но, к сожалению, с ними мы не работали.
6. Минимальное взаимодействие пользователя и тех.поддержки
Сократите количество операций, которые пользователь не может сделать самостоятельно, без участия поддержки. Примерами таких операций являются — переход на другой тариф, формирование договора, выставление счетов, закрывающих документов. В идеале тех. поддержка должна помогать пользователям с выполнением уже доступных им операций, а не делать эти операции за них. Разгрузив сотрудников поддержки, вы сможете обойтись меньшим штатом и сэкономить деньги.
7. Не допускайте беспорядка в файлах проекта
Очень жалеем о том, что изначально хорошо не подумали о файловой структуре проекта – поэтому у нас в файлах системы образовался некоторый беспорядок: где-то из-за элементарной лени, где-то из-за того, что мы не все учли. Потихоньку наводим порядок, но дело это не быстрое. Естественно на работу системы это никак не влияет, но мешает процессу разработки. Да и в целом, когда все файлы лежат на своих местах, это вызывает эстетическое удовольствие. Сразу подумайте, где у вас будут лежать библиотеки, как будет организованно расположение статики, и по какому принципу будут распределены файлы проекта.
8. Используйте JavaScript шаблонизаторы
Немногие разработчики знают, но в javascript тоже можно использовать шаблоны, что не только делает js-код более чистым, но и сильно упрощает работу с HTML-кодом. Для этих целей существует целый ряд продуктов: Handlebars, Swig, EJS, undercore.js. Если у вас планируется разработка RIA (Rich Internet Application), то рекомендуем познакомиться еще и с Backbone.JS, который станет отличным каркасом вашего JS-приложения.
9. Максимально очищайте ненужные данные
Ваш проект должен жить по принципу: если данные устарели или вышел срок их хранения –их нужно удалять. Чем больше данных в таблицах, тем больше нагрузка и тем медленнее работа системы. По мере разработки создавайте cron-скрипты, которые будут удалять ненужные данные – это относится не только к записям в БД, но и к пользовательским файлам. Например, частой ошибкой является удаление записи с файлом из БД, однако сам файл в хранилище остается.
Сюда же можно отнести и тот случай, когда из БД удаляется главная запись, но не удаляются связанные с ней записи в других таблицах: таким образом, нарушается целостность данных. В MySQL для этой цели можно использовать триггеры и внешние ключи.
10. Единый дизайн – во всем
Старайтесь, чтобы ваш дизайн был единым везде: имел одинаковый общий стиль и стиль отдельных элементов – таких как формы, буттоны, скроллбары, таблицы и т.п. При разработке дизайна создайте своего рода стандарт и не отступайте от него. Во-первых, это сильно облегчит верстку, во-вторых – вашим пользователям будет удобнее, если все будет унифицировано; в-третьих это просто красиво, когда везде, даже в мелочах, сохраняется общий стиль.
11. Используйте LESS для стилей
LESS — это простой инструмент, который превращает обычный CSS в динамический и позволяет использовать вложенные правила, переменные и функции. Код CSS становится более наглядным, а процесс разработки сильно упрощается. На выходе, с помощью специальной утилиты lessc, мы компилируем less-код и получаем обычный css-файл. С трудом можем себе представить, как раньше обходились без LESS – обязательно попробуйте.
12. Логичное ценообразование
Даже если у вас фиксированные тарифы иногда возникают ситуации, когда клиент требует индивидуального расчета стоимости под его потребности. Очень часто называются какие-то ориентировочные цены, происхождение которых непонятно. На первых порах мы грешили тем, что позволяли пользователям набирать только те функции, которые им необходимы. Соответственно стоимость таких тарифов рассчитывалась приблизительно и разнилась от клиента к клиенту. Это создавало сильную путаницу внутри компании и тогда мы решили, что все цены должны логично рассчитываться. Нам пришлось сделать индивидуальные тарифы менее гибкими: теперь люди могут выбирать не отдельные функции, а наборы функций – однако таким образом мы избавились от неразберихи и наши цены стали на 100% прозрачными и понятными, как для клиентов, так и для сотрудников.
13. Сразу думайте о том, как будете собирать статистику
Если в вашем приложении должна быть статистика по каким-либо данным, то настоятельно рекомендуем заранее подумать о том, как она будет собираться. Ведь когда речь идет о статистике важно не только получить данные из БД, но и сделать это быстро. Возможно, что для удобства выборки вам нужно будет добавить дополнительные ключи или сразу же где-нибудь собирать посчитанные данные.
14. Дорабатывайте только те функции, которые будут полезны остальным клиентам
Стандартная ситуация: к вам приходит клиент, которого в принципе устраивает ваш продукт, однако ему нужно «совсем немного» кое-что доработать – иначе он откажется. Очень велик соблазн, особенно в первое время, поддаться на уговоры клиента и доделать какие-либо возможности специально для него. Но не стоит торопиться. Прежде всего, подумайте: будет ли данная возможность полезна другим клиентам? Если это что-то узконаправленное и нужное только конкретному клиенту, то лучше бросайте это дело. В противном случае, постоянно создавая индивидуальные доработки, вы загоняете себя в яму, из которой почти нет выхода – ваш код становится грязным, а при разработке новых возможностей вам придется проверять их на совместимость с кучей мелких индивидуальных доработок. Это не значит, что не нужно прислушиваться к вашим клиентам – мы лишь рекомендуем опираться на пожелания большинства и с осторожностью относиться к единичным идеям.
15. Думайте о тех, кто присоединится к разработке
Простое правило при написании кода – всегда задавайте себе вопрос: сможет ли в этом разобраться новый разработчик? Делайте все логично, красиво и не скупитесь на комментарии. Часто проекты начинают писать в одиночку и не задумываются об этом. Однако если вы рассчитываете в итоге на более крупный проект, то однозначно настанет тот день, когда вашу команду пополнят новые программисты и им придется вникать в ваш код.