Опубликован: 05.11.2013 | Доступ: свободный | Студентов: 416 / 22 | Длительность: 11:51:00
Лекция 1:

Предисловие

Лекция 1: 12 || Лекция 2 >

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

Следствия:

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

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

Принцип Питера

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Лекция 1: 12 || Лекция 2 >
Ильдус Кучкаров
Ильдус Кучкаров
Россия, Санкт-Петербург, СПбГУ
Антон Конычев
Антон Конычев
Россия, Москва, МГУПИ, 2013