Ситуационно-ориентированное программирование

Основой всего, что сделано в методологии программирования, включая и объектное программирование стало структурное программирование, предложенное Эдсгером Дейкстрой в 1970-х годах. Одной из основных идей было введение блочных операторов ветвления (IF, THEN, ELSE) и цикличности (WHILE, FOR, DO, UNTIL и др.) вместо проблемного оператора GOTO, который приводил к получению запутанного, неудобочитаемого «спагетти-кода».

Как известно, существует три вида алгоритмов: линейные, разветвленные и циклические:

0913ca9aacc441eaaa65eed5f8989394

Для использования в интеллектуальных системах структурное программирование обладает серьезным недостатком. Любая интеллектуальная система подразумевает наличие процесса обучения — изменения своего поведения посредством обучения с учителем, или по мере накопления опыта на основе собственных наблюдений. Такое изменение поведения должно выполнятся специальными средствами метапрограммирования и в конечном счете приводит к внесению изменений в исходный код интеллектуальной программы. Недостаток блочной парадигмы структурного программирования заключается в возможности неограниченной вложенности одних блоков в другие. Необдуманное исправление кода одного блока может повлечь некорректную работу вложенных блоков, а иногда и блоков уровнями выше. Такое внесение изменений в исходный код требует наличия специально подготовленного человека (разработчика программного обеспечения), который перед внесением изменений обязан изучить не только блок кода, предназначенный для исправления, но и вложенные, а так же смежные с ним блоки.

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

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

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

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

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

Отличие сутуационно-ориентированного подхода от блочного можно рассмотреть на примере. Допустим, имеется программа на языке Си, которая удаляет все вхождения символа «C» из исходной строки «ABCABCABC» и печатает результат. Исходный код такой программы будет выглядеть примерно следующим образом:

acdb57184a8d40e9ad30d55945593fda

Ситуационно-ориентированная программа на условном алгоритмическом языке будет выглядеть иначе:

567fc80d389247c48451d30663ed1df1

При запуске программы на выполнение произойдет следующее. Изначальное значение переменной i не определено, после присваивания переменной i нулевого значения сработает ситуация S2, так как она срабатывает при каждом изменении значения переменной i, а также при истинности условия s[i]!=c. Поскольку s[0]==’A’, то условие s[i]!=c для первого символа строки является истинным. При вызове обработчика ситуации S2 выполнятся инструкции:

s[j]=s[i];
j=j+1;

После завершения обработчика ситуации S2 будет вызван обработчик ситуации S1, так как она также срабатывает при каждом изменении значения переменной i. Обработчик S1 увеличит значение переменной i на единицу:

i=i+1;

В следствии очередного увеличения значения переменной i произойдет новая итерация вызовов обработчиков ситуаций S2 и S1. Так будет происходить до перебора всех символов строки s. В случае, когда очередной символ s[i] будет равен «C», вызов обработчика S2 производится не будет, поскольку условие s[i]!=c будет ложным.

После того, как все символы входной строки s будут обработаны и программа встретит символ завершения строки ‘\0′, будет вызван обработчик ситуации S3. Ситуация S3 срабатывает каждый раз, когда условие s[i]==’\0′ истинно. В результате вызова обработчика ситуации S3 будут выполнены следующие инструкции:

Удалить ситуацию S1;
s[j]=’\0’;
printf («%s\n», s);

Таким образом, вызов обработчика ситуации S3 удалит ситуацию S1. Обработчик ситуации S1 перестанет вызываться, а значение переменной перестанет постоянно увеличиваться на единицу. Программа выйдет из циклического состояния и завершит выполнение. Результат работы будет такой же, как у программы на языке Си, а именно, вывод строки «ABABAB» на экран.

Теперь, допустим, появилась необходимость доработать обе программы таким образом, чтобы первое вхождение символа ‘C’ не удалялось из строки s. То есть результатом работы программ должна быть строка «ABCABAB».

Доработка программы на Си заключается в объявлении переменной k — счетчика вхождений символа ‘С’ в строку s, а также в добавлении инструкции копирования символа в выходную строку, при условии, что k==1.

Основная сложность такой доработки состоит во все той же строковой зависимости инструкций, которой обладает структурный подход. Во-первых, дополнительное условие if (s[i]==c) нельзя добавить в произвольное место программы, а только внутрь цикла FOR. Будь программа немного сложнее, то и этого было бы недостаточно. То есть условие нужно было бы добавлять не в любое место цикла FOR, а только в определенную его строку. Во-вторых, поскольку внутри цикла FOR теперь большее одной инструкции, его нужно дополнить фигурными скобками. В-третьих, порядок добавляемых инструкций

k++;
if (k==1) s[j++]=s[i];

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

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

В ситуации, когда во входной строке встречается символ «C», необходимо увеличивать на единицу счетчик вхождений символа ‘C’ в строку s.
В ситуации, когда во входной строке символ ‘C’ встречается первый раз, необходимо скопировать символ из входной строки в выходную.

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

b146ee146f40426da39de06a17316eb6

Резюмируя вышесказанное, ситуационно-ориентированный подход:

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

Источник материала
Настоящий материал самостоятельно опубликован в нашем сообществе пользователем proper на основании действующей редакции Пользовательского Соглашения. Если вы считаете, что такая публикация нарушает ваши авторские и/или смежные права, вам необходимо сообщить об этом администрации сайта на EMAIL abuse@proru.org с указанием адреса (URL) страницы, содержащей спорный материал. Нарушение будет в кратчайшие сроки устранено, виновные наказаны.

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