DevOps в разработке: автоматизация написания кода веб-приложений

Доброго времени суток, уважаемые Хабражители!

Сегодня DevOps находится на волне успеха. Практически на любой конференции, посвященной автоматизации, можно услышать от спикера мол “мы внедрили DevOps и тут и там, применили это и то, вести проекты стало значительно проще и т. д. и т. п.”. И это похвально. Но, как правило, внедрение DevOps во многих компаниях заканчивается на этапе автоматизации IT Operations, и очень мало кто говорит о внедрении DevOps непосредственно в сам процесс разработки.

Мне бы хотелось исправить это маленькое недоразумение. DevOps в разработку может прийти через формализацию кодовой базы, например, при написании GUI для REST API.

В этой статье хотелось бы поделиться с вами решением нестандартного кейса, с которым столкнулась наша компания – нам довелось автоматизировать формирование интерфейса веб-приложения. Я вам расскажу о том, как мы пришли к данной задачей и что использовали для ее решения. Мы не считаем, что наш подход является единственно верным, но нам он очень даже нравится.

Надеюсь данный материал будет вам интересен и полезен.

Ну что ж, начнем!

Предыстория


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

Процесс добавление новой фичи на старой архитектуре

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

  1. На back-end’e: создать модель для новой сущности (хуки), описать поля данной модели, описать всю логику действий (actions), которые данные модель может выполнять и т. д.
  2. На front-end’e: создать класс представления, соответствующий новой модели в API, вручную описать все поля, которые у данной модели есть, добавить все типы action’ов, которые данное представление может запустить и т. д.

Выходит, что нам одновременно сразу в двух местах, необходимо было сделать очень похожие изменения в коде, так или иначе, “дублирующие” друг друга. А это, как известно, не есть хорошо, поскольку при дальнейших изменениях, разработчикам нужно было бы вносить правки так же в двух местах одновременно.

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

Не слишком ли всё сложно?

Ранее мы мирились с данным фактом, поскольку многие приложения были не очень большими и подход с “дублированием” кода на сервере и на клиенте имел место быть. Но в тот самый летний день, перед началом внедрения новой фичи, внутри нас что-то щелкнуло, и мы поняли, что дальше так работать нельзя. Текущий подход являлся весьма неразумным и требовал больших временных и трудовых затрат. К тому же, “дублирование” кода на back-end’е и на front-end’e могло в будущем привести к неожиданным багам: разработчики могли бы внести изменения на сервере и забыть внести аналогичные изменения на клиенте, и тогда все пошло бы не по плану.

Как избежать дублирования кода? Поиск решения


Мы стали задумываться, как нам можно оптимизировать процесс внедрения новых фич.

Мы задали сами себе вопрос: «Можем ли мы прямо сейчас избежать дублирования изменений в представлении модели на front-end’e, после любого изменения в ее структуре на back-end’e?»

Мы подумали и ответили: «Нет, не можем».

Тогда мы задали себе еще один вопрос: «Окей, в чем тогда заключается причина подобного дублирования кода?»

И тут нас осенило: проблема, по сути, в том, что наш front-end не получает данных о текущей структуре API. Front-end ничего не знает о моделях, существующих в API, до тех пор, пока мы сами ему об этом не сообщим.

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

  • Front-end получал из API не только данные моделей, но и структуру этих моделей;
  • Front-end динамически формировал представления на основе структуры моделей;
  • Любое изменение в структуре API автоматически отображалось на front-end’e.

Внедрение новой фичи будет занимать гораздо меньше времени, поскольку будет требовать внесения изменений только на стороне back-end’a, а front-end автоматически все подхватит и представит пользователю должным образом.

Универсальность новой архитектуры


И тогда, мы решили подумать еще несколько шире: является ли новая архитектура пригодной только для нашего текущего приложения, или мы можем использовать ее где-то еще?

Общие для многих веб-приложений фичи

Ведь, так или иначе, почти все приложения имеют часть схожего функционала:

  • почти по всех приложениях есть пользователи, и в связи с этим необходимо иметь функционал связанный с регистрацией и авторизацией пользователя;
  • почти во всех приложениях есть несколько типов представлений: есть представление для просмотра списка объектов какой-то модели, есть представление для просмотра детальной записи одного, отдельного взятого, объекта модели;
  • почти у всех моделей есть схожие по типу атрибуты: строковые данные, числа и т. д., и в связи с этим, нужно уметь работать с ними как на back-end’е, так и на front-end’е.

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

Таким образом, в ходе долгих рассуждений у нас появилась идея о создании VSTUtils – фреймворка, который бы:

  1. Содержал в себе базовый, максимально схожий для большинства приложений, функционал;
  2. Позволял бы генерировать front-end на лету, основываясь на структуре API.

Как подружить back-end и front-end?


Ну что ж, надо делать, подумали мы. Некий back-end у нас уже был, некий front-end тоже, но ни на сервере, ни на клиенте не было инструмента, который мог бы сообщить или получить данные о структуре API.

В ходе поисков решения данной задачи наш глаз пал на спецификацию OpenAPI, которая на основе описания моделей и взаимосвязей между ними генерирует огромный JSON, содержащий всю эту информацию.

И мы подумали, что, по идее, при инициализации приложения на клиенте front-end может получать от API данный JSON и на его основе строить все необходимые представления. Остается только научить наш front-end все это делать.

И спустя некоторое время мы его таки научили.

Версия 1.0 – что по итогу вышло


Архитектура фрейворка VSTUtils первых версий состояла из 3 условных частей и выглядела примерно так:

  1. Back-end:
    • Django и Python – вся логика связанная с моделями. На основе базовой модели Django Model мы создали несколько классов основных моделей VSTUtils. Все actions, которые могут выполнять данные модели мы реализовали с помощью Python;
    • Django REST Framework – генерация REST API. На основе описания моделей формируется REST API, благодаря которому происходит общение сервера и клиента;
  2. Прослойка между back-end’ом и front-end’ом:
    • OpenAPI – генерация JSON’а с описанием структуры API. После того, как на back-end’е были описаны все модели, для них создаются views. Добавление каждой из views вносит необходимую информацию в итоговый JSON:
      Пример JSON'a – схема OpenAPI
      {
          // объект, хранящий в себе пары (ключ, значение),
          // где ключ - имя модели,
          // значение - объект с описанием полей модели.
          definitions: {
              // описание структуры модели Hook.
              Hook: {
                  // объект, хранящий в себе пары (ключ, зачение),
                  // где ключ - имя поля модели,
                  // значение - объект с описанием свойств данного поля (заголовок, тип поля и т.д.).
                  properties: {
                      id: {
                          title: "Id",
                              type: "integer",
                              readOnly: true,
                      },
                      name: {
                          title: "Name",
                              type: "string",
                              minLength:1,
                              maxLength: 512,
                      },
                      type: {
                          title: "Type",
                              type: "string",
                      enum: ["HTTP","SCRIPT"],
                      },
                      when: {
                          title: "When",
                              type: "string",
                      enum: ["on_object_add","on_object_upd","on_object_del"],
                      },
                      enable: {
                          title:"Enable",
                              type:"boolean",
                      },
                      recipients: {
                          title: "Recipients",
                              type: "string",
                              minLength: 1,
                      }
                  },
                  // массив, хранящий в себе имена полей, являющихся обязательными для заполнения.
                  required: ["type","recipients"],
              }
          },
          // объект, хранящий в себе пары (ключ, значение),
          // где ключ - путь предсталения (шаблонный URL),
          // значение - объект с описанием свойств представления.
          paths: {
              // описание структуры представлений по пути '/hook/'.
              '/hook/': {
                  // схема представления для get запроса по пути /hook/.
                  // схема представления, соответствующей странице просмотра списка объектов модели Hook.
                  get: {
                      operationId: "hook_list",
                          description: "Return all hooks.",
                          // массив, хранящий в себе объекты со свойствами фильтров, доступных для данного списка объектов.
                          parameters: [
                          {
                              name: "id",
                              in: "query",
                              description: "A unique integer value (or comma separated list) identifying this instance.",
                              required: false,
                              type: "string",
                          },
                          {
                              name: "name",
                              in: "query",
                              description: "A name string value (or comma separated list) of instance.",
                              required: false,
                              type: "string",
                          },
                          {
                              name: "type",
                              in: "query",
                              description: "Instance type.",
                              required: false,
                              type: "string",
                          },
                      ],
                          // объект, хранящий в себе пары (ключ, значение),
                          // где ключ - код ответа сервера;
                          // значение - схема ответа сервера.
                          responses: {
                          200: {
                              description: "Action accepted.",
                                  schema: {
                                  properties: {
                                      results: {
                                          type: "array",
                                              items: {
                                              // ссылка на модель, данные которой пришли в ответе от сервера.
                                              $ref: "#/definitions/Hook",
                                          },
                                      },
                                  },
                              },
                          },
                          400: {
                              description: "Validation error or some data error.",
                                  schema: {
                                  $ref: "#/definitions/Error",
                              },
                          },
                          401: {
                              // ...
                          },
                          403: {
                              // ...
                          },
                          404: {
                              // ...
                          },
                      },
                      tags: ["hook"],
                  },
                  // схема представления для post запроса по пути /hook/.
                  // схема представления, соответствующей странице создания нового объекта модели Hook.
                  post: {
                      operationId: "hook_add",
                          description: "Create a new hook.",
                          parameters: [
                          {
                              name: "data",
                              in: "body",
                              required: true,
                              schema: {
                                  $ref: "#/definitions/Hook",
                              },
                          },
                      ],
                          responses: {
                          201: {
                              description: "Action accepted.",
                                  schema: {
                                  $ref: "#/definitions/Hook",
                              },
                          },
                          400: {
                              description: "Validation error or some data error.",
                                  schema: {
                                  $ref: "#/definitions/Error",
                              },
                          },
                          401: {
                              // ...
                          },
                          403: {
                              // ...
                          },
                          404: {
                              // ...
                          },
                      },
                      tags: ["hook"],
                  },
              }
          }
      }
  3. Front-end:
    • JavaScript – механизм, парсящий схему OpenAPI и генерирующий представления. Данный механизм запускается один раз, при инициализации приложения на клиенте. Отправив запрос к API, он получает в ответ запрашиваемый JSON с описанием структуры API и, анализируя его, создает все необходимые JS объекты, содержащие параметры представлений моделей. Данный запрос к API довольно увесистый, поэтому мы его кэшируем и запрашиваем повторно только при обновлении версии приложения;
    • JavaScript SPA libs – рендеринг представлений и маршрутизация между ними. Данные библиотеки были написаны одним из наших front-end разработчиков. При обращении пользователя к той или иной странице, механизм рендеринга производит отрисовку страницы, на основе параметров сохраненных ранее в JS объектах представлений.

Таким образом, что мы имеем: у нас есть back-end, на котором описана вся логика, связанная с моделями. Затем в игру вступает OpenAPI, который на основе описания моделей формирует JSON с описанием структуры API. Далее эстафетная палочка передается клиенту, который анализируя сформированный OpenAPI JSON автоматически генерирует веб-интерфейс.

Внедрение фичи в приложение на новой архитектуре – как это работает


Помните задачу про добавление пользовательских хуков? Вот как бы мы ее реализовали в приложении на базе VSTUtils:

Процесс добавление новой фичи на новой архитектуре

Теперь благодаря VSTUtils нам не нужно ничего писать с нуля. Вот, что мы делаем, чтобы добавить возможность создавать пользовательские хуки:

  1. На back-end’e: берем и наследуемся от самого подходящего класса в VSTUtils, добавляем новый функционал, характерный для новой модели;
  2. На front-end’e:
    • если представление для данной модели ничем не отличается от базового представления VSTUtils, то ничего не делаем, все автоматически отображается должным образом;
    • если нужно как-то изменить поведение представления, с помощью механизма сигналов декларативно расширяем либо полностью изменяем базовое поведение представления.

В итоге, у нас получилось довольно неплохое решение, мы добились своей цели, наш front-end стал автогенерируемым. Процесс внедрения новых фич в существующие проекты заметно ускорился: релизы стали выходить раз в 2 недели, тогда как ранее мы выпускали релизы раз в 2-3 месяца с гораздо меньшим количеством новых фич. Хотелось бы заметить, что команда разработчиков осталась прежней, такие плоды нам дала именно новая архитектура приложения.

Версия 1.0 – перемен требуют наши сердца


Но, как известно, нет предела совершенству, и VSTUtils не стал исключением.

Не смотря на то, что нам удалось автоматизировать формирование front-end’а, получилось не прям то решение, которое мы изначально хотели.

Архитектура приложения на стороне клиента не была досконально продумана, и получилась не столь гибкой, какой могла бы быть:

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

И поскольку в нашей компании мы придерживаемся DevOps подхода и стараемся наш код максимально стандартизировать и формализовать, то в феврале этого года мы решили провести глобальный рефакторинг front-end’a фреймворка VSTUtils. У нас было несколько задач:

  • формировать на front-end’е не только классы представлений, но и классы моделей – мы поняли, что было бы правильней отделять данные (и их структуру) от их представления. К тому же, наличие нескольких абстракций в виде представления и модели значительно бы облегчило добавление перегрузок базового функционала в проектах на базе VSTUtils;
  • использовать для рендеринга и маршрутизации протестированный фреймворк, с большим сообществом (Angular, React, Vue) – это позволит нам отдать всю головную боль с поддержкой кода, связанного с рендерингом и маршрутизацией внутри нашего приложения.

Рефакторинг – выбор JS фреймворка


Среди наиболее популярных JS фреймворков: Angular, React, Vue, наш выбор пал на Vue поскольку:

  • Кодовая база Vue весит меньше, чем у React и Angular;

    Сравнительная таблица размеров фреймворков Gzipped версии
    Фреймворк Размер, kb
    Angular 2 111
    Angular 2 + RX 143
    Angular 1.4.5 51
    React 0.14.5 + React DOM 40
    React 0.14.5 + React DOM + Redux 42
    React 15.3.0 + React DOM 43
    Vue 2.4.2 21
  • процесс рендеринга страницы у Vue занимает меньше времени, чем у React и Angular;
    сравнение скорости рендеринга страниц разными javascript фреймворками относительно чистого javascript
  • Порог входа в Vue гораздо ниже, чем в React и Angular;
  • Нативно понятный синтаксис шаблонов;
  • Шикарная, подробнейшая документация, доступная на нескольких языках, в том числе и на русском;
  • Развитая экосистема, предоставляющая, помимо базовой библиотеки Vue, библиотеки для маршрутизации и для создания реактивного хранилища данных.

Версия 2.0 – результат рефакторинга front-end’а


Процесс глобального рефакторинга front-end’а VSTUtils занял около 4 месяцев и вот что у нас в итоге вышло:

новая архитектура fron-end VSTUtils

Front-end фреймворка VSTUtils по-прежнему состоит из двух больших блоков: первый занимается парсингом схемы OpenAPI, второй – рендерингом представлений и маршрутизацией между ними, но оба этих блоков перенесли ряд существенных изменений.

Был полностью переписан механизм, парсящий схему OpenAPI. Изменился подход к парсингу этой схемы. Мы постарались сделать архитектуру front-end’а максимально похожей на архитектуру back-end’a. Теперь на стороне клиента у нас есть не просто единая абстракция в виде представлений, теперь у нас есть еще абстракции в виде моделей и QuerySet’ов:

  • объекты класса Model и его потомков – объекты, соответствующие абстракции Django Models на стороне сервера. Объекты данного типа содержат в себе данные о структуре модели (имя модели, поля модели и т. д.);
  • объекты класса QuerySet и его потомков – объекты, соответствующие абстракции Django QuerySets на стороне сервера. Объекты данного типа, содержат в себе методы, позволяющие выполнять запросы к API (добавление, изменение, получение, удаление данных объектов моделей);
  • объекты класса View – объекты, хранящие в себе данные о том, каким образом нужно представить модель на той или иной странице, какой шаблон использовать для «рендеринга» страницы, на какие другие представления моделей может ссылаться данная страница и т. п.

Блок, отвечающий за рендеринг и маршрутизацию, тоже заметно преобразился. Мы отказались от самописных JS SPA библиотек в пользу фреймворка Vue.js. Мы разработали собственные Vue компоненты, из которых строятся все страницы нашего веб-приложения. Маршрутизация между представлениями осуществляется с помощью библиотеки vue-router, а в качестве реактивного хранилища состояния приложения мы используем vuex.

Хотелось бы также отметить, что на стороне front-end’а реализация классов Model, QuerySet и View не зависит от средств реализации рендеринга и маршрутизации, то есть если мы вдруг захотим перейти от Vue к какому-то другому фреймворку, например на React или на что-то новое, то все что нам нужно будет сделать, это переписать компоненты Vue на компоненты нового фреймворка, переписать роутер, хранилище, и все – фреймворк VSTUtils снова будет работоспособен. Реализация классов Model, QuerySet и View останется прежней, поскольку никак не зависит от Vue.js. Мы считаем, что это является весьма неплохим подспорьем для возможных будущих изменений.

Подведем итоги


Таким образом, нежелание писать “дублирующий” код вылилось в задачу по автоматизации формирования front-end’a веб-приложния, которая была решена с помощью создания фреймворка VSTUtils. Нам удалось построить архитектуру веб-приложения так, что back-end и front-end гармонично дополняют друг друга и любое изменение в структуре API автоматически подхватывается и отображается должным образом на клиенте.

Преимущества, которые мы получили от формализации архитектуры веб-приложения:

  • Релизы приложений, работающих на базе VSTUtils стали выходить в 2 раза чаще. Это связанно с тем, что теперь для внедрения новой фичи, зачастую, нам необходимо добавить код только на back-end’e, front-end автоматически сформируется – это значительно экономит время;
  • Упростили обновление базового функционала. Так как теперь весь базовый функционал собран в одном фреймворке, то для того, чтобы обновить какие-то важные зависимости или внести улучшение в базовый функционал, нам необходимо внести правки только в одном месте – в кодовой базе VSTUtils. При обновлении версии VSTUtils в дочерних проектах все нововведения автоматически подхватятся;
  • Поиск новых сотрудников стал легче. Согласитесь, гораздо проще найти разработчика под формализованный стек технологий (Django, Vue), чем искать человека, который согласится работать с неизвестным самописом. Результаты поиска разработчиков, упомянувших в своем резюме Django или Vue на HeadHunter’е (по всем регионам):
    • Django – найдено 3 454 резюме у 3 136 соискателей;
    • Vue – найдено 4 092 резюме у 3 747соискателей.

К недостаткам подобной формализации архитектуры веб-приложения можно отнести следующее:

  • За счет парсинга схемы OpenAPI инициализация приложения на клиенте занимает чуть больше времени, чем ранее (примерно на 20-30 миллисекунд дольше);
  • Неважная поисковая индексация. Дело в том, что в данный момент мы никак не задействуем серверный рендеринг в рамках VSTUtils, и весь контент приложения формируется в итоговом виде уже на клиенте. Но нашим проектам, зачастую высокая поисковая выдача не нужна и для нас это не так критично.

На этом мой рассказ подходит к концу, спасибо за внимание!

Полезные ссылки


Share post

Comments 25

    0
    А почему OpenApi, когда имхо для вашей задачи прекрасно подходит GraphQL?
      +1

      Переписывать структуру запросов backend'а ради схемы было не вариант просто. Это потребовало бы переписать ещё и тонну тестов. А так на уже готовую REST API положили GUI.

      +1
      Не понял, при чем тут devops? Без k8s, gitlab ci и Amazon EC2 (GCE, Azure) — не считается :)
        +3
        DevOps подразумевает под собой набор методов и средств, позволяющих повысить производительность команды, увеличить количество и качество выпускаемых релизов, ускорить процесс поставки продукта клиенту.

        DevOps ведь не ограничивается средствами по автоматизации тестирования и развертывания кода.

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

        А так, само собой, в своей работе мы используем GitLab CI/CD для автоматизации тестирования и сборки, и OpenStack в качестве облачного сервиса.

        Просто в этой статье я хотел сделать упор на автоматизации процесса написания кода, а не на автоматизацию тестирования или развертывания.
          0
          Не, вы, без сомнения, молодцы — запилили крутую штуку, тут сомнения нет. Просто я как-то привык, что в DevOPS есть OPS часть, с Linux, nginx и вот этим всем.
          А под «XXX подразумевает под собой набор методов и средств, позволяющих повысить производительность команды, увеличить количество и качество выпускаемых релизов, ускорить процесс поставки продукта клиенту.» подходит тот же Agile, TDD и еще куча всего
        –1
        Хороший заход, но ИМХО будущее за единой кодовой базой.
        Blazor хороший пример этого веяния.
          +1

          Раз уж DevOps, то нужно идти до конца и генерировать скрипты фронта на бэке при пуше изменений. Тогда и клиенту будет легче и… можно все сделать на питоне ;)

            0

            Только ситхи всё возводят в абсолют.
            Но мысли насчёт питона на фронте были. Правда вес скриптов (3.5мб) отбил всё желание.

              0
              Вы не поняли, можно Javascript клиента генерировать питоном на backend-е. Хотя проще, конечно, было все писать на Javascript/Node…
                +1

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

                  0
                  Я ж не предлагал переписать…
                    0

                    А как вы себе это представляете? Вопрос без подвоха. Просто интересно как можно дать фронту информацию из DRF через Node.

            0
            Мы отказались от самописных JS SPA библиотек в пользу фреймворка Vue.js.


            Т.е. в самой первой версии
            механизм, парсящий схему OpenAPI и генерирующий представления

            был написан на vanilla-js?
              +1
              И в первой и во второй версиях front-end можно условно разделить на 2 блока. Первый занимается парсингом схемы OpenAPI и формирует JS объекты с параметрами для отрисовки представлений (заголовок представления, для какой модели это представление, на какие другие представления строить ссылки и т. д.), второй – рендерингом представлений и маршрутизацией между ними.

              JS объекты с параметрами представлений, сформированные на этапе парсинга схемы OpenAPI, передают некоторые из своих свойств в качестве входных параметров компонентам, которые занимаются рендерингом.

              В обоих версиях механизм, парсящий схему OpenAPI, реализован на нативном JS, но эта реализация отличается.

              Блок, занимающийся рендерингом и маршрутизацией, в первой версии был реализован с помощью библиотек для создания SPA приложения, которые были написаны вне этого проекта одним из наших разработчиков. Они содержат в себе свой шаблонизатор, роутер и т. д. Они были некой альтернативой JS фреймворкам типа Angular’а, React’а или Vue.
              Во второй версии для рендеринга и маршрутизации мы используем Vue.js.
              0

              Представляю как вы удивитесь, когда увидите, как в 1С модели бэкенда, фронтэнда и в бд меняются синхронно в конструкторе описания объекта, вообще без изменения кода ;)

                0
                Аж стало интересно, не смотря на упоминание 1С =)
                  +1

                  Да это и грустно и смешно)
                  То, что в этой статье представляется как что-то новое реально в 1С используется уже 20 лет)) А потом говорят они, на русском пишут, на русском))

                    +1

                    А вот и "Свидетели 1С" подтянулись…
                    Вот я против 1С на той нише где оно изначально работает ничего против не имею, но вы серьёзно сейчас?:)
                    Вы понимаете разницу между веб-фреймворком на любом ЯП и проприоретарной платформой со скиптовым внутренним языком?
                    Это всё равно что сказать, что на Python/PHP/любом ЯП уже давно можно работать через web, а 1С только несколько лет назад научились.

                      0

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


                      Не-в-1С добавление поля в модель влечёт кучу лишних телодвижений и порождает решения похожие тем, что в статье. В 1С модель на первом месте, все сопутствующее: схема БД, GUI — изменяются сами

                        0

                        Думаю, что если бы в конструкторе был бы гемор с моделями, которые в нём представлены, то 1С вообще бы никто и никогда не смог и не захотел бы использовать. Я же говорю, это люто некорректное сравнение конструктора (коим 1С является) и веб-фреймворка. Если их сравнивать, то последний однозначно победит, хотя бы за счёт возможностей языка и производительности.

                          0
                          Как понять «некорректное сравнение»? Некорректное относительно чего? Скорость написания бизнес приложений под 1С очень высока. Вывести на рынок систему, написав ее на 1С можно очень быстро. Прототипы на ней же — тоже делаются быстро как раз за счет «конструкторности». Если же сравнивать относительно гибкости — то да, веб фреймворки здесь дают гораздо больше контроля, но и руками всякую нудятину приходится делать вроде перекладывания из DTO в базу данных и обратно, рисования сотен форм и тонн бойлерплейта. Так что все относительно. Хейтить 1С за то что там «кодят на русском» — однозначно не стоит.
                            0
                            Вывести на рынок систему, написав ее на 1С можно очень быстро.

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


                            Хейтить 1С за то что там «кодят на русском» — однозначно не стоит.

                            Причём здесь русский язык? Там и на английском можно, просто никто не пишет ибо незачем: зарубежом никто (бывшие из СССР не считаются) не использует 1С.

                              0

                              Ну на днях виноделов из Италии показывали, которые на 1С работают, так что "никто" слишком ложное утверждение. Да и цена приложения для корп. рынка не такая уж высокая. По совокупности функций на джаве с нуля писать будет не дешевле для заказчика.

                +1
                1. Нафига толстый клиент, в таком случае? Можно просто использовать генерацию HTML на сервере.


                2. Генерация моделей на основе API — это как бы совсем не новость и давно есть инструменты для описания и генерации, например, как у protobuf и многое другое.


                3. Хоть для чего-то примитивного это и удобно, но концептуально уровень отображения чего-то клиенту и уровень обработки данных на сервере — это вообще не одно и тоже.



                P.S. Если это DevOps, то с таким успехом снять квартиру ближе к офису и не опаздывать на работу — это тоже DevOps.

                  0

                  Модельки на сервере и клиенте пишутся отдельными людьми. Вы изобретаете велик для того чтобы генерить DTO клиента и сервера на основе некоторого описания API, что-то похожее на swagger-gen или JHipster (в дотнетовском мире наверняка есть аналоги посимпатичнее). Бывает так, что к фронту особых требований нет и можно сразу генерировать например формочки. А для статьи вы называете свой велик девопс-фреймворком.

                  Only users with full accounts can post comments. Log in, please.