Событийно-управляемые программные системы

В книге мы рассматривали случаи, когда процедура активизируется командой, которая вызывает процедуру явным образом. Однако существуют случаи, когда процедура активизируется неявно при появлении какого-либо события. В качестве примера можно привести графические пользовательские интерфейсы, в которых процедура, описывающая, что должно произойти, если щелкнуть мышью на кнопке, активизируется не вызывающей программной единицей, а щелчком на кнопке. Системы программного обеспечения, в которых процедуры активизируются таким способом, называются событийно-управляемыми (event-driven system). Говоря проще, событийно-управляемые программные системы состоят из процедур, которые описывают, что должно происходить в результате различных событий. Во время выполнения системы эти процедуры находятся в бездействии до тех пор, пока не произойдет событие, активизирующее их, выполняют свою задачу и возвращаются в состояние покоя.

Параметры

При написании процедур часто используются абстрактные имена, которые определяются более подробно в процессе выполнения процедуры. Например, в процедуре для сортировки списка, записанной с помощью псевдокода (см. листинг 4.2), используется абстрактный, а не какой-то определенный список. В нашем псевдокоде мы договорились записывать такие имена в скобках в заголовке процедуры. Поэтому процедура начинается с заголовка Procedure Сортировка (Список) и далее следует описание процесса сортировки списка, при этом для списка используется имя Список. Если мы хотим применить эту процедуру для сортировки списка гостей, то нам нужно просто следовать ее указаниям, предполагая, что имя Список относится к нашему списку гостей. Если же мы хотим отсортировать какой-либо другой список, то нужно просто представить, что имя Список относится к этому списку.

Такие абстрактные имена в процедурах называются параметрами (parameters). Точнее, имена, которые используются при написании процедуры, называются формальными параметрами (formal parameter), а конкретные значения, которые эти формальные параметры получают при вызове и используют при выполнении процедуры, называются фактическими параметрами (actual parameter). В некотором смысле формальные параметры представляют собой разъемы, в которые при вызове процедуры помещаются фактические параметры. На самом деле формальные параметры — это переменные, которым во время выполнения процедуры присваиваются необходимые значения (фактические параметры).

В языках программирования для задания формальных параметров применяется такой же метод, как и в нашем псевдокоде. То есть в большинстве языков программирования формальные параметры перечисляются в скобках в заголовке процедуры. Например, описание процедуры ProjectPopul ati on на языке С приведено на рис. 5.10. Эта процедура при вызове получает значение темпа роста популяции и вычисляет предполагаемую численность популяции вида на ближайшие десять лет, предполагая, что исходная численность равна 100, а затем сохраняет полученные значения в глобальном массиве Population.

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

ProjectPopulation (0.03):

может использоваться в программе, написанной на языке С, для вызова процедуры ProjectPopulation (см. рис. 5.10) с присвоением параметру GrowthRate значения 0.03.

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

Предположим, что процедура PrintCheck определяется таким заголовком procedure PrintCheck (Payee. Amount)

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

PrintCheck ("John Doe". 150)

формальному параметру Payee ставится в соответствие фактический параметр John Doe, а формальному параметру Amount — значение 150. Однако если вызвать ту же процедуру с помощью выражения

PrintCheck (150. "John Doe")

то значение 150 будет присвоено формальному параметру Payee, а имя "John Doe" — параметру Amount, что приведет к ошибкам в работе программы.

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

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

Предположим, что процедура Demo была описана следующим образом:

procedure Demo (Formal) Formal <— Formal + 1;

Предположим также, что переменной Actual было присвоено значение 5. Мы вызываем процедуру с помощью выражения Demo (Actual).

Тогда, если параметры передаются по значению, то замена переменной на Formal никак не отразится на переменной Actual (рис. 5.11). Если же параметры передаются по ссылке, то значение переменной Actual увеличится на 1 (рис. 5.12).

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

Функции

Рассмотрим вариации понятия процедуры, которые существуют во многих языках программирования'. Иногда цель процедуры заключается в том, чтобы вычислить значение, а не выполнить какие-либо действия. (Рассмотрим различие между процедурой, которая подсчитывает число проданных вещей, и процедурой, которая сортирует список: в первом случае процедура возвращает значение, во втором — выполняет действие.) Процедура, возвращающая значение, называется функцией. Здесь термин «функция» применяется к программной единице, отличающейся от процедуры тем, что в результате ее выполнения значение вычисляется и возвращается вызывающей программе как «значение функции». Это значение можно либо сохранить в переменной, либо тут же использовать в вычислениях. Например, в языках С, C++ и С# можно использовать выражение ProjectJanSales = EstimatedSales (January); для того чтобы присвоить переменной ProjectJanSai es результат применения функции EstimatedSales, определяющей, сколько вещей предположительно будет продано в январе. Или можно использовать выражение

if (LastJanSales < EstimatedSales (January))... else...

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

Функции определяются почти так же, как процедуры. Различие состоит в том, что заголовок функции обычно начинается с описания типа возвращаемого этой функцией значения, а в теле функции присутствует оператор возврата, операндом которого является возвращаемое значение. Определение функции CylinderVoiume в языке С приведено на рис. 5.13. (На самом деле существует более лаконичная форма записи, но из педагогических соображений мы используем эту запись). При вызове эта процедура получает конкретные значения для формальных параметров Radius и Height и возвращает результат вычисления объема цилиндра с такими параметрами. Таким образом, эту функцию можно использовать в программе для определения стоимости содержимого цилиндра радиусом 3.45 и высотой 12.7, поместив ее в оператор:

Cost = CostPerVolUnit * Cylinder-Volume (3.45. 12.7).


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: