Skip to content

Latest commit

 

History

History
88 lines (56 loc) · 35.4 KB

2_l4glcase.md

File metadata and controls

88 lines (56 loc) · 35.4 KB

Языки более высокого уровня, языки 4-ого поколения и CASE

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

W = (X + Y) / (Z + 3)

Бесконечно превосходит эквивалент на машинного языке:

LOAD  Z
ADD   3
STORE TEMP
LOAD  X
ADD   Y
DIV   TEMP
STORE W

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

Разумно было ожидать, что эту выразительность можно будет распространить и на другие функции, которые машины должны выполнять. Хоть ввод-вывод и становился все сложнее на уровне машинного кода, операционные системы продолжали развиваться. На IBM 1401 команда чтения карты состоит из одной инструкции и одного символа! В то время как GET от MVS мог выполнить несколько сотен и тысяч машинных инструкций пока программист точно также писал один единственный оператор.

Мы создавали один язык программирования за другим: COBOL должен был стать языком, который позволил бы людям с улицы или, по крайней мере, менеджерам заниматься программированием! Алгол стал стандартом документации для алгоритмов. IBM разработала PL/I (и я работал над одной довольно недолговечной имплементацией); люди разрабатывали компиляторы в своих подвалах; аспиранты писали компиляторы для своих диссертаций (и всё ещё пишут). Всегда было ощущение, что один из этих языков станет ключом к разблокировке великой производительности. Хоть наука о построении компиляторов продвигалась семимильными шагами, в целом продуктивность программистов росла не слишком.

COBOL и PL/I были компиляторами общего назначения. Также было много языков, специализирующихся на определенных задачах: языки моделирования, языки с паттерн-матчингом, языки генерации отчетов. И давайте не забывать APL - чрезвычайно мощный язык, открывший такие загадочные области математики, как обработка матриц, для тех из нас, кто никогда не понимал этого в школе. Умножать матрицу за 5 нажатий клавиш (A + .xB) это по-прежнему впечатляющий уровень выразительности, с которым, как мне кажется, немногие языки программирования когда-либо смогут сравниться! Сочетание огромной мощи в математической области и отсутствия типизации позволяло создавать интересные программы чрезвычайно быстро. Однажды я прочёт комментарий в одной математической статье о том, где автор писал, что его работа была бы невозможна без APL - и я ему верю. Хотя APL определенной мере и использовался в бизнесе, ориентированном на вычисления, особенно в банковском деле и страховании, а также в качестве основы для некоторых из ранних языков запросов, он мало что сделал для большинства коммерческих разработок. Продолжал использоваться COBOL и PL/I, PASCAL, BASIC...

APL по-своему показывает важность сокращения разрыва между идеей и ее воплощением - как и все наиболее популярные языки, это интерпретатор, что означает, что вы можете ввести программу, а затем сразу же запустить ее, без необходимости выполнять этап компиляции или компоновки. Конечно, это больше про восприятие, чем реальный факт (поскольку компиляция может быть столь быстрой, что пользователь не воспримет её как препятствие (прим.пер. - привет, Go)), но факт остается фактом: некоторые очень сомнительные языки стали чрезвычайно популярными, потому как не требуется этап компиляции. Многие циклы CPU на машинах IBM, используются для выполнения CMS EXEC или TSO CLIST. Оба они простые языки, позволяющие объединять команды в скрипты. В настоящее время оба уступают место REXX от Майка Коулишоу, который занимает ту же нишу, но предоставляет гораздо более мощный набор языковых конструкций. REXX тоже интерпретируемый, поэтому он также позволяет изменить программу и очень быстро увидеть результат.

Почему языки (даже интерпретируемые) не увеличили продуктивность по-настоящему? Я исследую этот вопрос подробнее в следующей главе, но одной вещью, что я заметил довольно рано, было то, что все они мало что сделали для логики (IF, THEN, ELSE, DO WHILE и т.д.). Для многих видов бизнес-программирования время разработки увеличивается из-за логики - на самом деле прямых вычислений может быть и немного. Логический выбор можно рассматривать как определенный объем работы, независимо от того, напишете ли вы его так:

IF x > 2
THEN
result = 1
ELSE
result = 2
ENDIF

или эдак:

result = (x>2) ? 1 : 2;

Можно хоть нарисовать как диаграмму Наси-Шнейдермана или Чапина. Можно утверждать, что, поскольку обе приведенные выше фразы предполагают одно бинарное решение, они требуют примерно одинаково объема умственной работы. Чем сложнее логика - тем сложнее кодирование. Фактически, в отрасли довольно широко используется мера, называемая цикломатической сложностью МакКейба, напрямую основанная на количестве бинарных решений в программе. Однако, мы обнаружили, что количество логики в обычном программировании можно уменьшить, потому как большая часть логики в обычном программировании связана с синхронизацией данных, а не с предметной областью. Поскольку FBP устраняет необходимость в большей части этой логики синхронизации, оно сокращает количество логики в программах.

Ряд авторов отметили, что продуктивность улучшается лишь тогда, когда можно уменьшить количество утверждений, необходимых для представления идеи. Другими словами, вы должны сократить "разрыв" между языками бизнеса и машины. Но каков же минимум битов (или нажатий клавиш) для представления идеи? Если условие и его ветви составляют одну "идею", то существует нижний предел компактности. Если это часть большей "идеи", есть надежда представить ее более компактно. Из теории информации мы знаем, что количество битов, необходимых для представления чего-либо - это квадратный логарифм количества доступных альтернатив. Если что-то всегда верно, то выбора нет, поэтому для представления не нужны никакие биты. Если у вас есть 8 вариантов, то для его представления требуется 3 бита (логарифм из 8 по основанию 2). С точки зрения программирования: если вы разрешаете человеку только два брачных состояния, вам нужен только 1 бит (логарифм от 2 по основанию 2). Если вы хотите поддержать более широкую "вселенную", где люди могут быть одинокими, женатыми, разведенными, овдовевшими или состоять в гражданском браке, то это уже пять альтернатив и вам нужно 3 бита (2 недостаточно, т.к. они позволяют только 4 варианта). А ещё они не исключают друг друга, так что вам, вероятно, понадобиться еще больше битов!

Это, в свою очередь, приводит к следующей идее: один из способов уменьшить информационную нагрузку программы - выбрать варианты из более ограниченной вселенной. Однако пользователь должен быть готов жить в этой более ограниченной вселенной. Я помню пакет бухучета, разработанный в Западной Канаде, который очень четко определял вселенную, в которой должны были работать ее клиенты. В этой вселенной он выполнял довольно много функций. Его основные файловые записи всегда имели длину 139 байт, и вы не могли их изменить. Если бы вы попросили об этом, разработчики ответили бы: зачем кому-то это нужно? Как и ожидалось, пакет не прижился, многие клиенты считали его слишком ограниченным. Мне запомнился пример одного клиента, который хотел изменить заголовок отчета, и ему сказали, что это невозможно. Опять же, почему кто-то мог подумать, что это так важно? Что ж, похоже, клиенты, особенно крупные, склонны считать, что заголовки отчетов должны выглядеть так, как они хотят. И это действительно был достаточно мощный пакет за свою цену! Это многому меня научило, и главное, что поставщик может предоставить стандартные компоненты, но заказчик должен иметь возможность писать собственные. Даже если последнее стоит дороже, это выбор клиента, а не продавца. И клиент, конечно, должен иметь возможность визуализировать, что делает инструмент. Это также связано с принципом открытой архитектуры: каким бы впечатляющим ни был инструмент, если он не может взаимодействовать с другими инструментами, он не сможет выжить (перефразировано из Уэйна Стивенса).

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

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

Еще один (часто следующий):

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

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

Эти паттерны возникают так часто, что имеет смысл предоставить шаблоны для их сценариев и декларативные (непроцедурные) способы, позволяющие программисту заполнить лишь необходимые данные.

Привлекательность 4GL также повысилась из-за непривлекательности стандартных средств IBM! Языки определения экрана для IMS и CICS кодируются с использованием макросов ассемблера S/370 (высокоуровневые операторы, которые генерируют константы, определяющие все части экрана). Этот метод позволяет им предоставлять множество полезных возможностей, но описания экранов, написанные таким образом, трудно написать и еще сложнее поддерживать! Скажем, вы хотите сделать поле длиннее и переместить его на несколько строк вниз, вы обнаружите, что меняете большое количество различных значений, которые все должны быть согласованными (значения часто даже не одинаковы, но должны быть согласованы в соответствии с некоторой формулой). Однажды я написал инструмент для создания прототипов, который позволял указывать описывать в формате WYSIWYG (What You See Is What You Get), а затем его можно было использовать для генерации макросов определения экрана, а также всех деклараций HLL, которые должны были ему соответствовать. Он довольно широко использовался внутри IBM, и на самом деле один проект, который нуждался в изменении некоторой MFS, начался с преобразования старой MFS в спецификации прототипа, чтобы они могли вносить свои изменения, а затем генерировать все автоматически. Таким образом, они могли быть уверены, что все данные корректны. Когда такой инструмент с 4GL, вы получаете очень привлекательную комбинацию. Еще лучше, когда инструмент для создания прототипов построен с использованием FBP, поскольку затем его можно "вырастить" в полноценное интерактивное приложение путем постепенного расширения сети. Эта возможность вырастить приложение из прототипа кажется очень желанной и является одной из вещей, которые делают FBP привлекательным.

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

Небольшим примером является утилита IBM MVS Sort (и другие виды сортировки, которые с ней совместимы) - до тех пор, пока можно работать со стандартными параметрами для сортировки в целом, довольно ясно, что она делает и как ей пользоваться. Теперь вы решили, что хотите выполнить некоторую обработку каждой входной записи, прежде чем она попадет в Сортировку. Теперь вам нужно начать работу с выходом "E15". Это требует понимания, как Sort работает изнутри - совсем другое дело. E15 и E35 (процедура вывода) должны быть независимыми, не реентерабельными, загрузочными модулями, что накладывает значительные ограничения на способы, которыми приложения могут использовать библиотеки загрузочных модулей... К счастью, Sort также имеет интерфейс LINKable, поэтому DFDM [и AMPS до него] использовали его, вывернули E15 и E35 наизнанку и преобразовали все это в хорошо управляемый переиспользуемый компонент. Намного проще в использовании, и вы также получаете улучшенную производительность за счет уменьшения количества операций ввода-вывода! Аналогичным образом FBP может использовать те же закономерности, что и 4GL, предоставляя повторно используемые компоненты (составные или элементарные), а также стандартные формы сети. Программистам не нужно понимать внутреннюю логику 4GL, им можно предоставить сеть и спецификации требований к данным различных компонентов. Вместо того, чтобы изменять ментальные модели для понимания и использования выходов, программист имеет единую модель, основанную на данных и их преобразованиях, и может перестраивать сеть, заменять компоненты пользовательскими или вносить другие желаемые изменения.

Должен подметить, что упомянутые выше закономерности также послужили благодатной почвой для различных схем переиспользования кода. Мое мнение о повторном использовании исходного кода - оно страдает от фундаментального недостатка: даже если создание новой программы может быть выполнено относительно быстро, после того, как вы ее построили, ее необходимо добавить в постоянно растущий список программ, которые вы должны поддерживать. Еще хуже, если, как это часто требуется, компоненты должны быть изменены, прежде чем ваша программа сможет работать, например чтобы исправить ошибку. В некоторых фирмах обслуживание занимает 80% ресурсов разработки, поэтому каждое дополнительное приложение увеличивает эту нагрузку. В FBP в идеале все, что добавляется к базе активов, - это сеть - все компоненты представляют собой черные ящики, поэтому новое приложение стоит намного дешевле в обслуживании.

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

Не хочется уходить от этой темы, не упомянув об инструментах CASE (Computer-Aided Software Engineering). Их популярность проистекает из нескольких очень действенных концепций. Во-первых, люди не должны вводить одну и ту же информацию несколько раз, особенно когда разные формы этих данных явно связаны между собой, но чтобы понять, как это сделать, нужен компьютер! Мы видели это на примере вышеупомянутого инструмента для создания прототипов. Если вы рассматриваете процесс разработки как процесс выражения творческого потенциала на постепенных этапах в контексте приложения, то вы хотите зафиксировать это в машине, и не просто как текст, а в форме, которая фиксирует смысл, чтобы он мог быть преобразованными в различные форматы, требуемые другим программным обеспечением, по запросу. Затем эту информацию можно преобразовать в другие формы, добавить, представить в различных форматах отображения и т.д.

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

По нашему опыту, структурный анализ - естественный первый шаг для FBP-разработки, поэтому инструменты CASE, которые поддерживают диаграммы структурного анализа и имеют открытую архитектуру, являются естественными партнерами FBP. Фактически, FBP - это единственный подход, который позволяет осуществлять структурный анализ на всем пути разработки - при обычном программировании вы не можете преобразовать проект в структуру исполняемой программы. Существует пропасть, которую никто не смог преодолеть на практике, хотя есть некоторые теоретические подходы, такие как "инверсия Джексона", которые частично оказались успешными. В FBP вы можете просто добавлять информацию в проект и использовать структурный анализ, пока у вас не будет работающей программы. Вероятно, наиболее важный момент - нужно различать компоненты кода и процессы (инстансы компонентов), а некоторые инструменты структурного анализа не проводят четкого различия между этими двумя концепциями. Как мы увидим в следующей главе, FBP-сеть состоит из нескольких взаимодействующих процессов, но инструмент, который рассматривается в первую очередь для построения диаграмм, прост, если предположить, что все блоки на диаграмме являются уникальными, разными программами. Необходимость выполнить изображение налагает дисциплину на процесс проектирования и дизайнера, а это означает, что эти недоразумения должны быть устранены. На самом деле мы разработали код для ПК, чтобы преобразовать схему одного из популярных инструментов CASE в спецификацию сети DFDM, которая успешно использовалась для нескольких проектов.

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

Подводя итог, можно сказать, что HLL, 4GL и CASE - всё это шаги на пути к тому месту, где мы хотим быть, и у всех есть уроки, которым можно нас научить, и возможности, которые определенно являются частью ответа. Что так захватывает в FBP, так это то, что оно позволяет взять лучшие качества всех подходов, которые использовались ранее, и объединить их в большее целое, которое больше, чем сумма его частей.