На протяжении 60-х годов запросы на разработку программного обеспечения быстро возросли и программы становились очень большими. Руководители начали понимать, что создание программного обеспечения – гораздо более сложная задача, чем они себе представляли. Это привело к тому, что было разработано структурное – модульное программирование. С развитием структурного программирования следующим достижением были процедуры и функции. Если задача выполняется несколько раз, то ее можно объявить, как функцию или процедуру и в выполнении программы просто вызывать ее. Общий код программы в данном случае становится меньше. Функции позволяют создавать модульные программы, в основе которых лежит представление программы в виде иерархической структуры блоков. Класс - это структура, которая имеет свои переменные и функции, которые работают с этими переменными. Это было очень большое достижение в области программирования. Программирование можно было разбить на классы и тестировать не всю программу, состоящую из строк кода, а разбить программу на группу классов, и тестировать каждый класс. Это существенно облегчило написание программного продукта.
Следующий шаг был сделан в 1954-м году, когда на Западе был создан первый язык программирования высокого уровня – Фортран. Языки высокого уровня имитируют естественные языки, используя некоторые слова разговорного языка и общепринятые математические символы. Эти языки более удобны для человека, с помощью них можно писать программы до нескольких тысяч строк длиной. Однако легко понимаемый в коротких программах, этот язык становился нечитаемым и трудно управляемым, когда дело касалось больших программ. Решение этой проблемы пришло после изобретения на Западе языков структурного программирования, таких как Алгол (1958), Паскаль (1970), Си (1972). С этого момента начался языковый бум. Языки программирования стали появляться один за другим. Так появились С+, ADA, FoxPro, Basic, Pascal и др. На сегодняшний день существует тысячи языков программирования. Из них популярность и известность получили только некоторые. Они отличаются простотой, быстротой, гибкостью и другими свойствами, удобными в некоторой определенной области использования.
Споры программистов перенеслись в другую плоскость – какой язык лучше. Большее предпочтение отдавалось универсальным языкам программирования, способным предоставлять эффективный инструментарий для решения разнообразных вычислительных задач. Все современные реализации широко распространенных языков обладают сходными характеристиками: начиная от скорости написания программ и кончая производительностью полученного кода.
Теперь приверженцы языка ассемблер утверждали, что их код самый быстрый, а любители языков высокого уровня утверждали, что они напишут программу быстрей, чем самый лучший программист на языке ассемблер. Однако программы на языках высокого уровня занимали больший объем памяти и работали медленнее. В вычислительных задачах победила в основном скорость разработки и "удобство" языка программирования для определенного класса задач.
Ассемблер не ушел из практики, когда необходимо было создавать эффективные по объему программы реального времени высокой производительности и занимающие минимальный объем памяти (см. главу 4). В 60-е – 70-е годы большинство программных продуктов в оборонной промышленности для мобильных и бортовых ЭВМ создавались на ассемблерах, адаптированных на архитектуру соответствующих машин. Только в 80-е годы в связи с ростом ресурсов специализированных машин начали использоваться алгоритмические языки высокого уровня, несмотря на возможное расширение программ при трансляции, по сравнению с программами, разработанными на ассемблере.
С середины 50-х годов во всех странах, производивших вычислительную технику, начался бурный процесс "языкотворчества" - создание нескольких сотен проблемно-ориентированных языков [1, 4]. Многим программистам казалось, что небольшие улучшения языков программирования способны радикально повлиять на разработку и качество программ, на использование скудных ресурсов ЭВМ. Однако это требовало создания соответствующих трансляторов и средств отладки, вследствие чего энтузиазм языкотворчества постепенно угас. Сложной задачей для системных программистов того времени было создание трансляторов для конкретных типов машин. Создание каждого транслятора с машинно-независимого языка программирования считалось крупным научным и практическим достижением. Большое число различных типов машин и различных языков требовало трудоемкой работы высококвалифицированных программистов и математиков по разработке трансляторов. Соответственно, возникла необходимость создания небольшого числа стандартизированных языков и программно-преемственных семейств вычислительных машин. Это потребовало глубоких теоретических исследование в теории алгоритмов, схем программ, теории формальных грамматик.
В СССР в 60-е годы был создан алгоритмический язык РЕФАЛ, в основе которого лежала теоретическая модель процесса, реализуемого нормальными алгоритмами Маркова. Его использование в нашей стране позволило создать ряд оригинальных программных продуктов, не имевших аналогов за рубежом. Однако РЕФАЛ испытал судьбу многих отечественных находок. Сходная судьба была у языков программирования семейства Аналитик, созданных в Институте кибернетики АН УССР для ЭВМ серии "МИР". Эти машины, по существу, были первыми персональными ЭВМ (к сожалению, тогдашняя элементная база не позволила свести их габариты к настольным). Однако, несмотря на передовые принципы, заложенные в структуру и функции языков семейства Аналитик, они также не стали достоянием мирового сообщества программистов, хотя иностранные эксперты достаточно высоко оценивали достижения программирования в СССР [4].
Исследования в области параллельного программирования в СССР начались в середине 60-х годов, когда в Институте математики СО АН СССР (Новосибирск) и в Московском энергетическом институте возникли первые коллективы, заинтересовавшиеся теорией параллельных процессов в вычислительных системах, состоящих из однородных или неоднородных машин [4]. Первые монографии по теории вычислительных систем и параллельных вычислений вышли в нашей стране с большим опережением аналогичных изданий за рубежом. Отечественные специалисты первыми в мировой науке дали постановку и предложили решения таких задач, как сегментация алгоритмов и программ, планирование выполнения больших программ на вычислительных системах, динамическое диспетчерование потока программ и сегментов программ, асинхронная организация протекания процессов. В это время было предложено несколько оригинальных моделей для параллельных вычислений, заново открытых потом в США и других странах.
В 1953-х годах Л.В. Канторович разработал технологию крупноблочного программирования, которая давала обозримое описание крупных программ и обеспечивала формализацию, достаточную для исследования синтаксических структур программ и создания программирующих программ [4]. Идеи, высказанные в этих работах, предшествовали развитию программной инженерии. Работа школы протекала весьма активно в 1950 – 60-е годы. Характерной особенностью крупноблочных систем являлось то, что они оперировали не с индивидуальными числами и символами, а с величинами – укрупненными агрегированными информационными объектами. Такие укрупненные структуры данных (матрицы, векторы, последовательности, деревья, схемы и т. д.) выступали как целое в вычислительных планах; стандартные способы обработки отдельных компонентов выполнялись автоматически на нижних уровнях. Это вносило иерархическую структуру в языки программирования, освобождая верхние уровни от ненужной детализации. Существенно, что вычислительный процесс мыслился при этом также "объемным", протекающим одновременно, либо попеременно на каждом из этих уровней. Громоздкие и трудоемкие вычисления часто чрезвычайно упрощались при переходе на другой уровень. Представлялось, что в разумной стратегии переходов с одного уровня на другой кроется значительный резерв для повышения экономики вычислений. На этой же уровневой основе была создана оригинальная теория и методология трансляции, гибко сочетающая компиляцию и интерпретацию.
Ряд объективных обстоятельств способствовал тому, что до середины 60-х годов программирование в СССР развивалось до некоторой степени автономно от зарубежного [1, 3, 4]. К этим обстоятельствам относились:
• более позднее начало массового производства электронной вычислительной техники (примерный сдвиг – 5 лет);
• меньшее количество доступных вычислительных ресурсов, приведшее к не столь широкому размаху работ, как в США или в Англии;
• практическое отсутствие импорта вычислительных машин и технологий;
• языковый барьер и сравнительно менее интенсивные личные контакты специалистов (в частности, вследствие секретности);
• некоторые общие отличия в организации и стиле научных исследований и производства.
Заметное влияние на общее развитие программирования в мире оказали работы Ю.И. Янова, приведшие к созданию теории схем программ, и некоторые работы по оптимизации трансляции. Существенный вклад в мировую тенденцию внесло широкое распространение Алгола-60 в СССР. Большая часть результатов представляла независимые, индивидуальные, практические разработки, без которых невозможно было полноценное развитие отечественного программирования.
Одним из факторов, сузившим фронт работ по автоматизации программирования в несекретных отраслях народного хозяйства, в это время было преобладание научных применений универсальных ЭВМ. Большая часть программистов в СССР была математиками с университетским образованием. Почти все успешные "художественные" экспериментальные и вычислительные программы кое-как переделывались в программный продукт, и это "кое-как" иногда мешало эксперименту и не давало должного эффекта при применении продукта. При всех положительных сторонах этого обстоятельства потребовалось длительное время, пока была осознана и реализована необходимость сбалансировать эту сторону вузовского образования с воспитанием способности к инженерному стилю работы, столь необходимому в системном программировании для создания крупных программных продуктов реального времени (см. главу 4).
В середине 50-х годов появились небольшие по численности группы математиков, привлеченных к разработкам проектов вычислительных машин, проводившихся в небольшом числе проектных организаций и институтов в Москве, Ленинграде, Киеве, Минске, Пензе. Каждая вновь разрабатываемая машина, прежде всего, требовала создания для нее операционной системы и программ вычисления элементарных функций. При этом необходимо было добиваться предельной эффективности таких вычисления на данной конкретной архитектуре и ресурсах ЭВМ. Это требовало от математиков высокого уровня понимания деталей логики работы процессора. Возможно, что именно это явилось отличительной чертой отечественных школ программирования, чертой теснейшей их связи с инженерными разработками, которая определила в дальнейшем, как достоинства, так и недостатки в работе этих школ.
Теоретические исследования методов программирования для ЭВМ в 1950-е – 60-е годы, активно проводились в Московском, Ленинградском и Киевском университетах, в Институте автоматики и телемеханики АН СССР, в Вычислительном центре АН СССР [1, 4]. В 1950 году в ИТМ и ВТ начал работать первый постоянный семинар по программированию, которым руководил Л.А. Люстерник, в МГУ в 1952-м году была основана кафедра вычислительной математики (ее возглавил С.Л. Соболев). В 1953-м году в Математическом институте АН СССР был создан отдел программирования во главе с А.А. Ляпуновым, а в 1955-м году был основан Вычислительный центр МГУ, специализировавшийся на разработке и применении вычислительных методов для решения научных и прикладных задач.
В 1952-м – 53-м годах А.А. Ляпуновым был предложен операторный метод для описания программ. Практически впервые был создан способ представления программ на обозримом уровне. Вместо неэффективного для человека написания программ в машинных кодах было предложено формализованное представление программ на языке высокого уровня. Особенно важным было то, что операторный метод позволил подготовить теорию синтаксических структур программ. В 1953-м году А.А. Ляпунов сформулировал постановку задачи автоматизации программирования. Эта оригинальная постановка была успешно использована в первых отечественных трансляторах, называвшихся тогда программирующими программами (ПП). Летом 1954-го года появилась программирующая программа ПП-1, разработанная в отделе прикладной математики Института математики АН СССР, а в 1955-м году – ее улучшенный вариант ПП-2. К середине 50 – х годов у ведущих специалистов в области вычислительной техники сформировалось представление о путях развития отечественной информатики и программирования.
В середине 1957-го года, Виктор Михайлович Глушков, определил направления стратегических исследований в области информатики [3]. По его мнению, основой прогресса развития вычислительных машин должна была стать теория их работы, разработка методов автоматизации проектирования ЭВМ и автоматизации программирования. Он подчеркивал важную роль исследований в области теории алгоритмов и теории конечных детерминированных и стохастических автоматов, принципиальное значение разработки методов символьных преобразований на ЭВМ. Отмечалась центральная роль, которую играет задача оптимизации размера при трансляции программ (особенно для управляющих машин), а также указывалось на обратное влияние развития вычислительных машин на дальнейшие работы в области вычислительной математики. В конце 1959-го года в Москве, в МГУ состоялось "Всесоюзное совещание по вычислительной математике и вычислительной технике". Это было большое научное собрание с почти 2000 участников и 217 докладами, прочитанными на четырех секциях.
Постепенно складывалась концепция системного математического (программного) обеспечения ЭВМ – интегрированной и удобной в работе системы различных средств автоматизации программирования (библиотеки, трансляторы, средства отладки), сопряженных с определенной дисциплиной реализации задач на машине [5]. Проблеме математического обеспечения ЭВМ было много препятствий научно-технического и организационного характера, одно из которых – слабая разработанность концепции программного продукта и его производства. Для М-20 в то время таким средством для вычислений была библиотека стандартных подпрограмм. Идея превращения библиотеки в переносимый и общий программный продукт стала для М.Р. Шура-Буры на некоторое время главной задачей, на решении которой со временем сформировались более общие взгляды на системное программное обеспечение. Необходимо было найти некоторый объект конструирования и научной работы, который одновременно решал бы задачу унификации математического обеспечения, мог бы быть эффективным средством автоматизации программирования и выдвигал бы новую научную проблематику. Таким корневым объектом в стране стал Алгол-60.
В начале 60-х годов был опубликован алгоритмический язык Алгол-60, рекомендованный в качестве международного стандарта для публикаций вычислительных алгоритмов. В нашей стране Алгол-60 был принят в качестве государственного стандарта. Использование других языков для программирования вычислительных задач не рекомендовалось и это касалось даже широко применявшегося за рубежом более простого языка Фортран. После этого в стране началась активная разработка трансляторов с Алгола– 60 для нескольких типов машин. Попытки создать транслятор с полного языка Алгол-60 за рубежом не удались. В ИПМ такой транслятор был создан для машины "Стрела", а затем для машины М-20, что явилось достижением мирового уровня.
В то же время стала совершенно очевидной общенаучная ценность этого документа, которая требовала его широкого распространения. Ситуация весной 1960-го года оказалась весьма благоприятной для принятия Алгола-60 в качестве единого языка программирования научных и инженерных применений ЭВМ. В июне в Вычислительном центре АН СССР координационное совещание по вопросам реализации Алгола-60. На фоне общей и во многом разнонаправленной активности выделились три проекта реализации языка для М-20, получившие, соответственно, названия TA-1, ТА-2 и Альфа. Начавшись как три независимые и подчас конкурирующие разработки, они в процессе развития приобрели взаимодополняющие свойства, решив удовлетворительно проблему снабжения М-20 трансляторами с Алгола-60.
В декабре 1960-го года в МГУ состоялась рабочая конференция "Построение программирующих программ на основе языка Алгол-60" [1, 4]. К этому времени у разработчиков уже сложились общие подходы к реализации языка и выбору схем трансляции. В TA-1 благодаря отказу от возможной рекурсивности процедур и ряду других ограничений, была выбрана компактная и быстрая схема трансляции без оптимизации. Главной задачей ТА-2 стала реализация практически полного языка без существенной потери в качестве реализации. В разработке системы Альфа (Андрей Петрович Ершов) было поставлено в качестве главной цели обеспечение высокого качества (по объему рабочих программ) с сохранением приемлемой скорости трансляции. Употребление универсального языка программирования снимало задачу перевода программ с одной машины на другую, дало возможность сокращать дублирование работ по составлению программ для различных типов машин и существенно облегчило обмен информацией между отдельными группами специалистов, работающих в области программирования. В докладе разработчиков системы Альфа был показан классический прецедент просчета в определении плановых экономических показателей и трудоемкости больших программных проектов с универсальным коэффициентом недооценки трудоемкости в 2–3 раза, подтвержденном впоследствии многими проектами. Авторы клали на разработку системы 15 человеко-лет для построения 15000 команд, затратив на самом деле свыше 30 человеко-лет и соорудив систему в 45000 команд (см. главу 5).
Библиотека программ ИС-2, трансляторы TA-1 и ТА-2 стали первыми образцами программных продуктов, которые поставлялись вместе с оборудованием машин заводом-изготовителем, образуя интегрированную систему поддержки программирования. В трансляторе Альфа были систематически учтены очень ограниченные ресурсы технологической ЭВМ:
• функция расстановки, для ускорения работы транслятора, в частности, для экономии совпадающих выражений;
• многовариантная система программирования процедур и циклов, основанная на анализе структуры программы;
• реализована глобальная экономия памяти;
• осуществлен ряд оптимизационных преобразований на уровне промежуточного языка, в частности, объединение циклов с одинаковыми заголовками и чистка циклов.