Все существующие языки устарели и функционально, и морально. Какие вехи пройдены, и каков должен быть следующий шаг.
Прежде всего следует различать два вида процессов: происходящие одновременно в разных участках пространства и происходящие последовательно с одним и тем же участком. Будем называть их 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