Целью программирования является описание процессов обработки данных. Для того чтобы по заданному описанию требуемый процесс выполнялся автоматически на компьютере, необходимо, чтобы это описание было формализованным. Такое описание называется программой. С другой стороны, программа должна быть понятной и человеку, так как и при разработке программ, и при их использовании часто приходится выяснять, какой именно процесс она реализует. Поэтому программа составляется на удобном для человека формализованном языке программирования, с которого она автоматически переводится на язык соответствующего компьютера с помощью другой программы, называемой транслятором.
Прежде чем составить программу на языке программирования, приходится проделывать большую подготовительную работу по уточнению постановки задачи, выбору метода ее решения, выяснению специфики применения требуемой программы, прояснению общей организации разрабатываемой программы и многое другое. Использование этой информации может существенно упростить задачу понимания программы человеком, поэтому
весьма полезно ее как-то фиксировать в виде отдельных документов (часто неформализованных, рассчитанных только для восприятия человеком).
Обычно программы разрабатываются в расчете на то, чтобы ими могли пользоваться люди, не участвующие в их разработке (пользователи). Для освоения программы пользователем помимо ее текста требуется определенная дополнительная документация. Программа или логически связанная совокупность программ на носителях данных, снабженная программной документацией, называется программным средством (ПС). Программа позволяет осуществлять некоторую автоматическую обработку данных на компьютере. Программная документация позволяет понять, какие функции выполняет та или иная программа, как подготовить исходные данные, как запустить программу и как интерпретировать получаемые результаты. Кроме того, программная документация помогает разобраться в самой программе, что необходимо, например, при ее модификации.
ПС называют надежным, если оно способно безотказно выполнять определенные для него функции при заданных условиях в течение заданного периода времени с достаточно большой вероятностью. При оценке степени надежности ПС следует учитывать последствия каждого отказа. Поэтому для оценки надежности ПС иногда используют дополнительные показатели, учитывающие стоимость (вред) для пользователя каждого отказа.
Технологию программирования (ТП) следует понимать как технологию создания надежных программных средств, включая в нее все процессы, начиная с момента зарождения идеи этого средства. В настоящее время большинство из этих процессов базируется на использовании компьютеров. В этом случае будем говорить о компьютерной технологии программирования.
Роль ТП менялась на разных этапах развития программирования. По мере повышения мощности компьютеров и развития средств и методологии программирования росла и сложность решаемых на компьютерах задач, что привело к повышенному вниманию к технологии программирования. Резкое
удешевление стоимости компьютеров привело к широкому внедрению компьютеров практически во все сферы человеческой деятельности. Человеческий фактор стал играть в ТП решающую роль. Сформировалось достаточно глубокое понятие качества ПС, в котором упор делается не столько на его эффективность, сколько на удобство работы с ним для пользователей и его надежность. Широкое использование компьютерных сетей привело к интенсивному развитию распределенных вычислений, дистанционного доступа к информации и электронного способа обмена сообщениями между людьми. Компьютерная техника из средства решения отдельных задач все более превращается в средство информационного моделирования реального мира, способное быстро и качественно отвечать людям на интересующие их вопросы. Начинается этап глубокой и полной информатизации человеческого общества. Все это ставит перед технологией программирования новые и достаточно трудные проблемы.
Развитие технологии программирования следует продемонстрировать следующим образом.
В 1950-е годы возможности компьютеров (первого поколения) были весьма ограниченными, и программирование велось в основном в машинном коде. Решались главным образом научно-технические задачи (расчет по формулам). Задание на программирование уже содержало, как правило, достаточно точную постановку задачи. Минимальная документация оформлялась уже после того, как программа начинала работать. Однако именно в этот период родилась фундаментальная для технологии программирования концепция модульного программирования. Появились первые языки программирования высокого уровня, из которых только ФОРТРАН пробился для использования в следующие десятилетия.
В 1960-е годы наблюдалось бурное развитие и широкое использование языков программирования высокого уровня (ЯПВУ: АЛГОЛ 60. ФОРТРАН, КОБОЛ и др.). Роль ЯПВУ в ТП явно преувеличивалась. Эти языки не могут
решать все проблемы, возникающие при разработке больших программ. В результате повышения мощности компьютеров и накопления опыта программирования на ЯПВУ быстро росла сложность решаемых на компьютерах задач. Ввиду этого выявилась ограниченность языков, в которых отсутствовала возможность модульной организации программ. Кроме того, было понято, что важно не только то, на каком языке мы программируем, но и то, как мы программируем. Это было уже началом серьезных размышлений над методологией и технологией программирования. Появление в компьютерах второго поколения прерываний привело к развитию мультипрограммирования и созданию больших программных систем.
В 1970-е годы получили широкое распространение информационные системы и базы данных. Интенсивно развивалась технология программирования: обоснование и широкое внедрение нисходящей разработки и структурного программирования, развитие абстрактных типов данных и модульного программирования, исследование проблем обеспечения надежности и мобильности ПС, создание методики управления коллективной разработкой ПС, появление инструментальных программных средств поддержки программирования.
1980-е годы характеризуются широким внедрением персональных компьютеров во все сферы человеческой деятельности и тем самым созданием обширного и разнообразного контингента пользователей ПС. Это привело к бурному развитию пользовательских интерфейсов и созданию четкой концепции качества ПС. Появляются языки программирования (например, Ада), учитывающие требования технологии программирования. Развиваются методы и языки спецификации ПС. Передовые позиции начинает занимать объектно-ориентированный подход к разработке ПС. Создаются различные инструментальные среды разработки и сопровождения ПС. Развивается концепция компьютерных сетей.
1990-е годы знаменательны широким охватом всего человеческого общества
международной компьютерной сетью, персональные компьютеры стали подключаться к ней как терминалы. Это поставило ряд проблем регулирования доступа к информации в компьютерных сетях (как технологического, так и юридического и этического характера). Остро встала проблема защиты компьютерной информации, в том числе от компьютерных вирусов. Стали бурно развиваться CASE-технология разработки ПС (с интенсивным использованием возросших возможностей компьютеров) и связанные с ней формальные методы спецификации программ. Начался решающий этап полной информатизации общества.
Далее следует рассмотреть понятие жизненного цикла программного средства, состоящего из следующих этапов: формирование требований к ПС, проектирование и тестирование, эксплуатация и сопровождение, снятие с эксплуатации.
Необходимо рассмотреть раздел технологии программирования, относящийся к созданию алгоритмов и программ.
При создании программного продукта возникают следующие проблемы:
1) описать алгоритм (каким-либо способом);
2) написать программу, реализующую этот алгоритм;
3) отладить программу.
Решением первой проблемы занимается специалист предметной области, второй — программист и третьей — оба эти специалиста.
Основным принципом создания алгоритма является декомпозиция. Решение сложной задачи разделяется на решение более простых подзадач, которые в свою очередь разделяются на еще более простые и так далее до выделения задач, которые решаются простыми средствами.
В качестве примера декомпозиции рассмотрим решение следующей задачи. Даны списки сотрудников подразделения с указанием их заработанных плат. Требуется вывести фамилии и заработную плату сотрудников, у которых зарплата наиболее близка к средней зарплате по отделу.
Решение этой задачи можно представить в виде последовательного выполнения следующих подзадач.
1. Ввести число п сотрудников подразделения.
2. Заполнить массив т [п] фамилий сотрудников.
3. Заполнить массив т2[п] значений зарплат.
4. Найти сумму S элементов массива т2.
5. Найти среднюю по отделу зарплату SRZ по формуле SRZ = S/n.
6. Заполнить массив т3[п] меры близости зарплаты сотрудника к SRZ по формуле m3[i] = |m2[i] – SRZ|.
7. В массиве т3 найти минимальное значение min.
8. Вывод результата.
Для 1 < i < n, если m3[i] = min, то вывести m [i] и m2 [i].
Следует перечислить (и при необходимости прокомментировать) основные этапы разработки алгоритма решения конкретной задачи на компьютере, написания и отладки, реализующей этот алгоритм программы:
—формулировка задачи;
—математическая постановка задачи;
—определение и анализ метода решения поставленной задачи;
—составление внешней спецификации разрабатываемого алгоритма;
—конструирование и анализ правильности и эффективности алгоритмов на основе выбранных методов решения и выбранной внешней спецификации;
—кодирование программы на заданном языке программирования;
—составление тестов и отладка программы.
Для разработки прикладных программ необходимым условием является формулировка задачи, не допускающая неоднозначного толкования.
Обычно процесс формализации задачи сводится к постановке и получению ответов на ряд вопросов. Перечислим некоторые из них:
♦ Понятна ли терминология, используемая в предварительной формулировке?
♦ Что дано?
♦ Что нужно найти?
♦ Каких данных не хватает?
♦ Являются ли какие-то имеющиеся данные бесполезными?
♦ Какие сделаны допущения?
Возможны и другие вопросы в зависимости от конкретной задачи. После получения полных или частичных ответов на некоторые из вопросов иногда их приходится задавать снова. Результатом этого процесса является постановка задачи, которая включает:
—содержательную постановку задачи;
—исходные (входные) данные;
—требуемые (выходные) данные;
—описание зависимостей выходных данных от исходных;
—описание условий зависимости.
В качестве примера можно рассмотреть решение квадратного уравнения.
Содержательная постановка задачи. Фонд заработной платы на предприятии, численностью не менее Ро человек, составляет S рублей. В результате увеличения персонала на Р1 человек и роста средней заработной платы на Z1 рублей фонд заработной платы вырос на S1 рублей. Найти первоначальные численность персонала предприятия Р и среднюю заработную плату Z.
Дано: S,P1,Z1 S1, Ро.
Требуется: Р и Z.
Связь: S = PZ и S + S1 = (Р + P1)(Z + Z1).
При Ро < Р и Р — целое.
Выбор метода решения. Разработке любой программы присуще некоторое противоречие, а именно неформальный характер постановки задачи и формализованный объект разработки — программа. Цель этого этапа — определить теоретическую возможность решения задачи и при положительном исходе найти формальные правила получения решения.
Поскольку данный этап плохо формализуется, что связано, с одной стороны, с чрезвычайно широким разнообразием задач и методов их решения, а с другой — с существованием большого количества задач, решение которых возможно только эвристически (то есть с попыткой воспроизвести действия человека), метод решения может быть представлен в виде:
—системы формул;
—словесного изложения последовательности действий;
—их комбинации.
Основой метода решения описанной выше задачи является сведение ее к решению квадратного уравнения. Затем надо проверить выполнение условий Ро < Р и Р — целое.
Внешняя спецификация представляет собой руководство по использованию программы.
Внешние спецификации прикладных программ состоят из трех разделов:
—описание форм записи входных данных;
—описание форм выходных данных при правильных входных данных;
—описание реакции программы на аномалии во входных данных.
Под аномалиями будем понимать различные варианты нарушений данных или правил их записи.
Заметим, что составление внешней спецификации задачи тесно связано с выбором структуры данных и конкретными реализациями этих структур в используемом языке программирования. Для таких языков программирования, как Паскаль и Си, фундаментальной идеей при представлении данных является концепция типа данных.
Анализ алгоритма состоит из двух частей:
—анализа правильности;
—анализа эффективности.
Анализ правильности — это обязательная фаза в создании алгоритмов и программ. Под правильностью программы понимают соответствие программы
постановке задачи и внешней спецификации.
Существуют два способа анализа правильности алгоритмов и программ:
—проверка правильности алгоритмов на конкретных входных данных (тестирование);
—доказательство правильности работы алгоритма на всех допустимых данных (верификация).
Утверждения о правильности или неправильности алгоритмов и программ могут высказываться относительно соответствующих внешних спецификаций и постановок задач, решаемых этими алгоритмами и программами. Отсутствие строгих постановок или полных спецификаций не позволяет достоверно говорить о правильности алгоритмов или программ.
Проверка правильности алгоритма или программы тестированием состоит в следующем.
♦ Выбираются конкретные входные данные.
♦ Проводится трассировка алгоритма на выбранных входных данных.
♦ Полученные после трассировки результаты сверяются с внешней спецификацией и постановкой задачи.
Трассировка алгоритма или программы — это последовательная запись результатов последовательного выполнения шагов алгоритма при заданных входных данных. Отметим, что все среды программирования имеют средства трассировки программ.
Важнейшим вопросом при проверке алгоритмов и программ с помощью контрольных примеров является полнота тестирования.
Набор тестов называют функционально полным, если он проверяет все основные частные случаи постановки задач и все варианты реакций программ на аномалии.
При анализе эффективности алгоритма вначале выбираются критерии эффективности, основными из которых являются время выполнения и количество требуемой памяти. Отметим, что эти критерии, вообще говоря,
противоречивы. Важно различать практическую сложность, которая является мерой времени вычислений и объема памяти для конкретной модели вычислительной машины, и теоретическую сложность, которая не зависит от практических условий выполнения алгоритма и дает порядок величины сложности алгоритма.