Основы объектно-ориентированного проектирования


Формы побочного эффекта


Определим, какие конструкции могут приводить к побочным эффектам. Операциями, изменяющими объекты, являются: присваивание a := b, попытка присваивания a = b, инструкция создания create a. Если цель a является атрибутом, то выполнение операции присвоит новое значение его полю для объекта, соответствующего цели текущего вызова подпрограммы.

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

Заметим, что, применяя принципы скрытия информации, мы при проектировании ОО-нотации тщательно избегали любых косвенных форм модификации объектов. В частности, синтаксис исключает присваивания в форме obj.attr := b, чья цель должна быть достигнута через вызов obj.set_attr (b), где процедура set_attr (x:...) выполняет присваивание атрибуту attr := x (см. лекцию 7 курса "Основы объектно-ориентированного программирования").

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

Определение: конкретный побочный эффект

Функция производит конкретный побочный эффект, если ее тело содержит:

  • присваивание, попытку присваивания или инструкцию создания, чьей целью является атрибут;
  • вызов процедуры.

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

  • Определение кажется слишком строгим, поскольку любой вызов процедуры рассматривается как создающий побочный эффект, в то время как можно написать процедуру, ничего не меняющую в мире объектов.
    Такие процедуры могут менять нечто в окружении: печатать страницу, посылать сообщения в сеть, управлять рукой робота. Мы будем рассматривать это как своего рода побочный эффект, хотя программные объекты при этом не меняются.
  • Определение кажется слишком слабым, поскольку оно игнорирует случай функции f, вызывающей функцию g с побочным эффектом. Соглашение состоит в том, что в этом случае сама f считается свободной от побочного эффекта. Это допустимо, поскольку правило, которое будет выработано в процессе нашего рассмотрения, будет запрещать все побочные эффекты определенного вида, так что нет необходимости в независимой сертификации каждой функции.
Преимущество этого соглашения в том, что для определения статуса побочного эффекта достаточно анализировать тело только самой функции. Достаточно тривиально, имея анализатор языка, встроить простой инструментарий, который для каждой функции независимо определял бы, обладает ли она конкретным побочным эффектом в соответствии с данным определением


Содержание раздела