Систематика и обобщение методологий моделирования и языков программирования

Необходимы перепосты и переводы на другие языки. Газета "Компьютерные вести" kv.by/index2010383801.htm Издание 4-е, исправленное и дополненное. Другие статьи (оглавление)


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

Систематика методологий

Прежде всего следует различать два вида процессов: происходящие одновременно в разных участках пространства и происходящие последовательно с одним и тем же участком. Будем называть их F[eat] и A[ct]. Несколько A возникают при делении одного F по времени. Таким образом места расчленения - состояния или S[tate] - чистая абстракция. F выдают, и в них поступают потоки команд C[ommand], перерабатываемого продукта D, инструментов T[ool] - людей, станков, денег, реакторов - и параметров других участков пространства M[edia]. D в IT-индустрии - это данные (data), в других отраслях это будет что-то из T, а данные войдут в состав T. Отдельное внимание к M возникает при проектировании компьютерных игр - для детей, для военных, для бизнесменов. Разумеется, у группы A, входящих в состав одного F, все C, D, M, T одни и те же.

Потоки могут разветвляться (дублироваться), попадая сразу в несколько F; и каждый F может принимать сразу несколько однотипных потоков. Обычно они начинаются в одном F и заканчиваются в другом, но бывают истоки и стоки C, D, M, T. А вот "стрелки" S такой эквилибристики проделать не могут: либо в один следующий A, либо в другой. Однотипные потоки, пришедшие из двух источников, являются двойным комплектом информации, а S - одинарным и указывает, что переход произошел либо из одного предыдущего A, либо из другого. "Либо, либо", а не "и, и". Аналогом истоков и стоков служат начальные и конечные процессы A.

В дальнейшем все эти F, A, S, C, D, M, T будем называть моделируемыми аспектами. К каждому из них может быть прикреплена диаграмма декомпозиции, на которой он разложен на составляющие егó аспекты. И так до бесконечности.

Частности

Все это хозяйство рисуют геометрическими фигурами разной формы и цвета закраски и стрелками, отличающимися типом линии и используемой гранью фигуры. Хотя стилевых отличий достаточно для обозначения всех аспектов, каждая методология ограничивается только их частью. Как следствие в практику вошло употребление сразу нескольких диаграмм. Кроме того, декомпозиции подвергают только фигуры, но не стрелки. Ни одна методология не выделяет M; только половина рассматривает T; многие не различает F и A, подразумевая под ними какой-то общий P[rocess]; многие - C и D, ссылаясь на них как на некий общий E[ntry], соответственно им ведом единственный вид истоков и стоков E.

IDEF0, например, обозначает P прямоугольниками; C, D, T - стрелками, которые отличаются только тем, к каким граням фигуры подходят (выходят они из правой грани). Истоки и стоки не отмечены, и начальные и конечные стрелки сильно смахивают на недостроенность диаграммы. Декомпозиция предусмотрена только для P.

В DFD методология одна, нотаций две - Йордона и Гейн-Сарсона, отличий ноль. P представлены кругами, E - стрелками без надписей (в дальнейшем если специально не указано, надписи присутствуют), E - прямоугольниками. В связи с таким выбором фигур, рефлекторно соотнести эти диаграммы с другими методологиями не удастся.

В EPC главным различительным свойством фигур является цвет, впрочем дублируемый незначительными изменениями формы. Фигурами в методологии представлены P, E (event), T (organization unit и т.д.). Стрелки без надписей между ними изображают временную последовательность. Основой является построение цепочек P-E-P-E-P-E-P.

Отечественный ГОСТ рисует P горизонтальными прямоугольниками, E - стрелками с одинарными линиями, T - стрелками с двойными. Он не различает C и D, но различает C и D и изображает первые горизонтальными прямоугольниками с выпуклыми боковыми сторонами, а вторые - вертикальными с выпуклой верхней стороной (для полноты картины, T - равнобокие трапеции широким основанием кверху). Декомпозиции подвергается только P, подпрограммы обозначены горизонтальными прямоугольниками с двойными линиями по бокам. В качестве бесплатного приложения существует двойная горизонтальная линия (без стрелок), которая проводится сверху и снизу группы параллельных процессов; при этом нижняя линия означает ожидание завершения всех процессов, т.е. барьер в терминах MPI и PVM. Вообще-то барьер в параллельном программировании излишен.

Из полезных изюминок хотелось бы отметить вот что. Издавна существует мысль сортировать ветви алгоритма по тому, насколько большой exception они описывают. Например, Теория Решения Изобретательских Задач в лице своего шага 1.4 различает самый-самый вариант и все остальные (бери то, что обеспечивает наилучшее выполнение главной задачи - altshuller.ru/triz/ariz85v-1.asp). Рисовалка ГОСТа "ДРАКОН" советует располагать ветви по принципу "чем правее, тем хуже", давая самой левой специальное название "шампур". Так вот, сам ГОСТ требует обозначать шампур сплошными линиями, а остальные - пунктирными.

IDEF3, он же WFD, на самом деле является собранием двух методологий - process flow и object state transition. В первой прямоугольниками изображают A, стрелками без надписей - S; во второй кругами - S, стрелками - A. Для декомпозиции предназначены только прямоугольники A. Остальное - бесплатное приложение. Соединение стрелок S можно пометить значком "барьер" (пиктограммой "амперсанд"). Сплошная стрелка S означает, что A, из которого она исходит, завершается до начала того A, к которому она приходит; пунктирная - иначе. Истоки и стоки задаются комментариями (вида "объект ссылки").

Если в OSTD все повторяющиеся S обозначить единственным кругом и над стрелками надписать не названия A, а введенные и выведенные E через слэш - традиционно обозначаемые как I/O - то получим конечный автомат Мили. Декомпозиция S называется "вложенный КА".

Остался UML - сборная солянка из sequence, collaboration, use case и state transition. Sequence diagram располагает вертикально "линии жизни" S-A-S-A-S-A-S нескольких участков пространства (в каждой линии S и A могут повторяться несколько раз), время направлено вниз. Первые S изображены горизонтальными прямоугольниками, все последующие - вертикальными отрезками, все A - вертикальными прямоугольники. Надписи есть только на первых S. Параллельно вертикальными прямыми с фигуркой человечека в начале представлены E. Между A и A, A и E протянуты горизонтальные стрелки, обозначающие E. Бесплатное приложение представлено разновидностями наконечника стрелки, указывающими реакцию получателя (не присылать подтверждение о приеме) или (обратите внимание, что не "и") отправителя - бесконечное ожидание ответа, ожидание в течение timeout, продолжение работы без ожидания, требование ответить немедленно или вообще никогда. Стандартный наконечник означает необходимость подтверждения и отсутствие ожидания. E самому себе есть стрелка вправо-вниз-влево.

Если оставить только горизонтальные прямоугольники, человечеки и все E, заменить наконечники стандартными, то получим collaboration diagram. А если еще горизонтальные прямоугольники превратить в горизонтальные овалы и постирать надписи над E, результат называется use case diagram. На последнюю такими же неотличимыми стрелками могут быть нанесены отношения гипоним-гипероним между E (a-la IDEF5), а стрелками с надписями <<uses>> и <<extends>> - отношения холоним-мероним между овалами (декомпозиция всех A одной линии жизни, понимаемых как единый F!). Наконец, state transition diagram - это PFD из IDEF3, на котором A изображены не прямоугольниками, а кругами (причем в качестве надписей могут фигурировать I или O с префиксом ^) и добавлены начальные и конечные A в виде жирных точек и жирных точек с ободком. Таким образом "state" в названии - с намёком на конечный автомат - чистейшая глупость. Полезной изюминкой является возможность надписать над стрелкой в квадратных скобках "ограждающее условие" для S, при котором запуск следующего A невозможен.

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

Упомянем также о расщеплении иного рода, в каком-то смысле "перпендикулярном" декомпозиции. Речь идет об IDEF1, подвергающем внутренней трансформации S и D. Не будем останавливаться на нем подробно - нелепости реализации перечислены в разделе "Доступ по третьей парадигме" отдельной публикации "Ошибки и их исправление в эргономике API" и в статье "Автоматический ввод-вывод XML в IDEF1-хранилище" Но перед тем как продолжить условимся, что ни одно из новых понятий не будем обозначать словом схема, применяемом при реляционных построениях.

Что языки взяли из методологий

Почти ничего! Нет типа данных STATE, операторов запроса и смены состояния, поэтому контролирует его не компилятор, а программист вручную, запоминая предназначение переменных и сообщений. Особенно это трудоемко при построении сети конечных автоматов. Отсутствует F: например, никакой "FEAT featname {}" не объединяет операторы воедино, и возможно перейти в точку непосредственно перед или после вызова функций fork и thread. Словом, языки не помогают человеку справиться с его работой, а лишь пересказывают архитектуру ЭВМ. Этакие переносимые ассемблеры.

Нет разделения на C и D, если не считать отдельных полномочий на CREATE TRIGGER и INSERT в SQL. Нет триггеров C за исключением SQL и ПРАЛУ, да и то, только в последнем их можно активизировать и дезактивизировать, в SQL приходится удалять и создавать, заново определяя их тела (ПРАЛУ представляет собой таблицу из четырех колонок: в первой стоит уникальный идентификатор строки, вторая булевская указывает активна строка или нет, третья тоже булевская и описывает условия срабатывания триггера, четвертая содержит само тело триггера, которое может активировать или дезактивировать любую строку по ее идентификатору). Но ни в одном языке триггеры нельзя вкладывать один в другой и извлекать, чтобы активизировать и дезактивизировать одновременно.

Кроме того, везде выражения по умолчанию выполняются последовательно, а не одновременно, что необыкновенно способствует искусственной задаче распараллеливания. И решать ее приходится - чтобы задействовать все 256 тредов процессора Niagara3, 32 треда процессора Power7 и т.д. Количество тредов все время увеличивается, потому как баснословно дорогá более быстроходная элементная база.

От концептуальной части перейдем к представлению. Оценить сложность алгоритма легче, если он изображен графом, а не текстом. К тому же разное расположение линий быстро различимо при беглом пролистывании, что существенно облегчают поиск и способствуют запомининанию. Поэтому не только сама диаграмма методологии должна быть неотъемлемой частью языка программирования (теперь уже не нужны FEAT, ACT, STATE, циклы "while-do" и "do-while"), но и выражения "if" и "switch", вписываемые в F и A, должны представляться графически. Именно такой язык должен быть базовым в операционной системе и поставляться вместе с её ядром вместо Си.

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

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

Что осталось за пределами нашей систематики "F, A, S, C, D, M, T"? Людям внушили изолировать все структуры (записи по терминологии IDEF1, хотя какие это записи - внешних ключей-то нет) - и снова соединять их friend-функциями, ведь любая сколько-нибудь значимая часть информации обладает свойством целостности, является деревом. Эта технология выкачивания денег называется ОО, и хотя все мучаются, считанные единицы отваживаются произнести, что "король-то голый".

Другая, уже отыгравшая финансовая пирамида - панораму всего дерева (например, путь в командной строке shell, XPath в XSL, XTree в sql5.19.3.pdf с.8-11, 18, 21, 34-38) заменили на рекурсию "FN(X,Z) :- tablename(X,Z). FN(X,Z) :- tablename(X,Y), FN(X,Z). ?- FN(identifier,X).", для которой известны и более древние языки. Результат перепозиционирования назывался Prolog.

Всеобъемлющая методология

Назовем ее FAL. Её картинки бывают трех видов - feat-диаграммы (FD), act-диаграммы (AD) и листинги (L). На первых изображены только F - прямоугольниками; на вторых - только A, кругами; на третьих вообще не граф, а текст. Потоки и S представлены стрелками. В надписях фигур и стрелок пользователь ведет литературное программирование, а на листингах - настоящее. Декомпозиция F, A, потоков и C возможна любой картинкой, S - только AD. Картинка имеет границу в виде прямоугольника или окружности, если прикреплена к таковым (корневая имеет в виде прямоугольника); и не имеет никакой, если прикреплена к потоку или к S. Соответственно она называется q[uadrangular], r[ound] и [un]b[ounded].

Для D выберем сплошную линию, для M - точечную. Визуализация T, не подлежащего программированию, будет отключена, как только модель попадет к кодерам, поэтому обозначим его сплошной двойной (плохо отличимой от одинарной). "C" пусть состоит из поставленных встык крохотных кружочков, что-то вроде "ooooo"; S - из значков слэш, /////, но наклонённых гораздо больше - под углом 45 градусов, очень похоже на след от протектора автомобильной шины. Стрелки с волнистой линией назовем U: от одного F к другому означает над- и под-программы, от хранилища D к триггеру C - активизацию последнего, от одного C к другому - вложение второго в первый (хранилище - это СУБД минус машина "join", см. раздел "Архитектура ОС" ранее упомянутой статьи про API).

На диаграммах стрелки протянуты между фигурой и границей или между фигурой и фигурой. На qFD возможны только потоки, на rFD - и потоки, и S. На AD - только S, т.к. для всех её А потоки одинаковы, причем конец входящей и начало исходящей стрелок попарно соединяются внутри кругов, чтобы не рисовать одно A несколько раз (литературное программирование в A ведётся поверх стрелок). Входящая S на qAD всего одна, на rAD - сколько угодно, исходящих любое количество на обеих. На L есть только потоки. Они протянуты между бесконечностью и границей, в месте касания коей имеют дополнительную надпись - свое название как переменной. Эти переменные в коде и используются. Входные и выходные стрелки должны быть названы по-разному.

"If" и "switch" обозначены разветвлениями стрелок. У первого надпись находится непосредственно перед точкой ветвления и содержит логическое условие, например "fld=5"; у второго надписей несколько, расположены непосредственно после и являются возможными значениями переменной. Линию до ветвления у "if" продолжает линия "yes" ("no" уходит вниз или вправо независимо от направления стрелки), а у "switch" - линия "default", которая единственная не имеет надписи и если отсутствует, ее место не занимают надписанные.

Упирающийся в линию потока незакрашенный наконечник другого однотипного потока означает операцию объединения, закрашенный - исключения, без наконечника - пересечения (исходная линия может в этом месте как менять направление, так и нет). Поток или S с закрашенным наконечником, упирающийся в U, фигурально изображает разрывание последнего: дизактивизацию триггера или вытаскивание одного триггера из другого; еще один поток или S с незакрашенным в ту же U - восстановление: активизацию или повторное вложение. Любой поток с закрашенным, упирающийся в S, есть запрет перехода из одного A в другое; еще один с незакрашенным - восстановление такой возможности. Линии на поворотах и ответвлениях образуют не угол, а дугу окружности. Это расширяет пространство между частями графа и тем сильнее выделяет части.

К подпрограмме не могут подходить и отходить стрелки, кроме U. Ее прямоугольник снаружи сверху имеет дополнительную надпись - свое название как функции. Ее декомпозиция содержит только те стрелки, что есть у всех ее над-программ. На FD-декомпозициях над-программ автоматически появляется озаглавленный прямоугольник, на L-декомпозициях - объявление функции. Отношения "над"-"под" назовем иерархией, а отношения, порожденные прикреплением картинок - деревом. Элементы иерархии обозначим префиксами "над" и "под", а элементы дерева - прилагательными "родительский" и "дочерний". Аналогично в первом случае - проксимальный-дистальный, во втором - предок-потомок.

F, имеющие по любому из видов потоков, и А, имеющие по S только приходящую стрелку, но не отходящую, или наоборот, автоматически считаются F и A, и прямоугольники и круги становятся жирными. Цвета же пользователь применяет для группировки фигур и стрелок по соответствию и по важности (сопоставьте с группировкой для текста). Если на каком-то конце D нет фигуры, то вместо нее автоматически подставляется жирная точка (D); если на конце C - такой же маленький закрашенный квадратик (C). Конец считается истоком или стоком в зависимости от направления стрелки. "Висящий" конец M - это действительно недостроенность диаграммы.

Панорама движения информации не будет полной, если над жирными точками не поставить адреса этих удаленных хранилищ (ненадписанные - локальные); имя и пароль ОС спросит во время выполнения программы. Устройства ввода-вывода - частные случаи хранилищ. Мы не знаем, сколько и какие они будут в будущем, не станем вводить для них новые фигуры или иконки, просто надпишем "address/screen" и "address/keyboard". Квадратики же всегда связаны с помощью U с каким-либо D (не связаны - не работают), поэтому сверху и снизу них укажем параметры ON и AFTER из SQL.

Мы уже предпочли AD циклам "while-do" и "do-while". Полностью отказаться от текстового программирования не удастся из-за выражений "WHERE fld = SELECT", аггрегатов и т.п. (цикл "for" в языках необходимо заменить на матричные и тензорные выражения, т.е. непроцедурные; Fortran90, MathCAD и статья "Чего не было в кодировках и до чего до сих пор так и не додумались" - в помощь). Если данные пришли из D, выход из F заворачивать назад в хранилище не надо, если только вы не хотите задублировать данные. Вставка новой информации есть частный случай присваивания - в * или в @µ аналогично изображенному на с.89-91, 94-96 документа sql5.19.3.pdf Удаление - это просто DELETE на листинге. Кстати, если он совсем короткий, его содержимое, а не прямоугольник можно разместить в разрыве линии потока.

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

Дмитрий Тюрин (DmitryTurin.narod.ru):
dima.turin@centrum.cz (все письма из домена .ru попадают в спам), dima.turin@gmail.com