image

Не думал, что напишу это, но JavaScript победил. Мы перестали использовать Razor для создания веб-приложений. Вместо этого реализуем front-end в отдельном проекте на JavaScript-фреймворках. От ASP.NET остался только WebAPI и «движок», на котором мы пишем бизнес-логику и API для пользовательского интерфейса.



Вселенная JavaScript и CSS



Последнее время мы наблюдаем взрывное развитие веб-технологий. Появились полноценные IDE для работы с HTML/CSS/JavaScript, проекты типа Grunt и сотни JavaScript-фреймворков. Инфраструктура для создания front-end'а стала взрослой.

Давайте посмотрим на статистику Github. Я нашел два источника статистики по языкам программирования, в обоих JavaScript стоит на первом месте.

В статье Language Trends on GitHub посчитали с помощью Linguist, что JavaScript на первом месте на GitHub по популярности, среди языков программирования:

image

GitHut показывает аналогичную ситуацию:

image

Теперь я понимаю откуда каждую неделю появляются новые JavaScript-фреймворки. Могу себе представить трудозатраты сообщества JavaScript-программистов, которые поставили JavaScript на первое место на github.

Миф о кроссфункциональности



Мы отказываемся верить во всемогущих full-stack web-разработчиков. Full-stack означает, что программист разбирается и в .NET, и в JavaScript/CSS.

Что значит разбираться в этих двух мирах? Это значит знать тонкости работы с браузерами, знать и практиковаться с новыми JavaScript-фреймворками, и одновременно с этим знать о новых фишках в C#, изменениях в платформе .NET, следить за новыми версиями ASP.NET MVC и новым базами данных. Такого всезнающего full-stack web-разработчика я последний раз видел… никогда. Охватить и стать экспертом в этих двух областях не под силу смертному. Я не говорю о людях с железным стержнем и безграничным запасом свободного времени, речь об обычных людях типа меня.

Если вы спросите меня, знаю ли я JavaScript и CSS? Я отвечу, что знаю. Но знаю ли я эти технологии достаточно, чтобы создать качественное решение на front-end? Нет, моих знаний недостаточно, я знаю эти технологии поверхностно по сравнению, например, с front-end разработчиками нашей компании.

Я пришел к выводу, что сложный проект не создать силами full-stack разработчиков . Если речь о сложном UI и сложном back-end, то специализация необходима. Доверять full-stack разработчикам проекты сложнее, чем натягивание дизайна на CMS, настройки интерфейса в SharePoint или кастомизации Bootstrap — губительно для проекта.

История из соседней компании. Lead .NET разработчик усмотрел проблемы на front-end. Он решил, что у UI-проекта неправильная архитектура и технический долг, поэтому он пошел наводить там порядок. В итоге стало еще хуже, чем было, потому что JavaScript-приложение он создавать не умел.

Я думаю похожая ситуация могла бы произойти, если бы JavaScript-разработчик полез в C#. Разница в том, что .NET разработчики считают, что смогут корректно поправить JavaScript/CSS, а front-end разработчики знают, что им в C# лучше не залезать и они не лезут.


Схема взаимодействия



На старте работы мы делаем два проекта. Первый проект традиционный — ASP.NET Web API приложение в Visual Studio, второй проект в Webstorm. Оба проекта лежат в одном репозитории, хотя это не обязательно.

image

Front-end разработчики согласуют с back-end разработчиками API, через которое происходит взаимодействие двух приложений.

Процесс работы



Мы создаем проектные команды, поэтому разработчики, QA и другие члены команды входят в состав единой команды проекта. В том числе front-end и back-end разработчики входят в эту команду. Единая команда работает с Impact Mapping, Customer Journey Mapping, User Story Mapping, которые появляются во время процесса создания ПО:

image

Видно, что с точки зрения процесса создания ПО, мы никак не разделяем front-end и back-end части. Это осознанный шаг, который помогает делать поставку бизнес-ценности.

Плюсы и минусы



В разделении front-end и back-end на два проекта я нахожу и плюсы и минусы:
  • Плюсы
    1. Front-end и back-end проекты слабо связаны. Становится возможно развиваться эти проекты параллельно или отдельно друг от друга.
    2. У вас случалось, что кроме веб-интерфейса, вас просят создать API к Android-приложению? У нас заказчики просили об этом и не раз. Если вы изначально создаете API, документируете API, то подключение новых клиентов к нему не составляет труда.
    3. Выкладка  front-end и back-end частей теперь может происходить независимо. Вам не придется перезаливать монолитное ASP.NET MVC приложение из-за изменений в JavaScript/CSS или разметки.
    4. Чем сложнее проект, тем сложнее управлять монолитным ASP.NET MVC приложением. Если разнести единое приложение на два проекта, как показано в статье, то развивать два небольших проекта проще.
    5. В монолитном ASP.NET MVC приложение цена ошибки это весь проект. В раздельных проектах цена ошибки это части системы.

  • Минусы
    1. Нужны сильные front-end разработчики, которые могут и не понадобится, если full-stack разработчики создают back и front.
    2. Следствие из предыдущего пункта — нужно больше людей в проект.
    3. Инфраструктура сложнее, усложняется процесс сборки релиза.
    4. Дополнительно время тратиться на согласование API между двумя проектами.
    5. Изменения в бизнес-логике часто затрагивают оба проекта.



Выбор подхода



Мы выбираем ASP.NET MVC приложение и рендер HTML через Razor, если используем CMS или пишем небольшой проект без сложной бизнес-логики. Например, так сделан сайт компании ByndyuSoft. Мы выбираем front-end в виде JavaScript-приложения во всех остальных случаях.

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


  1. kuber
    18.01.2016 10:51
    +6

    Понятно, что нет необходимости использовать Razor если вы используете Web API, но если вы используете ASP.net MVC, то Razor просто шикарен и я не встречал шаблонизатор лучше.


    1. AlexanderByndyu
      18.01.2016 11:23

      Речь скорее о том, что мы ушли от шаблонизатора Razor и перешли к JS-шаблонизаторам в отдельном JS-приложении. Если мы создаем ASP.NET MVC приложение и рендерим с помощью него HTML, то используем Razor.


      1. kuber
        18.01.2016 11:49

        Я так и понял.


      1. IL_Agent
        18.01.2016 12:20

        Не думал, что напишу это, но JavaScript победил. Мы перестали использовать Razor для создания веб-приложений.

        Исходя из названия статьи и первых её фраз можно было подумать, что вы собираетесь утверждать о ненужности server-side rendering как такового :)


        1. AlexanderByndyu
          18.01.2016 12:23

          Надеюсь продолжение статьи развеивает это впечатление.


          1. IL_Agent
            18.01.2016 12:28

            Да, противоречит ему


  1. AigizK
    18.01.2016 12:54
    +1

    У, такими темпами скоро дойдете до того, что бекэнд будет не на ASP.NET ))


    1. AlexanderByndyu
      18.01.2016 12:58
      +4

      От .NET мы вряд ли откажемся, но скорее всего перейдем на кросс-платформенную версию. Уже пробовали компилировать и запускать проекты под Linux, выглядит многообещающе.


      1. justmara
        18.01.2016 13:16

        Главное — не пытайтесь портировать имеющиеся. На данный момент это та ещё боль.


    1. ruslanys
      18.01.2016 13:47

      А на Node.JS, например)


      1. AlexanderByndyu
        18.01.2016 13:49

        В Facebook уже обсудили эту тему www.facebook.com/alexander.byndyu/posts/946206085463803?comment_id=946214718796273&comment_tracking=%7B%22tn%22%3A%22R%22%7D

        JavaScript с обеих сторон не отменяет того, что цели у бэка и фронта разные и среды исполнения разные.


      1. Razaz
        19.01.2016 13:51
        +1

        Нода хороша только на IO. Compute — не ее. А .Net дает и то и другое. github.com/aspnet/benchmarks. Либо Java/Scala либо .Net.
        17 декабря уже Kestrel perf target #1million


  1. AigizK
    18.01.2016 14:14
    +1

    А БД какую используете или собираетесь использовать, если будете еще на Linux запускать? И ваша команда вроде практиковала CQRS подход, не отказались еще?


    1. AlexanderByndyu
      18.01.2016 16:10

      Из БД у нас больше всего используются MSSQL, PosgtreSQL, MongoDB, Sphinx. Три последние мы хостим на Linux.

      Да, мы практикуем CQRS. Нам нравится, пока альтернативы не нашли :)


  1. SergeyRodyushkin
    18.01.2016 17:20
    +7

    А не могли бы вы рассказать, как в проектах с подобной архитектурой реализуется валидация правил, локализация и подобные вещи, имеющие отношение как к UI, так и к бизнес-логике? В каком виде приходят сообщения об ошибках?


    1. Shablonarium
      19.01.2016 15:33

      Подпишусь на этот вопрос.


    1. AlexanderByndyu
      19.01.2016 17:21
      +3

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


    1. osharper
      20.01.2016 00:01

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


      1. AlexanderByndyu
        21.01.2016 12:20

        > локализацию лучше как раз отдать рейзору и бэкэнду, чем тому же ангуляру

        Какая разница где писать переводы? Механизмы выбора перевода одинаковые. Из текста по ключу выбирается перевод в зависимости от локали.


    1. marshinov
      20.01.2016 10:19

      Локализацию можно использовать из *.resx-файлов. Для этого потребуется сгенерировать часть js-кода со стороны .NET и отдать отдельным файлом. Для большинства проектов оверхед на один запрос не значительный, работает хорошо. Файл создается только один раз при старте приложения или встраивается в билд-процесс.

      Для валидации так-же можно генерировать js-код на сервере, используя DataAnnotations. В случае с кастомной валидацией, которая нужно описывать в виде императивного кода — ничего не поделаешь — нужно дублировать код.

      Если хочется совсем упороться, то можно посмотреть в сторону Roslyn и конвертировать C#-код валидации в JS. Есть вот такой пример конвертирования C# в С++ от mezastel. Учитывая, что в ES6 есть поддержка лямбд подобная задача может быть интересна с исследовательской точки зрения. В коммерческой разработке применять такие решения скорее всего дороговато.


    1. AlexanderByndyu
      21.01.2016 12:19
      +1

      > реализуется валидация правил

      Валидация реализуется на front-end и back-end приложениях.

      Часть валидаций относятся только к front-end, например, пока поле не заполнено не нажимать кнопку.

      Часть валидаций одинаковые для front и back, например, валидация формата телефона или бизнес-правило не добавлять в корзину Х, если там уже Y. В этом случае логика реализуется и на front и на back.

      Часть валидаций только на back, например, является ли логин уникальным.

      По сути ничего не изменилось со времен, когда мы использовали только ASP.NET MVC. Единственная разница это отсутствие атрибутов валидации, которые можно было вешать на модель. Но это почти не заметно в работе, т.к. эти атрибуты покрывают обычно самую простую валидацию: пустные поля, маска для поля и т.п.

      > локализация

      Локализация front-end делается стандартными средствами. Можно для примера посмотреть как сделана локализация jQuery UI. Есть файл с переводами, есть механизмы выбора переводов из этого файла. Очень похоже на то, как сделаны переводы через ресурсы в .NET

      > В каком виде приходят сообщения об ошибках?

      Они приходят ответом на Ajax-запрос, а формат такой, какой будет согласован. Обычно это просто JSON.


      1. SergeyRodyushkin
        21.01.2016 13:10
        +1

        Спасибо за развёрнутый ответ. Поясню, моя цель, в общих чертах, состоит в уменьшении связности между backend и frontend для параллельной разработки. Есть общее соглашение о формате данных, но в частностях хотелось бы оставить некоторую свободу — например, чтобы изменение правил валидации не влекло за собой необходимость одновременной модификации frontend. Пока я склоняюсь к публикации неких метаданных с backend, подобно IClientValidatable-правилам. Сначала я хотел избежать необходимости локализации и клиента, и API, но, похоже, это мечты :)