Что такое сервис в программировании
Перейти к содержимому

Что такое сервис в программировании

  • автор:

Учебники. Программирование для начинающих.

Programm.ws — это сайт, на котором вы можете почитать литературу по языкам программирования , а так-же посмотреть примеры работающих программ на С++, ассемблере, паскале и много другого..

Программирование — в обычном понимании, это процесс создания компьютерных программ.
В узком смысле (так называемое кодирование) под программированием понимается написание инструкций — программ — на конкретном языке программирования (часто по уже имеющемуся алгоритму — плану, методу решения поставленной задачи). Соответственно, люди, которые этим занимаются, называются программистами (на профессиональном жаргоне — кодерами), а те, кто разрабатывает алгоритмы — алгоритмистами, специалистами предметной области, математиками.
В более широком смысле под программированием понимают весь спектр деятельности, связанный с созданием и поддержанием в рабочем состоянии программ — программного обеспечения ЭВМ. Более точен современный термин — «программная инженерия» (также иначе «инженерия ПО»). Сюда входят анализ и постановка задачи, проектирование программы, построение алгоритмов, разработка структур данных, написание текстов программ, отладка и тестирование программы (испытания программы), документирование, настройка (конфигурирование), доработка и сопровождение.

Программирование на Ассемблере

Глава 9 ROM BIOS

Системный сервис

Два драйвера в BIOS дают самый простой системный сервис. Они предназначены для определения объема памяти ЭВМ и конфигурации внешних устройств.

Программа определения объема памяти не имеет параметров. BIOS возвращает в регистре AX объем памяти системы, измеренный в килобайтах (1024 байт). Если система имеет память 64K байт, в регистре AX возвратится число 64. Любая программа, использующая всю память системы, должна запрашивать у BIOS объем памяти, чтобы определить, где находится ее конец. Программа могла бы определить объем памяти, записав и прочитав подряд ячейки памяти, сравнивая записанное и прочитанное значение. Но, как покажет пример в следующей главе, важно писать все прикладные программы так, чтобы они использовали для определения объема памяти подпрограмму, возвращающую этот объем. Изменяя значение верхнего предела памяти, можно зарезервировать участок в верхних адресах памяти. После того, как программа изменит значение общего объема памяти, корректно написанная прикладная программа не нарушит границу памяти.

Программа проверки конфигурации внешних устройств не имеет входных параметров. Эта программа возвращает в регистре AX 16-битовый код, показывающий, какие устройства подключены к конкретной системе. В прологе распечатки этой программы в техническом руководстве по IBM PC указывается, что означает каждый бит. Эта функция BIOS — простейший способ определения, существует ли конкретное устройство в системе, или нет.

Последняя системная сервисная программа проверяет время суток. У этой программы есть две функции: чтение времени и установка времени. Время измеряется в квантах таймера, начиная с того момента, когда машина включается, и отсчитывается от полуночи. BIOS не преобразует это значение в часы, минуты и секунды. Но в листинге BIOS показаны нужные для преобразования константы. Чтобы определить время в часах, разделите 24-битовое значение таймера на 65543, число квантов таймера в часе. Чтобы определить минуты, разделите остаток от предыдущего деления на 1092, количество квантов в минуте, и так далее.

Если точность преобразования значения времени не очень критична для вас, можно воспользоваться более простым методом. Так как количество квантов, соответствующее 24 часам не помещается в одно слово, значение таймера представляется трехбайтовым целым числом. Значение старшего байта отличается не более, чем на 1% от времени в часах. Младшее слово можно разделить на 1092, чтобы определить число минут, а деление остатка на 18 дает число секунд.

Функция времени дня использует аппаратное прерывание, прерывание по кванту таймера. Это прерывание имеет уровень 0 в контроллере прерываний 8259, и имеет вектор прерывания 8 в микропроцессоре 8088. Эта программа получает управление каждые 55 миллисекунд. Основное назначение этой программы — увеличение счетчика квантов таймера программы времени дня. Если программа выключит прерывания на значительный промежуток времени, то весьма вероятно, что время суток перестанет быть правильным.

Прерывание от таймера используется также программой обслуживания дисковода. Двигатели дисковода включены не постоянно; BIOS включает двигатели только на время доступа к дискете. Но BIOS не выключает двигатель сразу же после выполнения операции. Есть некоторый интервал времени между включением двигателя и тем моментом, когда он разгонится и будет вращаться достаточно быстро, для того, чтобы можно было читать данные. Если программа обращается к дисководу почти сразу после предыдущего обращения, лучше оставить двигатель включенным, а не выключать и включать его. Программа обработки аппаратного прерывания от таймера учитывает это. Обработчик дискового прерывания загружает число в переменную, которая называется MOTOR_COUNT, когда завершается операция обмена с дискетой. Прерывание от таймера уменьшает значение этого счетчика. Когда значение переменной MOTOR_COUNT достигает 0, выключается двигатель дисковода. Программа обслуживания дисковода проверяет этот счетчик, перед обращением к дискете. Если двигатель еще не включен, нужна задержка, пока двигатель не разгонится. Обычно двигатель дисковода продолжает работать две секунды после завершения предыдущей операции. Это время — один из параметров дисковода, и вы можете изменить его значение. Выбор этого значения поддерживает баланс между повышением производительности и снижением износа поверхности дискеты.

Все эти три сервисные программы BIOS передают числа из ячеек памяти в вызывающую программу. Можно избежать использования BIOS путем непосредственного чтения этих ячеек. Но зачастую проще вызвать BIOS, чем организовывать адресацию к сегменту DATA используемому в BIOS. С «наивной» точки зрения, проще использовать программу BIOS.

Сервисы

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

Все сервисы наследуются от класса Service и проходят следующие этапы жизненного цикла:

  • Метод onCreate() : вызывается при создании сервиса
  • Метод onStartCommand() : вызывается при получении сервисом команды, отправленной с помощью метода startService()
  • Метод onBind() : вызывается при закреплении клиента за сервисом с помощью метода bindService()
  • Метод onDestroy() : вызывается при завершении работы сервиса

Создадим простейшее приложение с сервисом. Наш сервис будет воспроизводить музыкальный файл. И вначале добавим в проект в каталог res папку raw . Для этого нажмем правой кнопкой мыши на каталог res и в контекстном меню выберем пункт New -> Android Resource Directory .

Добавление папки raw для сервисов в Android Studio и Java

Далее укажем в качестве типа папки — raw :

Добавление папки ресурсов raw для сервисов в Android Studio и Java

И поместим в эту папку ( res/raw ) какой-нибудь mp3-файл.

Затем добавим новый класс сервиса. Назовем его MediaService . В итоге получится следующий проект:

Добавление сервисов в Android Studio и Java

Для воспроизведения аудио-файла определим в классе MediaService следующий код:

package com.example.soundserviceapp; import android.app.Service; import android.content.Intent; import android.media.MediaPlayer; import android.os.IBinder; public class MediaService extends Service < MediaPlayer ambientMediaPlayer; @Override public IBinder onBind(Intent intent) < throw new UnsupportedOperationException("Not yet implemented"); >@Override public void onCreate() < ambientMediaPlayer=MediaPlayer.create(this, R.raw.music); ambientMediaPlayer.setLooping(true); >@Override public int onStartCommand(Intent intent, int flags, int startId) < ambientMediaPlayer.start(); return START_STICKY; >@Override public void onDestroy() < ambientMediaPlayer.stop(); >>

Для воспроизведения музыкального файла сервис будет использовать компонент MediaPlayer .

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

В методе onCreate() инициализируется медиа-проигрыватель с помощью музыкального ресурса, который добавлен в папку res/raw.

В методе onStartCommand() начинается воспроизведение.

Метод onStartCommand() может возвращать одно из значений, которое предполагает различное поведение в случае, если процесс сервиса был неожиданно завершен системой:

  • START_STICKY : в этом случае сервис снова возвращается в запущенное состояние, как будто если бы снова был бы вызван метод onStartCommand() без передачи в этот метод объекта Intent
  • START_REDELIVER_INTENT : в этом случае сервис снова возвращается в запущенное состояние, как будто если бы снова был бы вызван метод onStartCommand() с передачей в этот метод объекта Intent
  • START_NOT_STICKY : сервис остается в остановленном положении

Метод onDestroy() завершает воспроизведение.

Чтобы управлять сервисом, изменим activity. Сначала добавим в файл activity_main.xml пару кнопок для управления сервисом:

И изменим код MainActivity :

package com.example.soundserviceapp; import androidx.appcompat.app.AppCompatActivity; import android.content.Intent; import android.os.Bundle; import android.view.View; public class MainActivity extends AppCompatActivity < @Override protected void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); >public void click(View v) < Intent i=new Intent(this, MediaService.class); if (v.getId()==R.id.start) < startService(i); >else < stopService(i); >> >

Для запуска сервиса используется объект Intent:

Intent i=new Intent(this, MediaService.class);

Для запуска сервиса в классе Activity определен метод startService() , в который передается объект Intent. Этот метод будет посылать команду сервису и вызывать его метод onStartCommand() , а также указывать системе, что сервис должен продолжать работать до тех пор, пока не будет вызван метод stopService().

Метод stopService() также определен к классе Activity и принимает объект Intent. Он останавливает работу сервиса, вызывая его метод onDestroy()

И в конце нам надо зарегистрировать сервис в файле манифеста:

Регистрация сервиса производится в узле application с помощью добавления элемента . В нем определяется атрибут android:name , который хранит название класса сервиса. И кроме того может принимать еще ряд атрибутов:

  • android:enabled : если имеет значение «true», то сервис может ли создаваться системой. Значение по умолчанию — «true».
  • android:exported : указывает, могут ли компоненты других приложений обращаться к сервису. Если имеет значение «true», то могут, если имеет значение «false», то нет.
  • android:icon : значок сервиса, представляет собой ссылку на ресурс drawable
  • android:isolatedProcess : если имеет значение true, то сервис может быть запущен как специальный процесс, изолированный от остальной системы.
  • android:label : название сервиса, которое отображается пользователю
  • android:permission : набор разрешений, которые должно применять приложение для запуска сервиса
  • android:process : название процесса, в котором запущен сервис. Как правило, имеет то же название, что и пакет приложения.

Запустим приложение и нажмем на кнопку запуска сервиса:

Сервисы startService в Android и Java

После этого начнется воспроизведение добавленной нами в приложение мелодии.

СЕРВИСНОЕ ПРОГРАММИРОВАНИЕ

Эта парадигма программирования появилась как следствие рассмотрения программных компонентов, которые могут использоваться в качестве сервиса. Для них определены интерфейсы взаимодействия с разными программами и распределенными системами (CORBA, DCOM и EJB, MS.Net, IBM и тому подобное) и с веб-сервисами Интернета. В настоящее время действуют сервисноориентированная архитектура SOA (Service-Oriented Architecture), средства их поддержки (XML, SOAP, WSDL и др.) и механизмы взаимодействия обычных сервисов распределенных приложений и веб-сервисов Интернет [36-38].

Сервис. Базовые понятия

Веб-ссрвис — программа, которая идентифицируется строкой URI, свойства и методы которой описаны с помощью специального языка WSDL. Доступ к ресурсам такой системы осуществляется через протокол SOAP, который представляется XML-заиросами, которые передаются через HTTP Интернет-протокола.

Веб-сервисы близкие классам объектно-ориентированных ЯП (JAVA ЕЕ). Ключевые понятие веб-сервиса — это сообщение из одной или нескольких переменных. Методы классов задаются операциями с входным и выходным значениями сообщений. После вызова операции переменной входного сообщения протокола SOAP, интерпретируются как параметры соответствующего метода класса, который лежит в основе сервиса [96].

Сервис определяется, с одной стороны, как открытый компонент, который может быть элементом быстрой композиции в прикладные приложения. С другой стороны, сервис предлагается как готовый ресурс, который реализует некоторые дополнительные возможности, необходимые всем разнородным программам для технической поддержки, нужной потенциальным пользователям. Как правило, описания сервисов содержат в себе информацию об их возможностях, интерфейсах, поведении и характеристиках. Благодаря такому описанию пользователь может найти сервисы, выбрать нужные и интегрировать их в композиционную структуру, как готовый ресурс (http://www.w3.org/Submission/wsml).

Рассматривается три вида сервисов:

  • 1) общие системные сервисы, которые есть в каждой общесистемной среде для поддержки процессов проектирования и реализации РПС на основе сформулированных моделей ПС, ПС и РПС;
  • 2) объекгные сервисы, которые поддерживают объекты и классы, операции ЖЦ, услуги необходимы для разработки РПС в объектно-ориентированной среде;
  • 3) веб-сервисы, которые базируются на информационных ресурсах Интернет и обеспечивают создание элементов РПС путем композиции или интеграции КПИ и сервисов, способных к функционированию в вебе Всемерной паутины.

Системные сервисы создают некоторое множество сервисов CServ = , которое необходимо для организации построения и функционирования функций компонентов и сервисов РПС, а также для управления их конфигурационными структурами. В частности, набор сервисов включает в себя сервис:

  • 1. Наименование Naming, которое обеспечивает возможность поиска компонентов в распределенной среде с учетом пространства имен.
  • 2. Связи Binding предназначены для определения (связи) соответствия имя- объект и применяемая к выбранным компонентам.
  • 3. Транзакций Transaction, который обеспечивает организацию и управление функционированием совокупности компонентов и функций сервисов.
  • 4. Сообщения Messaging, необходимые для организации общения между компонентами, являются составным элементом в модели асинхронных транзакций.

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

  • 1) поиск компонентов;
  • 2) доступ к их ресурсам;
  • 3) организация обмена информацией между компонентами;
  • 4) динамическое управление функционированием, обусловленным совокупностью КПИ в РИС.

Модель сервисов РПС базируется на унификации и совместимости, что позволяет рассматривать РПС как набор сервисов, их функциональность и взаимодействие.

Унификация сервисов достигается путем:

  • 1) типизации функциональности сервисов и других характеристик;
  • 2) применения унифицированных языков для описания сервисов и их взаимодействия;
  • 3) использование стандартных базовых технологий.

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

Средством описания механизма взаимодействия с сервисами является SOAP, а для описания функциональности сервисов — язык WSDL. Описание функциональности сервисов выполняется унифицированными языками XML, WSDL; описание структуры и семантики данных выполняется языком RDF; описание процессов представления и обработки сервисов языком BPMN, а взаимодействие с сервисами и поиска необходимых сервисов — SOAP.

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

Модель сервиса обеспечивает:

  • 1) динамическое расширение функциональности системы за счет поиска и привлечения в сферу обработки новых сервисов;
  • 2) повышение масштаба и улучшение возможностей коммуникации между отдельными элементами системы за счет стандартного механизма подключения сервисов через их интерфейсы;
  • 3) повышение языкового уровня коммуникации системы с конечными пользователями.

Принципы разработки систем из готовых программных и информационных ресурсов (компонентов, сервисов, интерфейсов, данных, артефактов и т. п.) такие:

  • 1) композиционность сложных систем типа РПС из компонентов, интерфейсов и сервисов с их свойствами, характеристиками и механизмами агрегации в более сложные структуры и правилами взаимодействия в интегрированных средах;
  • 2) компонентность инженерии (CBSE), как деятельности создания РПС из готовых «деталей», базированная на реально существующих положениях инженерии продуктов, а именно, стандартизирован ЖЦ гребований, эксплуатации и уничтожения КПИ или СПС с использованием систем классификации и каталогизации КПИ, средств унификации, стандартизации описания КИИ и интеграции их в ПС и СПС;
  • 3) интероперабельность КГ1 и элементов ПС, которая базирована на интерфейсах и правилах взаимодействия компонентов между собой для обеспечения интеграции и функционирования в разных гетерогенных средах;
  • 4) вариантность как способность КПИ и компонентных ПС к изменениям путем уничтожения некоторых функциональных, незавершенных или добавления новых функциональных КПИ в конфигурационную структуру СПС, или ПС и т. п.

Сервис Интернета — это ресурс, который реализует некоторые функции (в том числе бизнес-функции), является КПИ и содержит в себе технологически независимый интерфейс с другими ресурсами. Например, сервисы транзакций, именования, безопасности в модели CORBA. Они образуют службу сервисов для создания ПС.

Основная форма реализации сервисов — это веб-сервисы, которые сохраняются и идентифицируются URL-адресами и взаимодействуют между собой посредством сети Интернета, например, RPC (Remote Procedure Call). Стремительное использование Интернета привело к тому, что традиционное интегрированное предприятие прошлых поколений все чаще замещается сетью бизнеса, которые совместно выполняют определенные функции при том, что и собственность, и менеджмент распределены между партнерами. Именно информационные потребности распределенных бизнесов вызвали к жизни веб-сервисы как адекватную форму компонентов типа КПИ.

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

Основные средства описания и разработки новых систем средствами вебсервисов:

  • 1) язык XML для описания и построения SOA-архитектуры;
  • 2) язык WSDL (Web Services Description Language) для описания вебсервисов и их интерфейсов в XML, а также типов данных и сообщений, моделей взаимодействия и протоколов связи сервисов между собой;
  • 3) SOAP (Simple Object Access Protocol) для определения форматов запросов к веб-сервисам;
  • 4) SCA (Servise-Component Architecture) для создания более сложной системы на основе компонентов и сервисов;
  • 5) UDDI (Universal Description, Discovery and Integration) для универсального описания, выявления и интеграции сервисов, обеспечения их хранения, упорядочения деловой сервисной информации в специальном реестре с указателями на конкретные интерфейсы веб-сервисов.

К средствам моделирования сложных систем и СПС относится система IBM ® WebSphere ® Integration Developer. Она предоставляет сервис-ориентированную архитектуру SOA (Servise Oriented Architecture), компонентну архитектуру сервисов SCA (Servise-Component Architecture) на основе вариантов использования UML. Эта система предлагает интеграцию сервисов SCA через модель интерфейсов JAVA, которая задается в WSDL, а реализация — классы JAVA ™.

Когда лучше всего использовать классы «Сервисы», а когда логику лучше помещать в сам класс?

Как правило, классы сервисы- это таке классы, которые не имеют состояния. Т.е передаешь им что-то, а в ответ они тебе выплевывают чего-то. Так вот, я часто вижу то, что какие-то методы можно было поместить в класс рядом с данными, а не выносить это в отдельный сервис. Так вот, когда это оправдано? Например, сейчас я наблюдаю сервис, который возвращает некий сложный объект. Что бы получить какие-то интересующие себя данные, без ручных итераций по внутренним коллекциям, я должен передать конкрутному методу сервиса этот объект и на это он вернет мне результат. Хотя. по моему, что мешает этот метод дать конкретному экземпляру? Единственный, наверное, + — это отделить данные от реализации и как следствие, можно не возиться с наследованием.

Отслеживать
задан 30 апр 2020 в 9:30
24.9k 13 13 золотых знаков 67 67 серебряных знаков 164 164 бронзовых знака
В тегах стоит любой-язык , но такое ощущение, что это вопрос про «безнес-логику» на java / c#.
12 мая 2020 в 12:40

7 ответов 7

Сортировка: Сброс на вариант по умолчанию

Service – это Java класс, который предоставляет с себя основную (Бизнес-Логику). В основном сервис использует готовые DAO/Repositories или же другие сервисы, для того чтобы предоставить конечные данные для пользовательского интерфейса.

Как гласит Принцип единственной ответственности (Single Responsibility Principle):

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

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

Отслеживать
ответ дан 6 мая 2020 в 17:32
1,002 1 1 золотой знак 8 8 серебряных знаков 24 24 бронзовых знака

Такой подход используется в принципе единой ответственности. Например, у нас есть объект письма Message , и мы хотим его отправить. Можно реализовать метод send() в самом письме, а можно написать сервис MailService с методом send(Message msg) . Первый случай с точки зрения SOLID будет не верным, так как письмо не может отправить само себя, для этого есть служба (мы просим службу отправить письмо, а служба уже займется доставкой согласно каким-то своим внутренним правилам).

Отслеживать
ответ дан 6 мая 2020 в 13:38
Ivan Dudarev Ivan Dudarev
1,456 1 1 золотой знак 8 8 серебряных знаков 18 18 бронзовых знаков

Здесь очень много примеров, но я постараюсь разобрать некоторые из них:

Интерфейсы (и классы их реализующие)

Да-да-да, я знаю, что «интерфейс вообще» это не «класс вообще» (привет С++), но в чём разница м-ду абстрактным классом и интерфейсом? Абстрактный класс может содержать поля, т. е. состояние, а интерфейс (по крайней мере «чистый») – только поведение (его декларацию, которую потом реализует класс. реализатор?).

public interface ISomeInterface < int someField; // compile error void DoSmth(); // no error >

XXX-Helpers/Services

Классы вида SomeHelpers или SomeServices . Тут ничего лишнего:

public static class SomeServices < public static void Check(this SomeEnum @enum) < const SomeEnum maxEnum = SomeEnum.SomeMaxValue; if (@enum < 0 || @enum >maxEnum) throw /*. */; > > 

Разве что добавлю по поводу разницы м-ду их именами, как её вижу я: SomeHelpers — internal class , SomeServices — public class . Опять же, могут быть исключения, но я их встречал несколько раз, например:

public static class DoubleHelpers < public static int Compare(double a, double b); public static bool IsZero(double value); // . >

ISomeFactory

public interface ISomeFactory < ISomeClass CreateSomeClass(/*some args*/); >

ISomeProvider

public interface ISomeProvider < ISomeClass GetObject(/*some args*/); // or ISomeClass ProvideObject(/*some args*/); >

Тут от экземпляра класса SomeObject . Здесь ISomeProvider может быть IServiceProvider , а ISomeObject – ISomeService . Теперь провайдер может возвращать не только объекты, но и сервисы. Ну или даже так:

public interface IFooProvider < IBarProvider GetProvider(); >public interface IBarProvider < IBazProvier GetProvider(); >// . // . 

Формальные «сервисы»

Если мы хотим назвать класс, например, как «служба доставки», то мы его назовём как DeliveryService . Здесь «сервис» формальный – это нужно иметь ввиду.

Сами по себе сервисы «бесплодны» и могут нести роль:

  • Реализуемого контейнера деклараций методов
  • Не наследуемого контейнера реализаций методов
  • Получателя других объектов (или даже сервисов или других провайдеров)

Например, сейчас я наблюдаю сервис, который возвращает некий сложный объект.

Вы наблюдаете сервис, реализующий интерфейс провайдера.

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

Вообще, сервисы целенаправленно и зачастую используются в данных случаях (первое, что мне в голову пришло). Нет смысла просто так брать и создавать класс-сервис, чтоб «полей не было». Например, класс RandomHelpers :

public static class RandomHelpers

Здесь статический для потоков random — отличный инструмент рефакторинга, позволяющий 1 строчкой не писать код с синхронизацией и, тем самым, оптимизировать run-time, хотя мы и немного (я б сказал вообще не) просели в памяти. И вроде статический класс-сервис, но со состоянием. Серьёзно? Эти (в худшем реальном случае, наверно, за историю) съедят 100 байт, не больше. Не нужно экономить, если не просят. Так же стоит сказать, что сервис зачастую – это просто классификация (мол, все классы «без полей» — сервисы).

 +-------------------+---------------+ | Абстракция | Реализация | +----------------+-------------------+---------------+ | Есть состояние | Абстрактный класс | Обычный класс | +----------------+-------------------+---------------+ | Нет состояния | Интерфейс | Класс-сервис | +----------------+-------------------+---------------+ 

Отслеживать
ответ дан 6 мая 2020 в 18:50
2,730 1 1 золотой знак 12 12 серебряных знаков 30 30 бронзовых знаков

Понятие сервис несколько противоречиво в мире ООП, поэтому с ним и возникают такие сложности.

В учебнике C++ Бьярна Страуструпа написано, что ООП держится на трёх китах, один из которых это инкапсуляция. Данные и методы надо держать вместе.

Общее правило такого: если методу нужны данные из класса, поместите этот метод прямо в класс.

И этот подход работает хорошо до тех пор, пока методу нужны данные одного класса. А если двух?

На этот вопрос нет общего ответа. Иногда новый код размещают в первом классе, иногда во втором, а иногда — в новом третьем классе.

При принятии решения играют роль вот какие факторы:

  1. Согласованность. Удобно, если в каждом случае вы принимаете похожие архитектурные решения. Программистам, которые работают над кодом, проще будет его понимать, если в коде прослеживаются закономерности. Если вы решите размещать код в каком-то из двух (трёх, пяти) классов, как это повлияет на остальной код. Не придётся ли вам в других местах вносить правки, чтобы решение оставалось согласованным.
  2. Краткость. У начинающих архитекторов есть проблема с простыми решениями. Они могут придумать что-то такое, что заставит всю команду писать десятки «лишних» строк кода. Иногда эту штуку называют monkey code, иногда boilerplate. Как его не называй, но это хороший индикатор, что решение не самое хорошее.
  3. Солидность. Обычно стоит прогнать решение на соответствие принципам SOLID. Метод может быть лишним в классе и нарушать Single Responsibility. Или он потребует постоянного дописывания уже готового кода, что нарушит принцип Open/Closed.

В общем и целом, когда стоит создавать службу и выносить методы туда? Когда речь идёт о процедуре или бизнес-процессе. Скажем, заказ проходит по стадиям (создан, сформирован, оплачен, собран, отправлен, доставлен). Конечно, у заказа есть его состояние, которое должно быть инкапсулировано внутри класса Заказ .

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

Про вас случай трудно сказать, не видя кода, и не зная архитектурных ценностей, которые положены в основу проекта. Прежде, чем переносить метод в класс, я бы посмотрел на размер класса. В языках типа Java/C#/C++ размер в 300-400 строк, это мой личный максимум. Ничем не подтвержу и случаи разные бывают, тут всё субъективно.

Второе, я бы посмотрел на другие классы-сущности, которые нужны в работе метода (в параметрах, в коде, в выходном значении). Нормально, если там либо примитивные типы, либо классы, которые называют объекты-значения. Точки из координат x и y , цвета из компонентов red , green , blue . Если же там полноценные сущности, то, пожалуй, стоит оставить метод в службе.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *