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


Получилось что-то вроде квеста с распределенным выбором: от того, какой язык программирования выбрать и до того, кого лучше нанимать в команду, которая сделает самый полезный продукт ever. Предлагаю вам почитать этот пост, выбрать свои варианты, дополнить квест и обсудить то, что наболело.


upd — немного дополнил текст до ката.



От идеи до прототипа


Предположим, что я и мой друг Валерка решили сделать стартап. Uber for X, или там еще что-нибудь в таком духе. Собрались в баре, обсудили эту идею, клёвая тема. Надо сделать. Три месяца не спали, не ели, не выходили из дома. Разрабатывали. Запустили и поняли, что это никому не нужно.


Печаль. Попробуем еще раз. На этот раз мы изучили рынок, посмотрели, какие потребности у пользователей, какие проблемы. Мы сделали какой-то прототип совсем на коленке, быстро и бесплатно за два вечера. Прототип взлетел. Круто, идем дальше.


Выбираем технологии


Теперь мы можем брать и делать из прототипа большое приложение, развивать его. Но для этого надо более серьезно подойти к выбору технологий, которые мы будем использовать.


Язык


По порядку. На каком языке писать? Можно взять модный функциональный: Haskell, Erlang, Lisp (очень модный среди дедушек старше 70). Либо очередного убийцу JS, который очень клевый, компилируется в JS, имеет все нужные фичи. Но скорее всего, нам некого будет нанимать через год, потому что очередной убийца JS не взлетит, и придется переучиваться заново или переписывать проект.


Попытка номер два. Можно взять что-нибудь проверенное временем. Например, PHP. Это неплохой язык, его модно иногда критиковать, у него есть свои минусы, но на нем легко делать бизнес-логику, он достаточно быстрый, неплохо масштабируется, можно нанять людей когда угодно и где угодно. Но он не очень производительный. Поэтому нам нужно либо много железа, либо писать свой компилятор, как сделали Facebook или ВК.


Еще варианты? Можно взять Perl, но тогда будет некого нанимать ещё вчера. Ещё?
Java. Java — норм. Как язык не очень, на мой субъективный взгляд, но JVM — отличная виртуальная машина, все ок, быстро работает, но железа все равно нужно много. А ещё пока мы на Java писали абстрактный билдер фабрики стратегий вместо того, чтобы делать фичи, пользователи ушли к конкурентам.


Ладно, у нас есть еще Python. В принципе, у него всё ок. Но мы запускаем приложение на Python, оно использует одно ядро из 56, в остальном… все ок. Либо можно взять что-то современное: Go, Rust, еще что-то. Но они слишком низкоуровневые, и мы просто долго делаем фичи… Какой-нибудь язык нам всё равно придется выбрать. Пусть в итоге это будет JS, сойдет.



База данных


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


Ок, давайте возьмем реляционную базу. MySQL, PostgreSQL, или Oracle, если денег хватит. С реляционными базами можно однажды прийти на работу и обнаружить себя в аду из транзакций и хранимок. Это не обязательно произойдёт с нашим проектом. Но если произойдет, то эти хитросплетения логики будет невозможно тестировать. А ещё если вдруг мы достигнем вертикального предела нашего большого золотого сервера, на котором мы хостим базу, потом будет довольно сложно их разделять. Долго делаем фичи.


Ладно. Базу взяли какую-нибудь, бахнули перед ней ORM, чтобы проще было с одного SQL на другой переезжать. Когда-нибудь (spoiler: никогда).



Архитектура


Какую взять архитектуру? Ребята на Хабре пишут, что микросервисы – это клёво. Олег Бунин говорит: «берите микросервисы».


Если начать с микросервисов, то с восьмидесятипроцентной вероятностью границы у них будут неправильные, потому что не до конца продумали доменную модель и плохо поняли, где надо резать, а где не надо. Плюс все берут микросервисы, деплоят их пачками по всему своему кластеру, и через месяц возникает вопрос: «а как это всё теперь тестировать?». Сервисы уже работают в продакшене, а мы их не тестируем. Используя привычные методологии (пирамида тестирования, ручные интеграционные тесты, end-to-end тесты), тестировать микросервисы сложно. Поэтому мы долго делаем фичи.


Ок, тогда давайте бахнем монолит. Это самая правильная идея для стартапа. Очень долго можно жить с отличным монолитом и не иметь проблем. Но если мы решим сильно расширить команду, то надо быть осторожнее. Монолит нормально масштабируется, пока разработчиков 20, 30, 50. Дальше скорость доставки фич падает экспоненциально, а мы теряем пользователей.



Где запускать проект?


Это всё надо где-то запускать. 2018 год, самый логичный вариант сделать это в облаке. Запустишь не в облаке — пацаны засмеют. Но, во-первых, есть федеральный закон 152, значительно ограничивающий выбор облачных провайдеров, у которых можно хоститься. Во-вторых, очень легко приватный ключ от своего аккаунта на Amazon случайно закоммитить в Github, и кто-то обязательно придёт и потратит все ваши деньги. А если этого не произойдёт, то в какой-то момент вас разорят облачные тарифы.


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


Команда


Разработка


Допустим, мы разобрались с языками, базами и тем, где хостить проект. Настало время набирать команду. Можно взять несколько очень крутых ребят, которые все проблемы решат: стократные разработчики, бэкенд-ниндзи, вы понимаете. Возможно, это прокатит. Но на деле вероятно, что приглашённые звёзды будут:


  • токсичными пижонами, которые ничего не будут делать и создадут плохую атмосферу в коллективе,
  • либо идеалистами, выстраивающими по крупицам безукоризненную архитектуру, ставящими ORM перед базами, которые никогда менять не придется...

В итоге… да-да, долго делаем фичи. Еще вариант — взять обычных девчонок и ребят, которые просто будут писать код, делать фичи нормально. Но если взять много не очень опытных разработчиков с разным бэкграундом, они могут писать код в разном стиле, делать штуки по-разному, и при достаточном размере команды всем будет тесно, все будут у друг друга фигурные скобочки переставлять в пуллреквестах. Это не очень эффективно. Как это можно решить? Начальник может читать весь код. Я могу читать все пуллреквесты, а мой друг и ко-фаундер Валерка потом второй раз будет перечитывать (на всякий случай, мало ли). Понятно, это не масштабируется и все медленно делают фичи.


Более правильный вариант — определить кодстайл для компании. Для многих языков он уже есть, и можно его просто соблюдать. Либо если кому-то очень хочется, можно взять готовый и подтюнить немного, и потом смотреть на пуллреквестах и говорить, что здесь фигурная скобочка не там стоит, по кодстайлу должна стоять там. С таким аргументом уже не поспоришь, но на деле это не сильно лучше предыдущего варианта, все равно мы медленно делаем фичи. Правильный вариант для всех современных языков — проверять это автоматически.



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


Quality Assurance


Можно сказать, что QA-специалисты нам не нужны. Многие так делают, это иногда работает. Но не все разработчики любят писать тесты. Их можно понять. И стоит их лучше мотивировать, чтобы тесты все-таки писали, но реальность жестока: unit-тесты ловят далеко не все баги. А если какой-то разработчик не любит писать тесты и все-таки начал их писать, то скорее всего это будут unit-тесты.


Плюс еще есть подходы, когда ты минимизируешь mean time between failures вместо mean time to recover. Mean time between failures — это когда QA специалист говорит: «не будем релизить, у меня чутье плохое, баги будут, давайте через две недели выкатим». А mean time to recover — это когда вы катите что-нибудь, сразу видите на метриках, что что-то сломалось, и через две минуты все откатили, пофиксили и все ок. Но чтобы можно было проект через две минуты откатить, надо всё покрыть нормальными метриками, а это не всегда тривиально. А если метрики в плачевном состоянии, и мы выкатим плохой релиз, мы можем узнать об этом после того, как все пользователи уйдут от нас к конкурентам.


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


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


Как это разрулить? Общаться с коллегами в кружках по интересам. Где-то это называют гильдиями, где-то — коммьюнити. Если мы масштабируем команду кроссфункциональными командами, чтобы они не замыкались в себе, мы просто организуем кружок любителей бэкенда, функциональных языков, секьюрити…



Итоги


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


А ещё — всё это интересно. Интересно решать проблемы, которые уже кто-то решал, новые проблемы еще интереснее решать. Интересно делиться знаниями.

Комментарии (35)


  1. AlexLeonov
    18.10.2018 16:41
    -4

    Открыл статью

    Например, РНР. Это неплохой язык… Но он не очень производительный.


    Закрыл статью.


    1. AlexLeonov
      18.10.2018 18:10
      +6

      Собственно минусы-то за что?
      Смотрим знаменитые картинки замеров производительности, коллеги:



      Где же здесь «не очень производительный»?


      1. kruslan
        18.10.2018 18:14

        А есть картинки с c++, go и т.п.? Автор вроде не сравнивал только эти 4.
        И да, php «не очень производительный». Остальные, просто, еще менее производительные.


        1. RouR
          18.10.2018 18:41

          www.techempower.com/benchmarks Web Framework Benchmarks


          1. kruslan
            18.10.2018 22:56

            Вы показали… что? Что есть менее производительные решения? Ок. Или что php в лидерах?


            1. RouR
              18.10.2018 22:59

              А есть картинки с c++, go и т.п.? Автор вроде не сравнивал только эти 4.
              Я показал что есть сравнения с «c++, go и т.п»


              1. kruslan
                19.10.2018 14:43

                Я знаю что есть, разговор был про картинку выше, на основе которой AlexLeonov показал, что круче php ничего нет ;)


        1. tedgisler
          18.10.2018 19:01

          Ну, учитывая, что в итоге выбрали JS. То как бы…


          1. kruslan
            18.10.2018 22:56

            То как-бы это ничего не значит)


            1. tedgisler
              19.10.2018 03:04

              На самом деле абсолютно верно.
              Хороший программист на любом языке может написать так, чтоб работало быстро.
              Плохой — на любом сделает медленно.


      1. whm Автор
        18.10.2018 18:16
        +1

        Мы в Авито очень любим PHP, но если производительность действительно важна — можем позволить себе не использовать динамические языки, а взять Go, например.

        А Валерка вообще Rust в WASM компилирует!


      1. Valery4
        18.10.2018 20:46
        +1

        Минусы за то, что не любят люди набросы в технических статьях, да и в нетехнических тоже.


      1. Newbilius
        19.10.2018 08:45

        Минусы за "закрыл статью". Автор утрирует в деталях, но очень точно описывает ситуацию про отсутствие серебряной пули и потенциальные грабли на любом из выбранных путей. Про java там тоже спорно, но суть то он передал)


      1. tcapb1
        19.10.2018 10:06

        В статье ещё предлагается очень спорное решение «писать свой компилятор». Мало того, что такое имеет смысл только для очень крупных компаний типа Фэйсбука и ВК, так ещё и вышеуказанные компиляторы по производительности примерно на одном уровне с PHP7.

        И решение ставить JS на бэкэнд из-за скорости. У JS на бэке много преимуществ: и нормальная асинхронность и единый язык разработки, и много чего ещё (как и у PHP есть свои преимущества). Но скорость?


    1. AGARTY
      19.10.2018 09:58
      +1

      У меня приятель тоже фыркает на PHP. Точнее фыркал. Я ему заказывал несколько проектов, он на c++ написал их. Но я постоянно сталкивался с проблемой того, что не мог получить от него то, что мне действительно надо. Логи? Пиши сам. Сортировка? Не буду делать. Зависает потому-что парсинг не может найти последнюю страницу? Ну извини, тут уже ничем не поможешь. И так далее.

      В итоге я плюнул, открыл редактор, #!/usr/bin/env php, создал проект в веб, научил через баш запускать потоки PHP-скриптов, отладил все. Через 4 дня у меня полностью сделанный и функциональный проект с возможностями менять граббинг, фильтрацией и отложенными заданиями. Заработал на PHP-граббере уже порядка 2 млн за несколько лет (в расчете на месяц не много, но денежка идет). Да не много, но заработал я. А не он. Он свои 10к получил, и пошел дальше.

      Потом еще один проект у него слямзил, и еще… Жестоко? Не честно? А мне нужна работа, а не вечное нытье. Я пока не могу писать программы такого уровня и учу JAVA, C++, C#. Да и не буду, проще людей нанять адекватных.

      Но какая разница какой язык, если он приносит прибыль? К докучи всего я еще и на FreeBSD сижу (x11+kde). Почти все сервера на этой оси строю. Ее тоже хают все кому не лень. Согласен, но она мне тоже обеспечивает прибыль. А про то, что она умирает пишут уже 14 лет. Живучая какая…

      Не подуймате, я и другие ОС юзаю, но эта у меня основная для серверов. Особенно если это касается безопасности, в ней мне почему-то проще настраивать все. Привычка видимо.

      Может дело все таки в человеке, а не в инструменте? Ведь у плохой хозяйки всегда кот виноват…


      1. tcapb1
        19.10.2018 10:14

        Ну статья-то всё-таки не холиварная. Так, поверхностный обзор. Говорится, что из зоопарка языков выберем JS на бэкэнд, но особо не говорится чем он лучше PHP. Согласен, что в PHP отличная экосистема для бэкэнда, хорошая сообщество, отличный выбор фреймворков и инструментов. То что надо для быстрого старта. Но и у других языков тоже свои плюсы есть. В итоге выбор зависит от конкретного проекта.


        1. AGARTY
          19.10.2018 10:15

          Полностью согласен.


    1. arturpanteleev
      19.10.2018 11:40

      Думаю многим(например мне, но я уже не могу исправить минус) сначала показалось что вы просто решили набросить на PHP, т.к вас возмутила фраза «РНР. Это неплохой язык». Потом понял что вы не об этом из коммента ниже.
      Ну и в принципе комменты в духе «Закрыл статью.» не очень приятны/полезны, так как наличие какой-то одной неточности или ошибки в статье в самом начале, это не повод ставить на ней крест, и публично об этом высказываться, показываю автору что он, как будто, потратил время зря.


  1. Vadem
    18.10.2018 17:28
    +2

    Я понимаю, что статься не несёт цели глубокого разбора всех ньюансов выбора технологий и подходов.
    Скорое это обзор с высоты птичьего полета.
    Но раздел про архитектуру может ввести в заблуждение начинающих разработчиков.
    Из него может показаться, что существуют два подхода — монолит или микросервисы.
    Это, конечно, две крайности.
    Ещё существуют, например, обычные сервисы или так называемые минисервисы.
    Но в целом за статью спасибо!


    1. whm Автор
      18.10.2018 18:13

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

      А ещё после доклада был отличный вопрос «почему в схеме нет ничего про безопасность» — потому что это отдельное большое приключение, где есть куча других возможностей выстрелить себе в ногу :)


  1. calg0n
    18.10.2018 18:19
    +1

    Спасибо за статью. Всё тлен. Пойду порежу вены…


    1. whm Автор
      18.10.2018 18:59
      +4

      image


  1. tedgisler
    18.10.2018 19:48
    +1

    А вообще смысл статьи в том, что в любой команде программистов должен быть Lead Programmer, который и будет задавать какие технологии все будут использовать и следить за тем, чтоб все придерживались единого стека технологий и стандартов кода.

    Как говорил Наполеон Бонапарт: лучше когда армией командует один плохой генерал, чем 20 хороших :)


    1. salkat
      20.10.2018 17:30

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


  1. usego
    18.10.2018 21:45

    >ставящими ORM перед базами, которые никогда менять не придется…

    как-то однобоко вы на ORM смотрите. Но да, из-за него хватает боли когда джуны ни фига не думают о том, какой SQL на его базе будет построен. Но в целом он существенно экономит время при разработке всей DTO лапши и тестов вокруг неё.


  1. Stasgar
    19.10.2018 10:42

    «Например, PHP… Но он не очень производительный.»
    Ребята из Авито умеют тонко троллить)


  1. SiliconValleyHobo
    19.10.2018 11:12

    Какой-то вброс. Прочитал про java, напрягся. Дочитал до python и нелепое суждение о загрузке только одного ядра — закончил читать.
    Надеюсь, это все толстый троллинг


  1. arturpanteleev
    19.10.2018 11:36

    Какую взять архитектуру? Ребята на Хабре пишут, что микросервисы – это клёво. Олег Бунин говорит: «берите микросервисы».

    Да вроде никто не говорит, что начинать надо с микросервисов. Наоборот, сейчас во большинстве книг/статей о микросервисах пишут о том, что начинать нужно с монолита(естественно не забывая о low coupling и разделении bounded contexts) и выделять что-то из него по мере необходимости и главное наличии понимания того, какие проблемы мы решаем вынесением определенной функциональности из монолита, и какие издержки будем иметь.


  1. arturpanteleev
    19.10.2018 11:55

    идеалистами, выстраивающими по крупицам безукоризненную архитектуру, ставящими ORM перед базами, которые никогда менять не придется...

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


  1. dovg
    19.10.2018 12:11

    А ещё пока мы на Java писали абстрактный билдер фабрики стратегий вместо того, чтобы делать фичи, пользователи ушли к конкурентам.

    Ну вот не надо. В 2018 году спринг абстрактные билдеры пишет за вас.
    В современной джаве вообще не надо писать бойлерплейт, ну вот ни строчки. Сразу делаешь прикладные фичи.


  1. newpy
    19.10.2018 12:50
    -1

    Lisp (очень модный среди дедушек старше 70)

    За что вы нас так ). А как же Clojure? LISP, JVM, FP, STM, AST, immutable, lazy, async, go все дела ;). Скобочки наше все в этом возрасте.


  1. miraage
    19.10.2018 14:08

    ITT: люди воспринимают «пятничный» (ну почти) пост супер серьёзно, читают невнимательно, начинают войны, недочитав до секции «Итоги».

    Спасибо авторам за настроение)


    1. tcapb1
      19.10.2018 14:35
      +2

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


    1. newpy
      19.10.2018 19:50

      Где вы увидели серьёзность? Где войны? Если у меня выше, и за это минусуете, то стоит учиться видеть самоиронию и улавливать весёлый тон хотя бы по смайликам а не сразу переходить к Итогам и минусовать. Веселой пятницы всем.


  1. werklop
    19.10.2018 19:45

    очень легко приватный ключ от своего аккаунта на Amazon случайно закоммитить в Github
    вы уж меня простите, но это надо быть совсем растяпой, чтобы никак не организовывать свои правки и не смотреть их перед тем, как решил коммитить. Например, в IDEA для этого можно заюзать changelists
    определить кодстайл для компании
    это не вариант, это аксиома, это так должно быть. Не вижу причин для замедления реализации фич, IDE умеет рефачить на лету