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

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

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

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

Объектно-ориентированное программирование (ООП) определяется как технология создания сложного программного обеспечения, основанная на представлении программы в виде совокупности объектов, каждый из которых является экземпляром определенного типа (класса), а классы образуют иерархию с наследованием свойств. Взаимодействие программных объектов в такой системе осуществляется путем передачи сообщений.

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



Бурное развитие технологий программирования, основанных на объектном подходе, позволило решить многие проблемы. Так были созданы среды, поддерживающие визуальное программирование, например, Delphi, C++ Builder, Visual C++ и т. д. При использовании визуальной среды у программиста появляется возможность проектировать некоторую часть, например, интерфейсы будущего продукта, с применением визуальных средств добавления и настройки специальных библиотечных компонентов. Результатом визуального проектирования является заготовка будущей программы, в которую уже внесены соответствующие коды.

Можно дать обобщающее определение: объект ООП - это совокупность переменных состояния и связанных с ними методов (операций). Упомянутые методы определяют, как объект взаимодействует с окружающим миром.

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

Структурное программирование (СП) возникло как вариант решения проблемы уменьшения СЛОЖНОСТИ разработки программного обеспечения.

В начале эры программирования работа программиста ничем не регламентировалась. Решаемые задачи не отличались размахом и масштабностью, использовались в основном машинно-ориентированные языки и близкие к ним язык типа Ассемблера, разрабатываемые программы редко достигали значительных размеров, не ставились жесткие ограничения на время их разработки.

По мере развития программирования появились задачи, для решения которых определялись ограниченные сроки все более сложных задач с привлечением групп программистов. И как следствие, разработчики столкнулись с тем, что методы, пригодные для разработки небольших задач, не могут быть использованы при разработке больших проектов в силу сложности последних.

Таким образом, цель структурного программирования - повышение надежности программ, обеспечение сопровождения и модификации , облегчение и ускорение разработки.

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

Подход базируется на двух основных принципах:

· Последовательная декомпозиция алгоритма решения задачи сверху вниз.

· Использование структурного кодирования.

Напомним, что данная методология является важнейшим развитием императивной методологии.

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

Методы и концепции, лежащие в основе структурного программирования. Их три

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

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

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

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

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

Теорема о структурировании (Бёма-Джакопини (Boem-Jacopini)): Всякую правильную программу (т.е. программу с одним входом и одним выходом без зацикливаний и недостижимых веток) можно записать с использованием следующих логических структур - последовательность, выбора и повторение цикла

Следствие 1: Всякую программу можно привести к форме без оператора goto.

Следствие 2: Любой алгоритм можно реализовать в языке, основанном на трех управляющих конструкциях -последовательность, цикл, повторение.

Следствие 3: Сложность структурированных программ ограничена, даже в случае их неограниченного размера.

Структурное программирование- это не самоцель. Его основное назначение- это получение хорошей ("правильной") программы, однако даже в самой хорошей программе операторы перехода goto иногда нужны: например - выход из множества вложенных циклов.

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

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

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

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

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

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

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

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

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

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

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

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

Наиболее общая тактика программирования состоит в разложении процесса на отдельные действия:

  • - функционального описания на подфункции;
  • - соответствующие программы на отдельные инструкции.

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

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

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

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

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

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

Фундаментальным понятием и функциональным элементом технологии структурного программирования является - модуль.

Модуль - это подпрограмма, но оформленная в соответствии со следующими правилами:

  • 1. модуль должен иметь один вход и один выход и выполнять строго однозначную функцию, которая описывается простым распространенным предложением естественного (русского) языка или даже предложением без сказуемого;
  • 2. модуль должен обеспечивать компиляцию, независимую от других модулей, с «забыванием» всех внутренних значений модулей;
  • 3. модуль может вызывать другие модули по их именам;
  • 4. хороший модуль не использует глобальные переменные для общения с другим модулем, так как потом трудно отыскать модуль, который портит данные. При использовании глобальных переменных, нужно четко комментировать те модули, которые только читают, и те модули, которые могут менять данные;
  • 5. модуль кодируется только стандартными структурами и тщательно комментируется.

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

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

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

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

  • - модульность программ;
  • - структурное кодирование модулей программ;
  • - нисходящее проектирование рациональной иерархии модулей программ;
  • - нисходящая реализация программы с использованием заглушек;
  • - осуществление планирования на всех стадиях проекта;
  • - сквозной структурный контроль программных комплексов в целом и составляющих их модулей.

Модульность программ характеризуется тем, что вся программа состоит из модулей. Некоторые смысловые группы модулей сосредотачиваются в отдельных файлах. Например, в отдельных файлах (Unit) могут быть сосредоточены модули текстового редактора и модули иерархического меню.

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

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

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

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

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

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

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

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

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

Каждый новый вариант сравнивается с предшествующим вариантом по описанным здесь критериям. Генерация вариантов прекращается при невозможности дальнейших улучшений.

Фонд критериев оптимальности схем иерархии является необходимым подспорьем при оптимизации схем иерархии и состоит из следующих критериев:

  • - полнота выполнения специфицированных функций;
  • - возможность быстрого и дешевого пополнения новыми, ранее не специфицированными функциями;
  • - обозримость для проектировщика составных частей программы;
  • - максимальная независимость по данным отдельных частей программы;
  • - возможность связывания программы с обширной многоуровневой схемой иерархии конкретным редактором связей (линковщиком). Если начинается работа над новой программой, то очень полезно выполнить на эВМ ее модель в виде пустых заглушек модулей, которые не содержат никаких действий;
  • - достаточность оперативной памяти. Здесь рассматриваются варианты с описанием особенно структурированных статических и динамических переменных на разных уровнях схемы иерархии. Проверка удовлетворения данного критерия осуществляется расчетами с некоторыми машинными экспериментами;
  • - оценка влияния топологии схемы иерархии на скорость выполнения программы при использовании оверлеев (динамической загрузки программы) и механизма подкачки страниц при разработке программы, которая целиком не может быть размещена в оперативной памяти;
  • - отсутствие разных модулей, выполняющих похожие действия. В идеале - один и тот же модуль вызывается на разных уровня схемы иерархии;
  • - достижение при реализации программы такого сетевого графика работы коллектива программистов, который обеспечивает равномерную загрузку коллектива по ключевым датам проекта;
  • - всемерно сокращение затрат на тестирование уже собранного ядра программы по ключевым датам сетевого графика реализации. Характеризуется простотой используемых заглушек и качеством тестирования по всем вычислительным маршрутам модулей. Достигается первичной реализацией сверху вниз модулей ввода и вывода программы с отсрочкой реализации остальных ветвей схемы иерархии. Обычно затраты на тестирование составляют около 60% стоимости всего проекта. Хорошая схема иерархии сокращает затраты на тестирование по сравнению с первоначальным вариантом в 2-5 раз и более;
  • - использованием в данном проекте как можно большего числа разработанных в предшествующих проектах модулей и библиотек при минимальном объеме изготавливаемых заново частей;
  • - удачное распределение модулей по компилируемым файлам программы и библиотекам;
  • - накопление уже готовых модулей и библиотек модулей для использования их во всех новых разработках.

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

функциональном подходе к программированию.

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

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

Что касается первой реализации, то она появилась в 50-х годах XX столетия в форме языка LISP , о котором речь пойдет далее.

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

Функциональный подход породил целое семейство языков, родоначальником которых, как уже отмечалось, стал язык программирования LISP . Позднее, в 70-х годах, был разработан первоначальный вариант языка ML, который впоследствии развился, в частности, в SML , а также ряд других языков. Из них, пожалуй, самым "молодым" является созданный уже совсем недавно, в 90-х годах, язык Haskell.

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

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

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

Благодаря реализации механизма сопоставления с образцом , такие языки функционального программирования как ML и Haskell хорошо использовать для символьной обработки.

Естественно, языки функционального программирования не лишены и некоторых недостатков.

Часто к ним относят нелинейную структуру программы и относительно невысокую эффективность реализации . Однако первый недостаток достаточно субъективен, а второй успешно преодолен современными реализациями, в частности, рядом последних трансляторов языка SML , включая и компилятор для среды Microsoft . NET .

Для профессиональной разработки программного обеспечения на языках функционального программирования необходимо глубоко понимать природу функции . Исследованию закономерностей и особенностей природы функции в основном и посвящены лекции 2 – 12 данного курса.

Заметим, что под термином " функция " в математической формализации и программной реализации имеются в виду различные понятия.

Так, математической функцией f с областью определения A и областью значений B называется множество упорядоченных пар

таких, что если

b 1 = b 2 .

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

Для формализации понятия "

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

Характерными принципами структурного программирования являются:

· нисходящее программирование – способ разработки программ, при котором программи­рование ведется методом «сверху-вниз», от общего к деталям;

· модульное программирование , при котором относительно независимые подзадачи про­граммируются в виде отдельных программных модулей;

· использование при программировании трех структур управления (следование, выбор, повторение). Структура следование предполагает естественную последовательность выполнения операторов. Структура выбор задается схемой «если – то – иначе» (условный оператор if). Структуре повторения сопоставлен оператор цикла;

· отказ от безусловных передач управления и ограниченное использование глобальных переменных.

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

Следование– это линейная последовательность действий (рис. 2.6):

Рис. 2.6. Следование

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

Ветвление алгоритмическая альтернатива. Управление передается одному из двух блоков в зависимости от истинности или ложности условия. Затем происходит выход на общее продолжение (рис. 2.7):

Рис. 2.7. Ветвление

Цикл повторение некоторой группы действий по условию. Различаются два типа цикла. Первый цикл с предусловием (рис. 2.8):

Рис. 2.8. Цикл с предусловием

Пока условие истинно, выполняется серия, образующая тело цикла.

Второй тип циклической структуры цикл с постусловием (рис. 2.9):

Рис. 2.9. Цикл с постусловием

Здесь тело цикла предшествует условию цикла. Тело цикла повторяет свое выполнение, если условие ложно. Повторение кончается, когда условие станет истинным.

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

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

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

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

Структурный подход требует соблюдения стандарта в изображении блок-схем алгоритмов. Чертить их нужно так, как это делалось во всех приведенных примерах. Каждая базовая структура должна иметь один вход и один выход. Нестандартно изображенная блок-схема плохо читается, теряется наглядность алгоритма.

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

Конструкции одного уровня вложенности записываются на одном вертикальном уровне (начинаются с одной позиции в строке);

Вложенная конструкция записывается смещенной по строке на несколько позиций вправо относительно внешней для нее конструкции.

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

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

«сверху вниз»: сначала строится основной алгоритм, затем вспомогательные алгоритмы;

«снизу вверх»: сначала составляются вспомогательные алгоритмы, затем основной.

Первый подход еще называют методом последовательной детализации, второй сборочным методом.

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

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

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

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

Программирование - процесс составления программ (перевода алгоритма на язык программирования).

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

В настоящее время “язык программирования” и “алгоритмический язык” часто выступают как синонимы.

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

Нисходящее пошаговое проектирование;

Структурное программирование;

Модульное программирование;

Сквозной структурный контроль.

Структурное программирование предполагает составление алгоритма задачи из конструкций строго определенного вида.

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

Каждая структура должна иметь один вход и один выход. На каждом шаге нисходящего проектирования следует составлять алгоритм одного из трех указанных видов (рис. 7.2).

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

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

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

а). Линейная: б). Разветвление: в). Ветвление с

вырожденной ветвью:

С предусловием: - с постусловием: - с известным числом повторов:

Рис. 7.2. Виды управляющих структур

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

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

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

Недостатки программирования на машинном языке:

Большие трудозатраты при записи программы;

Сложность процесса отладки программ;

Трудность достижения высоких показателей надежности программы, производительности труда программистов;

Язык связан с конкретным типом ЭВМ.

Преимущества:

Высокая эффективность программ;

Возможность использования всех ресурсов аппаратуры ЭВМ.

Языки уровня Ассемблера являются машинно-ориентированными. Ассемблер позволяет составить программы в более удобной для человека форме.

Преимущества Ассемблера:

Символическая адресация;

Возможность соединения нескольких программ в единый модуль;

Наличие средств контроля ошибок;

Достаточно высокая эффективность программ;

Использование всех возможностей ЭВМ.

Недостатки:

Излишняя детализация записи программ;

Отсутствие контроля за обращением к элементам памяти.

Языки высокого уровня не содержат машинно-зависимых операторов. Языки этого типа: Фортран, Алгол, Бейсик, Фокал, Пл/1, Паскаль, Кобол и др.

Достоинства программирования на этих языках:

Высокая производительность труда программистов;

Простота эксплуатации программ;

Возможность переноса программ с одной машины на другую (т.е. универсальность).

Недостатки:

Пониженная по сравнению с языками низкого уровня эффективность программ;

Не всегда оптимальное и полное использование ресурсов ЭВМ;

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

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

Интерпретатор - программа, которая транслирует каждый оператор исходной программы и сразу его выполняет.




Close