Основы разработки программного обеспечения на примере языка С

Предисловие

Разбить на страницы
Показывать лекцию целиком

В любой иерархической системе каждый служащий стремится достичь своего уровня некомпетентности.

Следствия:

1. С течением времени каждая должность будет занята служащим, который некомпетентен в выполнении своих обязанностей.

2. Работа выполняется теми служащими, которые еще не достигли своего уровня некомпетентности.

Краткая история развития программирования

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

Все команды были реализованы аппаратно, а программа представляла собой последовательность команд и данных в числовом виде. Во время своего выполнения она вместе с обрабатываемыми данными хранилась в памяти вычислительной машины (рис. 0.1). Команды последовательно выбирались процессором из памяти. Вычислительные команды выполнялись в самом процессоре. Для этого из памяти выбирались данные по адресам, прочитанным из исполняемой команды. Результаты вычислений записывались в память.

Если очередная выбранная команда требовала обмена (ввода или вывода) данных, то она передавалась на исполнение в процессор ввода/вывода. Последний активизировал соответствующее внешнее устройство (ВНУ) и обеспечивал пересылку данных либо из памяти машины во внешнее устройство, например для печати, либо от внешнего устройства в память машины.

(рис 0.1) Структура взаимодействия узлов вычислительной машины

Подобные процессоры ввода/вывода иногда называли каналами обмена. Различались селекторные каналы, которые, начав обмен с одним ВНУ, не прекращали его до полного завершения, и мультиплексные каналы. Последние могли параллельно поддерживать обмен с несколькими внешними устройствами. Как правило, это были относительно медленные устройства, которые уступали по быстродействию каналу и памяти в десятки раз.

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

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

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

(рис 0.2) Структура с общей шиной

В "узких" шинах и адрес, и сами данные последовательно передавались по одним и тем же проводникам. Поэтому возможна была ситуация, при которой для выборки одного 8-разрядного символа из оперативной памяти необходимо было затратить три такта обмена: два на передачу 16-разрядного адреса символа и еще один на получение самого символа.

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

Некоторые команды процессора вызывали изменение последовательной выборки команд. В результате их выполнения вырабатывался адрес очередной выполняемой команды. Обычно значение этого адреса зависело от ранее вычисленных в процессоре значений данных. Например, если результат вычислений был нулевой, то вместо выборки следующей по порядку команды процессор переходил к выполнению команды по заданному в ней адресу.

Такие команды часто называли командами условного перехода. Они определяли не только адрес следующей выполняемой команды, но и условие, при котором этот адрес должен был быть использован, например переход по нулевому значению, переход по отрицательному значению, переход по переполнению и т.п.

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

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

Изображение машинных команд в виде условных сокращений слов или символов (СЛ - сложить, ВЫЧ - вычесть, УМ - умножить и т.д.) стало первым шагом от кодов машины в сторону человека, а полученный язык кодирования программ называли ассемблером или мнемокодом. Программы стали более читабельными, но для перевода из мнемонического описания программы в машинные коды понадобился транслятор. Язык ассемблера теперь существует практически для любой машины, и на нем до сих пор пишут системные программы, требующие работы со специфичными аппаратными возможностями вычислителя, а также в случае серьезных ограничений на быстродействие и память при программировании микроконтроллеров.

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

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

Силами системных программистов были созданы специализированные редакторы текстов, предназначенные для подготовки программ, и трансляторы, переводящие исходные тексты программ в машинный код. Для поддержки коллективной модульной разработки были написаны программы-сборщики, которые позволяют объединить несколько независимо разработанных модулей в одну единую выполняемую программу. Наконец, были созданы управляющие программы - операционные системы, задача которых заключается в организации совместного выполнения нескольких программ на одной вычислительной установке, перераспределяя вычислительные ресурсы между ними по мере необходимости.

Языки высокого уровня

Следующим шагом в развитии средств общения компьютера и человека стало появление языков высокого уровня. Так как перед выполнением программы ее все равно было необходимо транслировать, то решили изменить сам язык написания программы. В него добавили новые команды, не имеющие соответствующих машинных аналогов, но реализуемые набором аппаратных команд. Это упростило понимание программы и облегчило ее составление. Сами языки высокого уровня по сравнению с ассемблером стали обладать определенными свойствами:

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

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

    С течением времени был создан целый ряд универсальных языков программирования (FORTRAN, Pascal, Си, Modula-2, Ada), многие из которых являлись предпочтительнее один другого в зависимости от класса решаемых на них задач. Параллельно с этим появились и ярко выраженные проблемно-ориентированные языки, такие как COBOL, GPSS, Simula, Snobol, ориентированные на достаточно узкие классы задач.

    Языки высокого уровня позволили достичь определенной степени абстракции проблемы при составлении программы и позволили представить ее в достаточно наглядной форме. Это привело к тому, что языки программирования стали не только языками общения человека с машиной, но и языками общения человека с человеком. Программисту стало проще показать программу на достаточно формализованном языке, чем объяснять алгоритм "на пальцах". И этим свойством начали активно пользоваться.

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

    Таким образом, современный язык высокого уровня выполняет несколько функций одновременно:

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

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

    Программная инженерия

    Сильное влияние на развитие технологии программирования оказал Э. Дейкстра (Edsger W. Dijkstra) [1], предложивший метод структурного программирования. Одновременно с публикациями его идей стали достоянием гласности работы Ч. Хоара, показавшего, что любая программа может быть математически (формально) проанализирована, и это позволяет избежать части ошибок при использовании соответствующих формальных приемов проверки программ и алгоритмов.

    Дейкстра же заметил, что язык программирования влияет на способ мышления [2]. Освоение алгоритмических языков программирования заставляет мыслить формальными категориями, "прививает" определенную логику, которая несколько отличается от логики написания программ на машинно-ориентированном языке. Программирование - это конструирование достаточно сложных объектов с большим количеством связей [3], и чтобы конструировать, следует последовательно использовать элементарные принципы конструирования, начиная от проектирования функций, модулей, абстрактных типов данных и заканчивая построением сложной системы.

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

    Кроме написания работающей программы существует проблема оценки степени соответствия этой программы предъявляемым к ней требованиям. Тут необходимо проводить тестирование, которое не всегда будет являться полным, но в конечном итоге должно привести к появлению качественного продукта, т.е. программы, соответствующей ожиданиям.

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

    Примером такого документа может служить ГОСТ Р 51904-2002 "Программное обеспечение встроенных систем. Общие требования к разработке и документированию". Во многих случаях он требует выполнения в процессе тестирования каждой команды машинного программного кода. Это позволяет убедиться не только в том, что программа делает то, что нужно, но и быть уверенным, что она не делает того, что не предусмотрено требованиями.

    Системы реального времени

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

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

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

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

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

    ТЕРМИНЫ И СОКРАЩЕНИЯ

    AK AcKnowledgement

    DDD Detailed Design Description

    ETX End of TeXt

    FA Functional Area

    HRD Hardware Requirements Document

    NAK No AcKnowledgement

    ORD Organizational Requirements Document

    RTS Request To Send

    SOW Statement Of Work

    SRD Software Requirements Document

    STX Start of TeXt

    SUT Software Under Test

    SYS SYStem requirements

    АТД Абстрактный тип данных

    ВНУ Внешнее устройство

    ЖЦ Жизненный цикл

    ОС Операционная система

    ПО Программное обеспечение

    РБНФ Расширенная Бэкуса-Наура форма

    ЯВУ Язык высокого уровня

    ЯП Язык(и) программирования

    Страницы:

    В любой иерархической системе каждый служащий стремится достичь своего уровня некомпетентности.

    Следствия:

    1. С течением времени каждая должность будет занята служащим, который некомпетентен в выполнении своих обязанностей.

    2. Работа выполняется теми служащими, которые еще не достигли своего уровня некомпетентности.

    Краткая история развития программирования

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

    Все команды были реализованы аппаратно, а программа представляла собой последовательность команд и данных в числовом виде. Во время своего выполнения она вместе с обрабатываемыми данными хранилась в памяти вычислительной машины (рис. 0.1). Команды последовательно выбирались процессором из памяти. Вычислительные команды выполнялись в самом процессоре. Для этого из памяти выбирались данные по адресам, прочитанным из исполняемой команды. Результаты вычислений записывались в память.

    Если очередная выбранная команда требовала обмена (ввода или вывода) данных, то она передавалась на исполнение в процессор ввода/вывода. Последний активизировал соответствующее внешнее устройство (ВНУ) и обеспечивал пересылку данных либо из памяти машины во внешнее устройство, например для печати, либо от внешнего устройства в память машины.

    (рис 0.1) Структура взаимодействия узлов вычислительной машины

    Подобные процессоры ввода/вывода иногда называли каналами обмена. Различались селекторные каналы, которые, начав обмен с одним ВНУ, не прекращали его до полного завершения, и мультиплексные каналы. Последние могли параллельно поддерживать обмен с несколькими внешними устройствами. Как правило, это были относительно медленные устройства, которые уступали по быстродействию каналу и памяти в десятки раз.

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

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

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

    (рис 0.2) Структура с общей шиной

    В "узких" шинах и адрес, и сами данные последовательно передавались по одним и тем же проводникам. Поэтому возможна была ситуация, при которой для выборки одного 8-разрядного символа из оперативной памяти необходимо было затратить три такта обмена: два на передачу 16-разрядного адреса символа и еще один на получение самого символа.

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

    Некоторые команды процессора вызывали изменение последовательной выборки команд. В результате их выполнения вырабатывался адрес очередной выполняемой команды. Обычно значение этого адреса зависело от ранее вычисленных в процессоре значений данных. Например, если результат вычислений был нулевой, то вместо выборки следующей по порядку команды процессор переходил к выполнению команды по заданному в ней адресу.

    Такие команды часто называли командами условного перехода. Они определяли не только адрес следующей выполняемой команды, но и условие, при котором этот адрес должен был быть использован, например переход по нулевому значению, переход по отрицательному значению, переход по переполнению и т.п.

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

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

    Изображение машинных команд в виде условных сокращений слов или символов (СЛ - сложить, ВЫЧ - вычесть, УМ - умножить и т.д.) стало первым шагом от кодов машины в сторону человека, а полученный язык кодирования программ называли ассемблером или мнемокодом. Программы стали более читабельными, но для перевода из мнемонического описания программы в машинные коды понадобился транслятор. Язык ассемблера теперь существует практически для любой машины, и на нем до сих пор пишут системные программы, требующие работы со специфичными аппаратными возможностями вычислителя, а также в случае серьезных ограничений на быстродействие и память при программировании микроконтроллеров.

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

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

    Силами системных программистов были созданы специализированные редакторы текстов, предназначенные для подготовки программ, и трансляторы, переводящие исходные тексты программ в машинный код. Для поддержки коллективной модульной разработки были написаны программы-сборщики, которые позволяют объединить несколько независимо разработанных модулей в одну единую выполняемую программу. Наконец, были созданы управляющие программы - операционные системы, задача которых заключается в организации совместного выполнения нескольких программ на одной вычислительной установке, перераспределяя вычислительные ресурсы между ними по мере необходимости.

    Языки высокого уровня

    Следующим шагом в развитии средств общения компьютера и человека стало появление языков высокого уровня. Так как перед выполнением программы ее все равно было необходимо транслировать, то решили изменить сам язык написания программы. В него добавили новые команды, не имеющие соответствующих машинных аналогов, но реализуемые набором аппаратных команд. Это упростило понимание программы и облегчило ее составление. Сами языки высокого уровня по сравнению с ассемблером стали обладать определенными свойствами:

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

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

    С течением времени был создан целый ряд универсальных языков программирования (FORTRAN, Pascal, Си, Modula-2, Ada), многие из которых являлись предпочтительнее один другого в зависимости от класса решаемых на них задач. Параллельно с этим появились и ярко выраженные проблемно-ориентированные языки, такие как COBOL, GPSS, Simula, Snobol, ориентированные на достаточно узкие классы задач.

    Языки высокого уровня позволили достичь определенной степени абстракции проблемы при составлении программы и позволили представить ее в достаточно наглядной форме. Это привело к тому, что языки программирования стали не только языками общения человека с машиной, но и языками общения человека с человеком. Программисту стало проще показать программу на достаточно формализованном языке, чем объяснять алгоритм "на пальцах". И этим свойством начали активно пользоваться.

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

    Таким образом, современный язык высокого уровня выполняет несколько функций одновременно:

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

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

    Программная инженерия

    Сильное влияние на развитие технологии программирования оказал Э. Дейкстра (Edsger W. Dijkstra) [1], предложивший метод структурного программирования. Одновременно с публикациями его идей стали достоянием гласности работы Ч. Хоара, показавшего, что любая программа может быть математически (формально) проанализирована, и это позволяет избежать части ошибок при использовании соответствующих формальных приемов проверки программ и алгоритмов.

    Дейкстра же заметил, что язык программирования влияет на способ мышления [2]. Освоение алгоритмических языков программирования заставляет мыслить формальными категориями, "прививает" определенную логику, которая несколько отличается от логики написания программ на машинно-ориентированном языке. Программирование - это конструирование достаточно сложных объектов с большим количеством связей [3], и чтобы конструировать, следует последовательно использовать элементарные принципы конструирования, начиная от проектирования функций, модулей, абстрактных типов данных и заканчивая построением сложной системы.

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

    Кроме написания работающей программы существует проблема оценки степени соответствия этой программы предъявляемым к ней требованиям. Тут необходимо проводить тестирование, которое не всегда будет являться полным, но в конечном итоге должно привести к появлению качественного продукта, т.е. программы, соответствующей ожиданиям.

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

    Примером такого документа может служить ГОСТ Р 51904-2002 "Программное обеспечение встроенных систем. Общие требования к разработке и документированию". Во многих случаях он требует выполнения в процессе тестирования каждой команды машинного программного кода. Это позволяет убедиться не только в том, что программа делает то, что нужно, но и быть уверенным, что она не делает того, что не предусмотрено требованиями.

    Системы реального времени

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

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

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

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

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

    ТЕРМИНЫ И СОКРАЩЕНИЯ

    AK AcKnowledgement

    DDD Detailed Design Description

    ETX End of TeXt

    FA Functional Area

    HRD Hardware Requirements Document

    NAK No AcKnowledgement

    ORD Organizational Requirements Document

    RTS Request To Send

    SOW Statement Of Work

    SRD Software Requirements Document

    STX Start of TeXt

    SUT Software Under Test

    SYS SYStem requirements

    АТД Абстрактный тип данных

    ВНУ Внешнее устройство

    ЖЦ Жизненный цикл

    ОС Операционная система

    ПО Программное обеспечение

    РБНФ Расширенная Бэкуса-Наура форма

    ЯВУ Язык высокого уровня

    ЯП Язык(и) программирования

    Вернуться к учебному плану