Да-да, я знаю, Vue 3 находится в stable-версии, и даже Nuxt наконец-то обновился. Но именно 3-й Vue с его provider / inject подтколкнул меня к поиску решения о том, как можно удобно инкапсулировать бизнес-логику во Vue 2.

Введение

Начнем с вопроса "Почему нельзя просто обновиться до Vue 3?". Все просто, некоторые проекты обладают таким уровнем связанности с другими проектами, что это невозможно сделать быстро. Где-то возможно используются специфичные пакеты, которые были написаны только под 2-ю версию Vue. Где-то разработчиков устраивает Vue 2, а даже если бы они и перешли на Vue 3, они продолжали бы писать на Options API (скажу сразу, я не проверяла свое решение на Vue 3, так что не уверена сработает ли такой подход там, но вообще должен).

Как можно инкапсулировать логику

На просторах интернета и участвуя в вопросах, задаваемых в чатах (по типу "Vue.js - русскоговорящее сообщество"), да и просто работая, чаще всего я видела несколько решений. Давайте разберем их плюсы и минусы.

Вынести во Vuex/Pinia/Другой стейт менеджер

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

Доходит до смешного, человек спрашивал как можно передать строку поиска из компонента в соседний (у них общий родитель). Ему накинули несколько решений, и человек выбрал Vuex, потому что на его взгляд это проще.

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

Pros

  • Часто советуют, легко найти помощь

  • Использование vuex интуитивно понятно

  • Возможно внушает чувство безопасности

  • В целом легко читается, понятно откуда приходят данные

  • Можно получить только те данные, которые тебе нужны в конкретном компоненте

Cons

  • Вызывает баги, если пытаться хранить временные данные (которые должны чиститься, или меняться в зависимости от контекста)

  • Невозможно переиспользовать логику (модуль один на сайт, от этого ты никуда не денешься, дополнительный экземпляр не создашь) только если не сделать 10 одинаковых модулей

  • Используя недолго эту логику, она все равно останется в памяти, хоть и больше не требуется

  • Данные не защищены, любой компонент может изменить их с помощью прямого обращения к state

Миксины

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

Pros

  • опять же интуитивно понятно, выглядит как кусок компонента

  • другого способа интегрировать общий хук, или фреймворко-зависимые элементы особо нет

Cons

  • Если само написание миксина действительно интуитивно понятно, то вот чтение компонента, использующего миксин совершенно нечитабельно. Ты выделяешь переменную, ищешь ее по файлу, а ее просто нет, и вот эту маленькую строчку mixins очень легко пропустить.

  • Легко затереть функциональность миксина, используя случайно те же имена свойств/методов

  • Иногда миксины используют свойства, которые должны быть определены в компоненте, а ты можешь этого не знать

  • Невозможно расшарить данные (только если не положить их во vuex)

  • Подходит только для переиспользования кода, что-то глобальное сделать с помощью миксина не получится

  • Выбрать какие методы/свойства тебе нужны нельзя

Provide / Inject

Это уже не самый популярный способ, не все знают про эту опцию. Многие знают про то, что это есть во Vue 3, но во Vue 2 provide появился еще в версии 2.2.0. Подробнее можно почитать по ссылке.

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

Pros

  • Позволяет передавать данные на любую глубину

  • Можно выбрать, что ты будешь инъектить

Cons

  • Требует общего родителя, в худшем случае придется делать это на странице или в App что засоряет код

  • Таким образом не получится переиспользовать код, это больше про распространение данных

  • Если сделать экземпляр класса (каким-то образом, я не пробовала), то ты его себе заберешь целиком, нет возможности выбрать, что тебе надо

  • Не интуитивно и не очевидно, что будет происходить с реактивностью, где менять эти данные, и вообще вызывает много вопросов

Почему я упомянула provide/inject в начале

Когда я писала на Vue 2, у меня даже примерной идеи не было, как бы можно было инкапсулировать логику. Мне казалось, что в том формате, как мы делаем компоненты, это будет по-любому неудобно, непонятно, и как-то костыльно.

Vue 3 с Composition API открыл для меня новую веху, там можно сделать экземпляр класса, полностью обернуть его в reactive, сделать provide прям на этапе создания приложения (т.е. в index.js условном, что было понятно).

Но и это решение меня не до конца устраивало, мне хотелось сделать это как-то по-другому. Пока я об этом думала, я перешла на другой проект, который написан на Vue 2, и это подтолкнуло меня к поиску решения.

Вынести в функции

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

Pros

  • Легко использовать, импортируешь функцию и используешь

  • Знакомо и узнаваемо

Cons

  • Для связанного процесса приходится передавать данные из одной функции в другую, что ухудшает читабельность

  • Если пытаешься сохранить данные в какой-то переменной вне функций, не будет ясности, что там находится

Глобальные переменные

Во Vue 2 я частенько записывала созданный мной класс, хранящий экземпляр Axios, в глобальные переменные. Это довольно удобно для модуля, который используется повсеместно.

Pros

  • Удобное использование через this

  • Можно в глобальную переменную записать экземпляр класса, что увеличивает ваши возможности

Cons

  • Даже если записать экземпляр класса, то он будет один

  • Непонятно, будут ли данные реактивными, не совсем очевидно

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

Вынести в класс

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

methods: {
  someAlias() {
    Class.someMethodFromClass();
  }
}

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

Поэтому я решила создать это решение сама.

Вводные

Хочется, чтобы можно было создать сервис, который

  1. Создавал экземпляр только по запросу, позволял создать несколько экземпляров, мог удалить нужный экземпляр

  2. Было понятно откуда пришли данные или методы, чтобы при поиске по файлу названия можно было найти источник

  3. Данные должны быть консистентные, при изменении в одном месте, во всех остальных местах они должны стать такими же

  4. Если данные используются в компоненте, то должна быть возможность сделать их реактивными, то есть при отображении в template после изменения компонент должен перерендериться

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

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

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

  8. Должна быть возможность встраивать этот класс в любой компонент без обязательства иметь общего родителя

Спойлер

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

Это 1 часть статьи про реализацию сервиса во Vue 2.

Во 2 части я хочу рассказать о деталях проектирования класса, как работать с разными типами данных, каким образом они встраиваются в компонент и приобретают реактивность, как сделать геттер на свойство/свойства (аналог computed) и передать его в компонент.

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

Опционально

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

Буду смотреть по вашей реакции, будет ли вам интересно про это прочитать.

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

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

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


  1. Mecitan
    22.11.2022 22:09
    +4

    Объясните мне, человеку, который интересуется разработкой сайтов, зачем выносить бизнес-логику на сторону клиента? Для чего? Какой прок от этого?

    Мои взгляды могут показаться консервативными, но всё же такие штуки должны обрабатываться на стороне сервера, а на стороне клиента должен происходить вывод всего этого. При этом сайт должен быть легковесным, интуитивно понятным и доступным. То бишь каждый занят своим дело. Фронт раскрашивает кнопочки и добавляет "реактивность", бэк пишет логику и хранит данные. Всё чётко.


    1. Marcelinka
      22.11.2022 22:17
      +2

      1. На данный момент на стороне бэкенда популярен паттерн REST-api, что говорит о том, что они отдают чистые данные, связанные с конкретными сущностями. Клиент на данный момент не только рисует кнопки и добавляет реактивность, а в том числе сращивает все эти запросы между собой.

      2. Часто данные приходят не в удобном виде, и нам приходится писать адаптеры, добавлять форматирование и так далее.

      3. Часть логики, связанную с рендерингом, считается хорошей практикой выносить клиент.

      Например, последняя моя задача: есть страница для сбора паспортных данных, она включает в себя с 10 разных экранов, которые должны показаться в разных случаях. Условно, сначала мы приходим на первый экран, при успехе попадаем на экран 2, при провале попадаем на экран 3, если у экрана 2 успех, то мы переходим на экран 4 и т.д. Где хранить эту логику? Она очень прямо связана с бизнес-логикой - это флоу клиента, но при этом она связана с отображением экранов на клиенте. Мы храним эту логику на клиенте, потому что нам проще регулировать отображение экранов, чем если бы это делали на сервере.


      1. Mecitan
        23.11.2022 17:11

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

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


        1. Marcelinka
          23.11.2022 17:24

          Не понимаю смысла спора, это современный стандарт, часть бизнес-логики так или иначе переносится на фронт, дабы уменьшить нагрузку на сервер и убрать зависимость сервера от клиента. То есть АПИ строится таким образом, что им не нужно знать о том, как работает клиент, и любой клиент сможет использовать это АПИ.


          1. Mecitan
            23.11.2022 19:07

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


            1. Marcelinka
              23.11.2022 19:16

              С момента, как появилась технология SPA, она впринципе возникла из-за потребности разделить логику между клиентом и сервером. Это не "популярно", это стандарт и считается нормой на сегодняшний день. Пользователям нравится SPA, когда все плавно и без задержек, без выноса части логики на клиент - это невозможно.


              1. Mecitan
                23.11.2022 20:08

                Каким образом нынче сохраняетеся микроразметка? Как решается вопрос с seo?


                1. Marcelinka
                  23.11.2022 21:25

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

                  А вообще я давненько не вижу запроса на какую-то работу с микроразметкой/seo, сейчас часто используют другие каналы продвижения (типа соцсетей или мессенджеров)

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


    1. Ilusha
      23.11.2022 00:44
      +4

      Бэк хранит данные, валидирует их, управляет ими и предоставляет API для доступа для клиентов. Которыми может быть не только люди.

      Фронт - это “человеческий API”. На один и тот же бэк может быть: мобилка, десктоп, браузер-экстеншен, генератор pdf/cvs/etc.

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

      А дальше аппетиты растут: кеши на фронте - чтобы снизить нагрузку на сеть и бэк (и механизмы их инвалидации), использование параметров урла для хранения данных, шеринг каких-нибудь данных на весь апликейшн (ACL, например). Работа со сложными формами: это все вложенные переиспользуемые компоненты, которые валидируются и мапятся на модель, которая, в свою очередь, законтрактована с моделью на бэке.

      На самом деле на фронте бизнес-логики часто не катастрофически много.


      1. Mecitan
        23.11.2022 17:14

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


        1. Ilusha
          24.11.2022 18:27

          Конечно.

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


    1. ILaeeeee
      24.11.2022 08:01

      Сеть является самым тормозным местом. Поэтому, чтобы интерфейс работал максимально быстро, часть вещей переносят на фронт, где это можно и имеет смысл. Я анимирую часто на фронте элементы, и уже интервал 100ms (0.1 s) хорошо заметен: можно с уверенностью сказать стало быстрее или медленнее. Поэтому этот интервал использую как шаг для грубой настройки анимации.


    1. SkiperX
      25.11.2022 11:14

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


  1. ionicman
    22.11.2022 23:31

    Я не очень понял суть задачи — надо расшарить какие-то данные/события между какими-то иерархически несвязанными/связанными компонентами?

    Если да, то максимально корректный в парадигме Vue — это provide/inject.
    А если с этим не заморачиваться, то (имхо) самый удобный — event-bus на руте (либо внешний через mixin/globals). В нем можно как райзить события-данные, так и события-логику, получают их все подписанные на нужные события компоненты, что очень удобно. Расплата за это только одна — отследить типы событий и где они порождаются и где ловятся — сложно. Но, если именование событий стандартизировать, то ищется в проекте элементарно поиском по названию события.

    Не увидел event-bus в статье, кстати — но может быть потому, что неверно задачу понял. Поясните, если не трудно, можно просто простым примером задачи.


    1. Marcelinka
      23.11.2022 00:08

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

      Provide/inject в плане выноса логики страдает проблемой общего родителя (он обязателен) + необходимость встраивать в родителя, что засоряет код ненужными вещами собственно говоря для родителя. + еще несколько минусов, описанных в секции cons, но эти 2 самые весомые для меня.

      Да, я действительно забыла указать EventBus, но он слишком неочевидный, как вы уже сами сказали, отследить вызов события и его listener - не очень удобно.

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

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


      1. ionicman
        23.11.2022 10:41
        +1

        Общий родитель есть всегда - это рут. Чтобы его не загрязнять, можно то что провайдится, затащить внешним файлом js.

        Про отслеживание событий я написал ниже.

        А так вы затащили в проект ещё одну зависимость, которую, во-первых, нужно понимать всем, кто работает в проекте, а во-вторых - поддерживать. Вместо того, чтобы использовать сам vue и его парадигмы, которые понятны всем и доступны из коробки.

        ИМХО, это пятая нога - вы облегчили одно и усложнили другое.

        Но, вообще, чтобы понять что решали, было бы очень неплохо увидеть реальную задачу.


    1. ArutaGerman
      23.11.2022 09:23

      Event-bus - мега не очевидно. provide/inject - тоже, но в меньшей степени.

      В большом проекте надо постараться, чтобы найти родителя в котором сделан provide. Можно ставить коммент, как вариант, у inject, но родителя перенесли/переименовали и финита ля комедия - ищи снова родителя.

      Сам я использовал provide/inject и это удобно, но это был маленький проект и там было всё очевидно. В больших проектах лучше искать более удобные решения, даже если это "велосипеды"


      1. ionicman
        23.11.2022 10:37
        +2

        Чем event-bus меганеочевиден?

        Если договориться о стандарте именования, например, сделать события вида [НазваниеКомпонента]_[Событие]_[ID], где ID - это идентификатор экземпляра компонента, если компонентов такого вида может быть несколько.

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

        Я бы не сказал, что это неочевидней provide/inject, а самое главное - никаких внешних зависимостей и парадигм тащить не надо - работает из коробки.

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


  1. borovinskiy
    23.11.2022 02:26

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


    1. Marcelinka
      23.11.2022 08:12

      Я не знала про этот паттерн, но это по сути то, что я и сделала для себя


  1. zizop
    23.11.2022 07:23
    +1

    Я раньше очень много писал на Symfony, и там просто великолепный Dependency Injection Container. Очень сильно не хватало этого на стороне фронта, на Vue. Использовать контейнеры с декораторами не хотелось ( ну не перевариваю я их).
    И вот недавно я открыл для себя RSDI. Оказалась потрясная штука, сейчас использую вовсю. В потом еще я подключил авто-маппинг сервисов из rsdi с помощью provide/inject, и теперь могу вызвать сервис из любого компонента, где мне это нужно и в тоже самое воемя четко видить все зависимости и в одном месте иметь описание состава контейнера. Мне прям зашло. Если интересно - могу поделиться деталями.
    P.S. rsdi и под vue 2 будет работать.


    1. Marcelinka
      23.11.2022 08:17
      +1

      Напишите статью!) Очень мало способов решения именно на просторах интернета, что и подтолкнуло меня написать статью


  1. BruTO8000
    23.11.2022 08:01

    Я правильно понял, что вы создали свой DI контейнер, когда могли просто использовать inversifyjs?


    1. Marcelinka
      23.11.2022 08:10

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

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


      1. BruTO8000
        25.11.2022 02:54

        Идея мне понравилась. Это как MobX в реакте, посмотрите provide/inject в библиотеке mobx-react. Там не нужно писать так много кода, и запоминать работу фреймворка (вы переопределили сеттер, чтобы vue мог установить proto).

        То есть можно использовать классы, а с помощью mobX они уже реактивны, а если нужен мультитон, то оборачивать сервис в свой декоратор (написать самостоятельно).


        1. Marcelinka
          25.11.2022 09:14

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

          В целом я знакома с mobx, и работала с ним на реакте. Вроде как есть реализация под Vue, надо будет глянуть, как они это сделали.

          Насчёт того, что приходится помнить особенности фреймворка, согласна. У меня была идея сделать декораторы, чтобы объявление свойства в классе могло выглядеть как-то так:

          @primitive
          @readonly
          _prop =  'something'
          
          @object
          @validated
          _obj = { }
          

          Тогда в этих декораторах можно было бы зашить Vue-специфичную логику. Но в нативном JS декораторы ещё не въехали в стандарт, вот в TS - это возможно.


  1. js_n00b
    23.11.2022 09:27

    Почему пропущен вариант использовать Composables?


    1. Marcelinka
      23.11.2022 13:39

      Потому что статья про Vue 2


      1. js_n00b
        23.11.2022 13:53

        В чем проблема использовать Composables во Vue 2 ?


        1. ionicman
          23.11.2022 14:10

          "composable" is a function that leverages Vue's Composition API to encapsulate and reuse stateful logic.

          Из документации по VUE.

          VUE Composition API появилась только во VUE3.


          1. gmtd
            23.11.2022 14:18
            +1

            С 2.7 работает

            Из документации по VUE.


          1. js_n00b
            23.11.2022 14:20
            +1

            Во вторую тоже уже завезли Changelog


            1. ionicman
              23.11.2022 15:25

              Хе, пропустил.
              Но смешивать бы точно не стал.


      1. js_n00b
        23.11.2022 14:29
        +1

        Спасибо за слив кармы за абсолютно оправданное замечание(смотрите ссылку ниже). Парни и девчонки, которые знают, что я был прав, пожалуйста, накидайте плюсов в карму! Верните мне веру в Хабр, что здесь еще можно нормально общаться хотя бы на технические темы!


        1. Marcelinka
          23.11.2022 15:23

          Статья написана про старые проекты на Vue 2, написанные на Options Api, которые не используют Composition Api. Там нет такой опции.


          1. js_n00b
            23.11.2022 15:50

            Начиная с версии 2.7 во Vue 2 появилась опция setup. В доказательство этому, выше я уже скидывал ссылку на Changelog. Даже если Вам не нравится это вариант, мне было бы интересно прочитать сравнение с плюсами и минусами. Только поэтому я спрашиваю.


            1. Marcelinka
              23.11.2022 16:10

              Я не говорила, что мне не нравится этот вариант, мне впринципе Vue 3 больше нравится, и там я использовала только Composition Api.

              Просто тема статьи другая, я это наверное явно не обозначила, но опция Composable на некоторых проектах не стоит, так как весь проект на Options Api, и composable не совсем вписывается.

              Для 3 версии Vue я потом хотела сделать решение, где как раз таки класс встраивается в компонент через composable.


  1. gmtd
    23.11.2022 09:56
    +2

    Смешались в кучу кони, люди стейты, функции, миксины...

    Автор понимает, что такое сервис? Верней, как автор понимает что такое сервис? Судя по тексту, Math.round() для нее сервис. И весь Vuex стор тоже.

    О каких сервисах речь? Stateless, stateful? Откуда к нему нужен доступ? Какие данные передаются? Какие задачи решаются? Нужна ли реактивность? О чём статья, вообще?

    "Как можно инкапсулировать логику", "Сервисная архитектура во Vue 2" - статья точно не об этом.


    1. Marcelinka
      23.11.2022 13:46

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

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


      1. gmtd
        23.11.2022 14:28
        +1

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


        1. Kirill_94
          23.11.2022 17:38
          -2

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