stringtranslate.com

Архитектура брокера общих объектных запросов

Common Object Request Broker Architecture ( CORBA ) — это стандарт, определенный Object Management Group (OMG), разработанный для упрощения взаимодействия систем, развернутых на различных платформах . CORBA обеспечивает совместную работу систем на разных операционных системах, языках программирования и вычислительном оборудовании. CORBA использует объектно-ориентированную модель, хотя системы, использующие CORBA, не обязательно должны быть объектно-ориентированными. CORBA — это пример парадигмы распределенных объектов .

Несмотря на то, что CORBA была популярна в середине и конце 1990-х годов, ее сложность, непоследовательность и высокие затраты на лицензирование низвели ее до уровня узкоспециализированной технологии. [1]

Обзор

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

CORBA использует язык определения интерфейсов (IDL) для указания интерфейсов, которые объекты представляют внешнему миру. Затем CORBA определяет отображение из IDL в определенный язык реализации, такой как C++ или Java . Стандартные отображения существуют для Ada , C , C++ , C++11 , COBOL , Java , Lisp , PL/I , Object Pascal , Python , Ruby и Smalltalk . Нестандартные отображения существуют для C# , Erlang , Perl , Tcl и Visual Basic , реализованные брокерами объектных запросов (ORB), написанными для этих языков. Версии IDL значительно изменились, и некоторые прагмы были заменены аннотациями.

Спецификация CORBA предписывает наличие ORB, через который приложение будет взаимодействовать с другими объектами. Вот как это реализовано на практике:

  1. Приложение инициализирует ORB и обращается к внутреннему адаптеру объектов , который поддерживает такие вещи, как подсчет ссылок , политики создания экземпляров объектов (и ссылок) и политики жизненного цикла объектов.
  2. Object Adapter используется для регистрации экземпляров сгенерированных классов кода . Сгенерированные классы кода являются результатом компиляции пользовательского кода IDL, который транслирует определение интерфейса высокого уровня в специфичную для ОС и языка базу классов для использования пользовательским приложением. Этот шаг необходим для обеспечения семантики CORBA и предоставления чистого пользовательского процесса для взаимодействия с инфраструктурой CORBA.

Некоторые отображения IDL сложнее в использовании, чем другие. Например, из-за природы Java отображение IDL-Java довольно простое и делает использование CORBA очень простым в приложении Java. Это также верно для отображения IDL в Python. Отображение C++ требует от программиста изучения типов данных, которые предшествуют стандартной библиотеке шаблонов C++ (STL). Напротив, отображение C++11 проще в использовании, но требует интенсивного использования STL. Поскольку язык C не является объектно-ориентированным, отображение IDL в C требует от программиста C ручной эмуляции объектно-ориентированных функций.

Чтобы построить систему, которая использует или реализует распределенный объектный интерфейс на основе CORBA, разработчик должен либо получить, либо написать код IDL, который определяет объектно-ориентированный интерфейс для логики, которую система будет использовать или реализовывать. Обычно реализация ORB включает инструмент, называемый компилятором IDL, который транслирует интерфейс IDL на целевой язык для использования в этой части системы. Затем традиционный компилятор компилирует сгенерированный код для создания файлов связываемых объектов для использования в приложении. Эта диаграмма иллюстрирует, как сгенерированный код используется в инфраструктуре CORBA:

Иллюстрация автоматической генерации кода инфраструктуры из интерфейса, определенного с использованием CORBA IDL
Иллюстрация автоматической генерации кода инфраструктуры из интерфейса, определенного с использованием CORBA IDL

На этом рисунке показана высокоуровневая парадигма для удаленного межпроцессного взаимодействия с использованием CORBA. Спецификация CORBA далее рассматривает типизацию данных, исключения, сетевые протоколы, тайм-ауты связи и т. д. Например: Обычно на стороне сервера есть Portable Object Adapter (POA), который перенаправляет вызовы либо локальным сервантам , либо (для балансировки нагрузки) на другие серверы. Спецификация CORBA (и, следовательно, этот рисунок) оставляет различные аспекты распределенной системы приложению для определения, включая время жизни объектов (хотя семантика подсчета ссылок доступна приложениям), избыточность/отказоустойчивость, управление памятью, динамическую балансировку нагрузки и ориентированные на приложения модели, такие как разделение между семантикой отображения/данных/управления (например, см. Модель–представление–контроллер ) и т. д.

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

История версий

В этой таблице представлена ​​история версий стандарта CORBA. [2] [3] [4]

Обратите внимание, что изменения IDL коснулись замены некоторых прагм на аннотации (например, @unit, @topic).

Слуги

Слуга — это цель вызова, содержащая методы для обработки удаленных вызовов методов . В новых версиях CORBA удаленный объект (на стороне сервера) разделен на объект (который открыт для удаленных вызовов) и слугу (которому первая часть пересылает вызовы методов) . Это может быть один слуга на удаленный объект , или один и тот же слуга может поддерживать несколько (возможно, все) объектов, связанных с данным Portable Object Adapter . Слуга для каждого объекта может быть установлен или найден «один раз и навсегда» (активация слуги) или динамически выбираться каждый раз, когда вызывается метод на этом объекте (локация слуги). Как локатор слуги, так и активатор слуги могут перенаправлять вызовы на другой сервер. В целом эта система предоставляет очень мощные средства для балансировки нагрузки, распределяя запросы между несколькими машинами. В объектно-ориентированных языках как удаленный объект , так и его слуга являются объектами с точки зрения объектно-ориентированного программирования.

Инкарнация — это действие по связыванию серванта с объектом CORBA, чтобы он мог обслуживать запросы. Инкарнация предоставляет конкретную форму серванта для виртуального объекта CORBA. Активация и деактивация относятся только к объектам CORBA, в то время как термины инкарнация и этериализация относятся к сервантам. Однако время жизни объектов и сервантов независимы. Вы всегда воплощаете серванта перед вызовом activate_object(), но возможно и обратное: create_reference() активирует объект без воплощения серванта, а воплощение серванта позже выполняется по требованию с помощью диспетчера сервантов.

ThePortable Object Adapter (POA) — это объект CORBA, отвечающий за разделение обработчика удаленных вызовов на стороне сервера на удаленныйобъекти егоserve. Объект предоставляется для удаленных вызовов, в то время как serve содержит методы, которые фактически обрабатывают запросы. serve для каждого объекта может быть выбран либо статически (один раз), либо динамически (для каждого удаленного вызова), в обоих случаях позволяя переадресацию вызовов на другой сервер.

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

Функции

Ниже описаны некоторые из наиболее важных способов использования CORBA для облегчения связи между распределенными объектами.

Объекты по ссылке

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

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

Данные по значению

Язык определения интерфейса CORBA обеспечивает определение межобъектной коммуникации, нейтральное по отношению к языку и ОС. Объекты CORBA передаются по ссылке, а данные (целые числа, двойные числа, структуры, перечисления и т. д.) передаются по значению. Сочетание Objects-by-reference и data-by-value обеспечивает средства для обеспечения отличной типизации данных при компиляции клиентов и серверов, сохраняя при этом гибкость, присущую проблемному пространству CORBA.

Объекты по стоимости (OBV)

Помимо удаленных объектов, CORBA и RMI-IIOP определяют концепцию OBV и Valuetypes. Код внутри методов объектов Valuetypes по умолчанию выполняется локально. Если OBV получен с удаленной стороны, необходимый код должен быть либо априори известен обеим сторонам, либо динамически загружен от отправителя. Чтобы это стало возможным, запись, определяющая OBV, содержит Code Base, которая представляет собой разделенный пробелами список URL-адресов, откуда этот код должен быть загружен. OBV также может иметь удаленные методы.

Модель компонентов CORBA (CCM)

CORBA Component Model (CCM) — это дополнение к семейству определений CORBA. [5] Она была введена в CORBA 3 и описывает стандартную структуру приложений для компонентов CORBA. Хотя она не зависит от «зависимых от языка Enterprise Java Beans (EJB)», она является более общей формой EJB, предоставляя четыре типа компонентов вместо двух, которые определяет EJB. Она предоставляет абстракцию сущностей, которые могут предоставлять и принимать службы через четко определенные именованные интерфейсы, называемые портами .

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

Переносные перехватчики

Портативные перехватчики — это «крючки», используемые CORBA и RMI-IIOP для посредничества в важнейших функциях системы CORBA. Стандарт CORBA определяет следующие типы перехватчиков:

  1. Перехватчики IOR опосредуют создание новых ссылок на удаленные объекты, представленные текущим сервером.
  2. Клиентские перехватчики обычно опосредуют удаленные вызовы методов на стороне клиента (вызывающей стороны). Если объект Servant существует на том же сервере, где вызывается метод, они также опосредуют локальные вызовы.
  3. Серверные перехватчики выполняют функцию посредника при обработке вызовов удаленных методов на стороне сервера (обработчика).

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

Общий протокол InterORB (GIOP)

GIOP — это абстрактный протокол, посредством которого общаются брокеры запросов объектов (ORB). Стандарты, связанные с протоколом , поддерживаются Object Management Group (OMG). Архитектура GIOP предоставляет несколько конкретных протоколов, включая:

  1. Протокол Internet InterORB (IIOP) — протокол Internet Inter-Orb представляет собой реализацию GIOP для использования через Интернет и обеспечивает сопоставление сообщений GIOP и уровня TCP/IP .
  2. Протокол SSL InterORB (SSLIOP) – SSLIOP – это IIOP поверх SSL , обеспечивающий шифрование и аутентификацию .
  3. Протокол HyperText InterORB (HTIOP) – HTIOP представляет собой IIOP поверх HTTP , обеспечивающий прозрачный обход прокси-сервера.
  4. Сжатый IOP (ZIOP) – сжатая версия GIOP, которая снижает использование полосы пропускания.

VMCID (дополнительный кодовый идентификатор поставщика)

Каждое стандартное исключение CORBA включает в себя младший код для обозначения подкатегории исключения. Второстепенные коды исключений имеют тип unsigned long и состоят из 20-битного "Vendor Minor Codeset ID" (VMCID), который занимает старшие 20 бит, и собственно младшего кода, который занимает младшие 12 бит.

Второстепенные коды для стандартных исключений предваряются VMCID, назначенным OMG, определенным как беззнаковая длинная константа CORBA::OMGVMCID, которая имеет VMCID, назначенный OMG, занимающий старшие 20 бит. Второстепенные коды исключений, связанные со стандартными исключениями, которые находятся в Таблице 3–13 на странице 3-58, объединяются с помощью операции ИЛИ с OMGVMCID для получения значения второстепенного кода, которое возвращается в структуре ex_body (см. Раздел 3.17.1, «Определения стандартных исключений», на странице 3-52 и Раздел 3.17.2, «Стандартные второстепенные коды исключений», на странице 3-58).

В пределах пространства, назначенного поставщиком, назначение значений второстепенным кодам остается за поставщиком. Поставщики могут запросить выделение VMCID, отправив электронное письмо на адрес [email protected]. Список назначенных в настоящее время VMCID можно найти на веб-сайте OMG по адресу: https://www.omg.org/cgi-bin/doc?vendor-tags

VMCID 0 и 0xfffff зарезервированы для экспериментального использования. VMCID OMGVMCID (Раздел 3.17.1, «Определения стандартных исключений», на стр. 3-52) и 1 по 0xf зарезервированы для использования OMG.

Общий брокер объектных запросов: архитектура и спецификация (CORBA 2.3)

Расположение Корба (CorbaLoc)

Corba Location (CorbaLoc) — это строковая ссылка на объект CORBA, которая выглядит как URL.

Все продукты CORBA должны поддерживать два определенных OMG URL: " corbaloc: " и " corbaname: ". Их цель — предоставить понятный и редактируемый человеком способ указать местоположение, где можно получить IOR.

Пример corbaloc показан ниже:

corbaloc::160.45.110.41:38693/StandardNS/NameServer-POA/_root

Продукт CORBA может опционально поддерживать форматы " http: ", " ftp: " и " file: ". Семантика этих форматов заключается в том, что они предоставляют сведения о том, как загрузить строковый IOR (или, рекурсивно, загрузить другой URL, который в конечном итоге предоставит строковый IOR). Некоторые ORB предоставляют дополнительные форматы, которые являются фирменными для этого ORB.

Преимущества

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

Языковая независимость
CORBA была разработана, чтобы освободить инженеров от ограничений, связанных с привязкой их проектов к определенному языку программного обеспечения. В настоящее время существует множество языков, поддерживаемых различными поставщиками CORBA, наиболее популярными из которых являются Java и C++. Существуют также реализации C++11, C-only, Smalltalk, Perl, Ada, Ruby и Python, и это лишь некоторые из них.
независимость от ОС
Дизайн CORBA не зависит от ОС. CORBA доступен в Java (независимо от ОС), а также изначально для Linux/Unix, Windows, Solaris, OS X, OpenVMS, HPUX, Android, LynxOS, VxWorks, ThreadX, INTEGRITY и других.
Свобода от технологий
Одним из основных неявных преимуществ является то, что CORBA предоставляет инженерам нейтральное игровое поле для нормализации интерфейсов между различными новыми и устаревшими системами. При интеграции C, C++, Object Pascal, Java, Fortran, Python и любого другого языка или ОС в единую связную модель проектирования системы CORBA предоставляет средства для выравнивания поля и позволяет разрозненным командам разрабатывать системы и модульные тесты, которые впоследствии могут быть объединены в целую систему. Это не исключает необходимости принятия базовых решений по проектированию системы, таких как потоки, синхронизация, время жизни объекта и т. д. Эти проблемы являются частью любой системы независимо от технологии. CORBA позволяет нормализовать элементы системы в единую связную модель системы.
Например, проектирование многоуровневой архитектуры упрощается с помощью сервлетов Java на веб-сервере и различных серверов CORBA, содержащих бизнес-логику и оборачивающих доступы к базе данных. Это позволяет изменять реализации бизнес-логики, в то время как изменения интерфейса должны обрабатываться так же, как и в любой другой технологии. Например, база данных, обернутая сервером, может иметь изменение схемы базы данных ради улучшения использования диска или производительности (или даже полномасштабной смены поставщика базы данных), не влияя на внешние интерфейсы. В то же время унаследованный код C++ может взаимодействовать с унаследованным кодом C/Fortran и кодом базы данных Java, а также может предоставлять данные веб-интерфейсу.
Типизация данных
CORBA обеспечивает гибкую типизацию данных, например, тип данных "ANY". CORBA также обеспечивает тесно связанную типизацию данных, уменьшая человеческие ошибки. В ситуации, когда передаются пары Имя-Значение, возможно, что сервер предоставляет число там, где ожидалась строка. Язык определения интерфейса CORBA предоставляет механизм, гарантирующий, что пользовательский код соответствует именам методов, возвращаемым значениям, типам параметров и исключениям.
Высокая настраиваемость
Многие реализации (например, ORBexpress (реализация Ada, C++ и Java) [6] и OmniORB (реализация с открытым исходным кодом C++ и Python)) [7] имеют опции для настройки функций управления потоками и соединениями. Не все реализации ORB предоставляют одинаковые функции.
Свобода от деталей передачи данных
При обработке низкоуровневого соединения и потоковой передачи CORBA обеспечивает высокий уровень детализации в условиях ошибок. Это определено в стандартном наборе исключений, определенном CORBA, и расширенном наборе исключений, специфичном для реализации. С помощью исключений приложение может определить, был ли вызов неудачным по таким причинам, как «Небольшая проблема, попробуйте еще раз», «Сервер не работает» или «Ссылка не имеет смысла». Общее правило таково: отсутствие исключения означает, что вызов метода был успешно завершен. Это очень мощная конструктивная особенность.
Сжатие
CORBA упорядочивает свои данные в двоичной форме и поддерживает сжатие. IONA, Remedy IT и Telefónica работали над расширением стандарта CORBA, которое обеспечивает сжатие. Это расширение называется ZIOP, и теперь это формальный стандарт OMG.

Проблемы и критика

Хотя CORBA внесла большой вклад в написание кода и разработку программного обеспечения, она стала предметом критики. [8]

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

Первоначальные несовместимости реализации
Первоначальные спецификации CORBA определяли только IDL, а не формат on-the-wire. Это означало, что совместимость исходного кода была лучшей из доступных в течение нескольких лет. С CORBA 2 и более поздними версиями эта проблема была решена.
Прозрачность местоположения
Понятие прозрачности местоположения CORBA подверглось критике; то есть объекты, находящиеся в одном адресном пространстве и доступные с помощью простого вызова функции, обрабатываются так же, как объекты, находящиеся в другом месте (разные процессы на одной и той же машине или на разных машинах). Это фундаментальный недостаток дизайна, [9] [ неудачная проверка ], поскольку он делает весь доступ к объектам таким же сложным, как и самый сложный случай (т. е. удаленный сетевой вызов с широким классом сбоев, которые невозможны в локальных вызовах). Он также скрывает неизбежные различия между двумя классами, делая невозможным для приложений выбор подходящей стратегии использования (то есть вызов с задержкой 1  мкс и гарантированным возвратом будет использоваться совсем иначе, чем вызов с задержкой 1 с с возможным сбоем транспорта, в котором статус доставки потенциально неизвестен и может занять 30 с для истечения времени ожидания).
Недостатки конструкции и процесса
Создание стандарта CORBA также часто упоминается из-за процесса его разработки комитетом . Не было процесса арбитража между конфликтующими предложениями или принятия решения об иерархии проблем, которые нужно было решать. Таким образом, стандарт был создан путем объединения функций во всех предложениях без учета их согласованности. [10] Это сделало спецификацию сложной, дорогой для полной реализации и часто неоднозначной.
Комитет по проектированию, состоящий из смеси поставщиков и клиентов по внедрению, создал разнообразный набор интересов. Это разнообразие затруднило создание единого стандарта. Стандарты и совместимость усилили конкуренцию и облегчили перемещение клиентов между альтернативными реализациями. Это привело к большой политической борьбе внутри комитета и частым выпускам ревизий стандарта CORBA, которые, по мнению некоторых разработчиков ORB, было трудно использовать без фирменных расширений. [8] Менее этичные поставщики CORBA поощряли привязку клиентов и добивались сильных краткосрочных результатов. Со временем поставщики ORB, поощряющие переносимость, захватили долю рынка. [ требуется ссылка ]
Проблемы с реализацией
На протяжении всей своей истории CORBA страдала от недостатков в плохих реализациях ORB. К сожалению, многие статьи, критикующие CORBA как стандарт, являются просто критикой особенно плохой реализации CORBA ORB.
CORBA — это всеобъемлющий стандарт со множеством функций. Немногие реализации пытаются реализовать все спецификации, [10] а первоначальные реализации были неполными или неадекватными. Поскольку не было требований предоставить эталонную реализацию, участники могли свободно предлагать функции, которые никогда не проверялись на полезность или реализуемость. Реализации еще больше затруднялись общей тенденцией стандарта быть многословным и распространенной практикой компромисса путем принятия суммы всех представленных предложений, что часто создавало API, которые были непоследовательными и сложными в использовании, даже если отдельные предложения были совершенно разумными. [ необходима цитата ]
Надежные реализации CORBA было очень трудно получить в прошлом, но теперь их гораздо легче найти. SUN Java SDK поставляется со встроенной CORBA. Некоторые плохо спроектированные реализации оказались сложными, медленными, несовместимыми и неполными. Надежные коммерческие версии начали появляться, но за значительную цену. По мере того, как становились доступными качественные бесплатные реализации, плохие коммерческие реализации быстро умирали.
Брандмауэры
CORBA (точнее, GIOP ) не привязана к какому-либо конкретному транспорту связи. Специализацией GIOP является Internet Inter-ORB Protocol или IIOP. IIOP использует необработанные соединения TCP/IP для передачи данных.
Если клиент находится за очень ограничивающим брандмауэром или прозрачной средой прокси-сервера, которая разрешает только HTTP- подключения наружу через порт 80, связь может быть невозможна, если только рассматриваемый прокси-сервер не разрешает также метод HTTP CONNECT или соединения SOCKS . В свое время было сложно даже заставить реализации использовать один стандартный порт — вместо этого они, как правило, выбирали несколько случайных портов. На сегодняшний день текущие ORB имеют эти недостатки. Из-за таких трудностей некоторые пользователи все чаще используют веб-сервисы вместо CORBA. Они взаимодействуют с помощью XML / SOAP через порт 80, который обычно остается открытым или фильтруется через HTTP-прокси внутри организации для просмотра веб-страниц через HTTP. Однако последние реализации CORBA поддерживают SSL и могут быть легко настроены для работы на одном порту. Некоторые ORBS, такие как TAO , omniORB и JacORB, также поддерживают двунаправленный GIOP, что дает CORBA преимущество в возможности использовать обратную связь вместо подхода с опросом, характерного для реализаций веб-сервисов. Кроме того, большинство современных брандмауэров поддерживают GIOP и IIOP и, таким образом, являются брандмауэрами, дружественными к CORBA.

Смотрите также

Разработка программного обеспечения

Компонентно-ориентированные программные технологии

Языковые привязки

Ссылки

  1. ^ Взлет и падение CORBA
  2. ^ "История CORBA". Object Management Group . Получено 12 марта 2017 г.
  3. ^ "История CORBA". Object Management Group . Получено 4 июня 2017 г.
  4. ^ "OMG IDL Corba Version". Object Management Group . Получено 4 декабря 2023 г.
  5. ^ "Модель компонентов CORBA". Журнал доктора Добба . 1 сентября 2004 г. Получено 13 марта 2017 г.
  6. ^ «ORBexpress: Обзор».
  7. ^ "omniORB: Free CORBA ORB" . Получено 10 октября 2024 г. .
  8. ^ ab Chappel, David (май 1998 г.). «Проблемы с CORBA». davidchappel.com. Архивировано из оригинала 3 декабря 2012 г. Получено 10 октября 2024 г.
  9. ^ Уолдо, Джим; Джефф Уайант; Энн Воллрат; Сэм Кендалл (ноябрь 1994 г.). «Заметка о распределенных вычислениях» (PDF) . Sun Microsystem Laboratories . Архивировано (PDF) из оригинала 10 октября 2022 г. . Получено 10 октября 2024 г. .
  10. ^ ab Henning, Michi (30 июня 2006 г.). «Взлет и падение CORBA». ACM Queue . 4 (5). Association for Computing Machinery : 28–34. doi : 10.1145/1142031.1142044 . S2CID  12103742.

Дальнейшее чтение

Внешние ссылки