Опубликован: 11.05.2007 | Доступ: свободный | Студентов: 1698 / 235 | Оценка: 4.36 / 4.25 | Длительность: 16:06:00
Лекция 2:

Взаимодействие компонент распределенной системы

< Лекция 1 || Лекция 2: 12345 || Лекция 3 >

Использование свойств удаленных объектов

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

processing.FirstName = "Иван";
processing.SecondName = "Иванов";
processing.ThirdName = "Иванович";
processing.City = "Москва";
result = processing.Run();

Если processing – локальный объект, то в методе Run() он будет иметь доступ к установленным здесь значениям своих методов. Предположим, что processing – удаленный объект. В этом случае возможны, например, следующие варианты.

  1. Используется модель единственного вызова, причем установка свойства объекта рассматривается как вызов метода установки свойства ( set в C#). В этом случае к моменту вызова метода Run состояние полей объекта не задано (при отсутствии пула объектов) или неопределенно (при использовании пула объектов).
  2. Используется модель единственного вызова, но установка свойств объекта не рассматривается как удаленный вызов. Например, их значения сохраняются на стороне клиента и передаются на сервер в момент вызова метода, где на основе этих значений заполняются поля объекта. В этом случае результат будет корректен.
  3. Используется модель активации по запросу клиента, или такой вариант модели единственного вызова, в котором присваивание свойств объекта приводит к передаче данных на сервер без последующей деактивации объекта (по существу такая модель уже не является моделью одного вызова). В этом случае результат так же будет корректен, но присваивание свойств объекту приводит к непроизводительным удаленным вызовам.
  4. Используется модель одного экземпляра. В этом случае результат будет некорректным, поскольку поля объекта будут заполняться параллельно разными клиентами.

Таким образом, один и тот же код может давать разные результаты в зависимости от модели использования удаленной компоненты, причем только в одном из примеров был получен корректный результат при минимальных накладных расходах. Можно сделать заключение, что использование в программе свойств удаленного объекта приводит к зависимости ее результата от используемой промежуточной среды и ее конфигурации. Наилучшим вариантом решения этой проблемы представляется отсутствие публичных свойств у удаленного объекта. В таком случае использование удаленного объекта может не отличаться от вызова метода локального объекта. Однако применение такого подхода "в лоб" (так называемый chunky design ) может привести к плохо читаемому коду, например следующему.

result = processing.Run("Иванов", "Иван", "Иванович", "Москва");

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

person.FirstName = "Иван";
person.SecondName = "Иванов";
person.ThirdName = "Иванович";
person.City = "Москва";
result = processing.Run(person);

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

task.Epsilon = 1e-5:
task.X1 = -1;
task.X2 = 1;
task.MaximumSteps = 20;
task.Function += X2Function;
result = processing.Run(processingArguments); 
...
double X2Function(double x)
{
    return x*x;
}

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

Для решения возникшей проблемы в общем случае требуется передать тем или иным способом код функции (и, возможно, используемых ею данных) на сервер с реализующим математический метод удаленным объектом. Такой подход неприменим в общем случае по соображениям безопасности, но при необходимости можно, например, при использовании .NET Framework передать клиенту сборку с требуемым кодом как данные при удаленном вызове. В качестве возможной альтернативы для математических задач может выступать и передача кода функции для дальнейшей компиляции встроенным компилятором языка C#.

< Лекция 1 || Лекция 2: 12345 || Лекция 3 >