Сдам Сам

ПОЛЕЗНОЕ


КАТЕГОРИИ







История языков программирования.





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

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

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

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

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

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

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

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

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

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

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

Процесс преобразования программы с языка высокого уровня в машинные команды называется трансляцией. Программа в первоначальной форме называется исходной программой, преобразованная программа называется объектной. Процесс трансляции включает в себя три стадии: лексический анализ (лексический анализатор), синтаксический анализ (синтаксический анализатор) и генерацию объектного кода (генератор объектного кода). В процессе лексического анализа распознаются цепочки символов, которые представляют собой отдельные элементы, и классифицируются согласно тому, являются ли они числовыми значениями, арифметическими операторами, словами и т.д. (например, число 347, слово for). По мере классификации элементов лексический анализатор порождает цепочки битов – лексемы, и передает их синтаксическому анализатору. Синтаксический анализатор рассматривает программу как совокупность лексем и его задача состоит в том, чтобы сгруппировать эти элементы в отдельные высказывания. В большинстве языков программирования для обозначения конца высказывания используются знаки пунктуации, а для обозначения отдельных конструкций – ключевые (зарезервированные) слова. Последняя стадия трансляции программы – это генерация кода, т.е. создание команд машинного языка, выполняющих выражения, распознанные синтаксическим анализатором. Процессы лексического и синтаксического анализа и генерации кода в ЭВМ протекают одновременно.

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

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

Существует тенденция группировать транслятор и другие программы, использующиеся в процессе разработки программного обеспечения, в пакеты, которые функционируют как одна система. Такую систему можно отнести к прикладному программному обеспечению. Используя такую систему, программист получает доступ к редактору для написания программ, транслятору для перевода программы на машинный язык и большому количеству инструментов отладки. Редактор обычно структурирует текст программы согласно правилам используемого языка, иногда распознает и дописывает зарезервированные слова. [1, 8]

 

Парадигмы программирования.

В основе разделения языков программирования на поколения лежит линейная шкала. Позиция языка на этой шкале определяется тем, насколько пользователь свободен от ненужной информации и в какой степени данный язык позволяет программисту мыслить в понятиях, связанных с решаемой задачей. В действительности развитие языков программирования происходит не только в этом направлении, существуют и другие подходы к процессу программирования - парадигмы программирования. Поэтому историческое развитие языков программирования лучше изображать с помощью диаграммы (рис. 2.6). На этой диаграмме показано, что разные направления развития языков являются результатом разных парадигм (подходов), развивающихся независимо друг от друга. В частности, на рисунке изображены четыре направления, представляющие функциональную, объектно-ориентированную, императивную и декларативную парадигмы. Языки, относящиеся к каждой парадигме, расположены на временной шкале, показанной внизу (но из этого не следует, что один язык развивался из другого).[1]

Рис. 2.6. Эволюция парадигм программирования.

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

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

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

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

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

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

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

1) (MAX_число1_число2_... числоN) - максимальное из чисел;

2) (+_число1_число2_... числоN) – сложение;

3) (SETQ_символ1_S-exp1_.... символN_S-expN) - связывает имя со значением выражения.;

4) (EVAL_(/_(-_(*_ 2_7)_5)_2)) - вычисление значения выражения (2*7-5)/2;

5) (SETQ_f_1) (WHILE_(<_f_10)_(SETQ_f_(+_f_3))) – присваиваем переменной f значение 1 и увеличиваем переменную f на три, до тех пор, пока f меньше 10.

Объектно-ориентированная парадигма и соответствующее ей объектно-ориентированное программирование (ООП) представляют собой еще один подход к процессу разработки программного обеспечения. Данные при этом подходе рассматриваются как активные «объекты», а не как пассивные единицы, представленные в обычной императивной парадигме. Например, рассмотрим список имен. В императивной парадигме этот список рассматривается просто как набор данных. Любая программа, пытающаяся получить доступ к списку, должна содержать алгоритм, выполняющий необходимые действия (чтение списка и т.п.). Таким образом, список обслуживается управляющей программой. При объектно-ориентированном подходе список рассматривается как объект, состоящий из самого списка и процедур для манипуляции им. Это могут быть программы для помещения в список нового элемента, удаления элемента из списка, проверки наличия элемента в списке и сортировки списка. В свою очередь, программе, пытающейся получить доступ к списку, совсем не обязательно содержать алгоритмы для выполнения этих задач. Вместо этого она использует процедуры объекта. Можно сказать, что программа просит список отсортировать себя, а не сама сортирует его.

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

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

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

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

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

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

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

 

Основные понятия традиционного программирования.

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

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

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

Тип данных однозначно определяет представление данных в памяти ЭВМ, и следовательно, и множество их возможных значений, а также допустимые действия над данными.

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

В программе могут использоваться фиксированные, заранее заданные значения – константы.

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

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

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

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

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

 







ЧТО И КАК ПИСАЛИ О МОДЕ В ЖУРНАЛАХ НАЧАЛА XX ВЕКА Первый номер журнала «Аполлон» за 1909 г. начинался, по сути, с программного заявления редакции журнала...

Система охраняемых территорий в США Изучение особо охраняемых природных территорий(ООПТ) США представляет особый интерес по многим причинам...

Что вызывает тренды на фондовых и товарных рынках Объяснение теории грузового поезда Первые 17 лет моих рыночных исследований сводились к попыткам вычис­лить, когда этот...

Конфликты в семейной жизни. Как это изменить? Редкий брак и взаимоотношения существуют без конфликтов и напряженности. Через это проходят все...





Не нашли то, что искали? Воспользуйтесь поиском гугл на сайте:


©2015- 2024 zdamsam.ru Размещенные материалы защищены законодательством РФ.