Содержание
Введение
1. Понятия зыка программирования
1.1 Машинный код
1.2 Алгоритм и программа
1.3 Что такое язык программирования
1.4 Уровни языков программирования
1.5 Компилируемые и интерпретируемые языки
2.Классификация языков программирования
3. Исторический обзор языков программирования
4. Характеристики языков программирования
4.1 Элементы объектной модели
4.2 Характеристики языков программирования с точки зрения элементов объектной модели
Приложение. Популярность языков программирования
Заключение
Литература
Введение
Бурное развитие информационных технологий повлекло за собой создание множества искусственных языков, ориентированных на решение проблемы общения человека с компьютером. Любой обзор по языкам программирования первым делом неизбежно затрагивает вопросы классификации этих языков. Не стремясь к соблюдению слишком строгой и исчерпывающей классификации и опираясь на ряд традиционных подходов, попробуем проанализировать современное состояние языков программирования.
Один из подходов, помогающий провести обзор языков программирования, — подход исторический. Действительно, на первый взгляд все выглядит очень просто. Сначала было программирование в машинных кодах, когда программист являлся единственным посредником между остальными смертными и Машиной — гигантским "ламповым монстром", занимающим если не целое здание, то почти целый этаж. Затем появились мнемонические представления машинного кода, ассемблер и, наконец, макроассемблер. В конце 50-х возникли языки формульного программирования, из которых наиболее замечательным был Фортран, затем (в 60-х) центр тяжести стал понемногу смещаться к нечисленным методам — появился АЛГОЛ. Еще немного, и к 70-м годам произошла структурная революция — АЛГОЛ-W и, наконец, Паскаль. Далее настала очередь "модульного" программирования — Модула и Модула-2. Приблизительно в это же время рождается знаменитый язык Си, идет новая революция логического программирования — в моде ПРОЛОГ и экспертные системы. Пентагон проводит свой знаменитый конкурс, на котором побеждает Ада, а Япония заявляет о проекте машин пятого поколения, основанных на SmallTalk. В результате происходит объектно-ориентированная революция, появляются С++, Оберон, Eiffel и Модула-3.
Общие тенденции развития языков программирования при историческом подходе проследить вполне возможно, однако изложение получается сумбурным и путаным. Удивляться тут нечему — ладно если бы произошла, например, структурная революция: программистская общественность присягнула на верность программированию без "goto" и прощай Фортран! Но нет, и Фортран сейчас "в ходу", а если вспомнить об его преуспевших детях Basic и Visual Basic, то придется признать, что "некрологи" Фортрана более чем двадцатилетней давности выглядят в наше время как забавный исторический курьез. Хотя верно и то, что тех версий языка Фортран, что были четверть века назад, уже не осталось, да и машин, на которых с ними работали, сейчас найдешь разве что в музее. Язык Паскаль также, по сравнению со многими другими языками, сейчас уже не молод, но это не мешает ему оставаться одним из наиболее популярных языков и в наши дни. А Кобол? У него еще более преклонный возраст, а если посмотреть по конференциям на Internet — окажется, что очень много работ и сейчас проводится на Коболе.
Другой возможный классификационный критерий языков программирования — это революционные идеи программирования, воплотившиеся в соответствующих решениях: структурное программирование, модульное программирование, объектно-ориентированное программирование. Однако и тут четкой классификации не получится. К примеру, Паскаль возник как "продукт" структурной революции, удачно впитал в себя идеи революции "модульной", и сегодня существует практически на всех компьютерных платформах в объектно-ориентированных воплощениях. Другой пример: приверженцы языка С++, как правило, самым важным его достоинством называют объектно-ориентированное программирование. Однако было бы неверно считать, что С++ стал популярным только благодаря объектам — как и объектно-ориентированный Паскаль, С++ является языком гибридным. Применение объектно-ориентированной парадигмы при работе на нем совсем не обязательно, и многие программисты в практической работе этими возможностями как в С++, так и в объектно-ориентированном Паскале не пользуются. Точно так же, работая с современными компиляторами языка Паскаль, например с широко известными Borland Pascal/Turbo Pascal (Borland) 7.0 для IBM PC или Think Pascal (Symantec) для компьютеров Macintosh, можно в явном виде не пользоваться модульными возможностями, оформляя исходный код программы почти в полном соответствии со стандартным Паскалем. Ошибочный подход, скажет иной поклонник прогресса. Однако исходный код, соответствующий стандарту, будет обладать высокой переносимостью на разные платформы. Могут быть и иные резоны как для стандартных, так и для гибридных подходов. Видимо, поэтому разработчики объектно-ориентированного языка Модула-3 сделали принцип "гибридности" одним из основных в своем языке. С другой стороны, существует большая группа чистых объектно-ориентированных языков, где объектно-ориентированная парадигма является обязательной. Примером такого языка может служить Dee .
Казалось бы, еще один удобный классификационный признак — популярность языка: чем язык популярней — тем он лучше, так может, недолго думая, и разбить все языки на "плохие" и "хорошие"? Однако хорошо известно, что коммерческий успех того или иного продукта не является объективной оценкой качества. Мода — преходяща, особенно если ее приход стимулируется громкой рекламой и значительными капиталовложениями. И чем популярней язык, тем больше споров вокруг него, чем больше у него сторонников — тем больше и противников. Так, в самое ближайшее время много споров можно будет услышать об языке Java. Не вызовет ли приверженность этого языка принципам объектно-ориентированного программирования оттока его сторонников — и тех, кто не стремится использовать объектно-ориентированное программирование на практике, и тех, кто считает, что в ряде современных языков (например в С++ или в Eiffel) эти принципы реализованы полнее?
И, наконец, еще один критерий — уровень языка. Традиционно к языкам низкого уровня относят ассемблеры, а к языкам высокого уровня все остальные универсальные языки программирования, впрочем, для таких языков, как Форт (FORTH), Си и т. д., иногда выделяется некий "промежуточный" уровень. Помимо этого, делались неоднократные попытки выделить какой-либо язык или группу языков на "сверхвысокий" уровень, например для макросредств электронных таблиц. Не нужно вдаваться в детали, чтобы почувствовать всю условность и этой классификации. Тем более, если учесть, что большинство реализаций современных языков программирования высокого уровня имеют богатые низкоуровневые возможности. Скажем, Inline-директива, позволяющая записывать в исходном тексте машинные коды, или встроенный ассемблер, как, например, это сделано в Borland Pascal. Отметим, что, как правило, встроенный ассемблер гораздо удобнее — запись в кодах на его фоне выглядит анахронизмом. При необходимости программирования какого-либо фрагмента программы на низком уровне можно применять и обычный "не встроенный" ассемблер. В общем случае в современных языковых средах вполне возможно программировать разные модули одной и той же программы на разных языках, например и на нескольких языках высокого уровня. Отметим, однако, что на практике этого лучше не делать без особых причин.
Весьма проблематична классификация языков и по названию. Например, Н. Вирт заявляет, что недостатки концепций языка Паскаль преодолеваются в языках Модула-2 и Оберон: "Назови я эти языки Паскаль-2 и Паскаль-3... их эволюционная линия была бы очевидна". Напрашивается вопрос — что есть язык, а что есть диалект языка: например, стандартный Паскаль, расширенный Паскаль (Extended Pascal) и Turbo Pascal — три разных языка или три диалекта Паскаля?
Итак, подведем итог: несмотря на неполноту традиционных классификаций, они позволяют выявить ряд важнейших характеристик языков программирования. То же самое можно сказать о проблеме сравнения языков. Периодически такие сравнения появляются как в компьютерных журналах, так и в сетевых конференциях. Естественно, главная цель здесь недостижима, и большинство участников дискуссии обычно остается при своем мнении: одним язык Y нравится — другие его терпеть не могут. Однако, при малоинтересных общих выводах, сравнительные оценки деталей двух языков содержат иногда много оригинальных, интересных и плодотворных подходов.
Машинный код
Процессор компьютера — большая интегральная микросхема. Все команды и данные он получает в виде электрических сигналов. Фактически процессор можно рассматривать как огромную совокупность достаточно простых электрических элементов — транзисторов. Транзистор имеет три вывода. На два крайних подается напряжение, необходимое для создания в транзисторе электрического тока, а на средний вывод — напряжение, с помощью которого можно управлять внутренним сопротивлением транзистора, а значит, управлять и током, и напряжением на его выводах.
В электронике транзисторы имеют 3 применения: для создания усилителей, в электронных схемах, обладающих автокабельными свойствами, и в электронных переключателях. Последний способ и применяется в цифровой вычислительной технике. В процессоре компьютера транзисторы сгруппированы в микроэлементы, называемые триллерами и вентилями. Триллеры имеют два устойчивых состояния ( открыт – закрыт) и переключается из одного состояния в другое электрическими сигналами. Этим устойчивым состояниям соответствуют математические понятия 0 и 1 . Вентили немного сложнее – они могут иметь несколько входов ( напряжение на выходах зависит от комбинаций напряжений на входах) и служат для простейших арифметических и логических операций).
Команды, поступающие в процессор по его шинам, на самом деле являются электрическими сигналами, но их тоже можно представить как совокупность нулей и единиц. Разным командам соответствуют разные числа. Поэтому реально программа, с которой работает процессор, представляет собой последовательность чисел, называемую машинным кодом.
Алгоритм и программа
Управлять компьютером нужно по определенному алгоритму. Алгоритм – точно определенное описание способа решения задачи в виде конечной (по времени) последовательности действий. Такое описание еще называют формальным. Для представления алгоритма в виде, понятным компьютеру, служат языки программирования. Сначала всегда разрабатывают алгоритм действий, а потом он записывается на одном из таких языков. В итоге получается текст программы – полное, законченное и детальное описание алгоритма на языке программирования. Затем этот текст программы специальными служебными приложениями, которые называются трансляторами, либо переводится в машинный код, либо исполняется.
Самому написать программу в машинном коде сложно, причем эта сложность резко возрастает с увеличением размера программы и трудоемкости решения нужной задачи. Условно можно считать, что машинный код приемлем, если размер программы не превышает несколько десятков байтов.
Поэтому сегодня почти все программы создаются с помощью языков программирования. Теоретически программу можно написать и средствами обычного естественного языка – это называется программированием на метаязыке(этот подход обычно используется на этапе составления алгоритма), но автоматически перевести такую программу на машинный код пока невозможно из-за высокой неоднозначности естественных языков.
Языки программирования – искусственные языки. От естественных они отличаются ограниченным числом «слов», значение которых понятны транслятору, и очень строгими правилами записи команд (операторов). Совокупность подобных требований образуют синтаксис языка программирования, а смысл каждой команды и других конструкций языка – его семантику. Нарушение формы записи программы приводит к тому, что транслятор не может понять назначение оператора и выдает сообщение о синтаксической ошибке, а правильно написанное, но не отвечающее алгоритму использование команд языка приводят к семантическим (логическим) ошибкам.
В реальных системах программирования переменны технологии и компиляции и интерпретации. В процессе отладки программу можно выполнять по шагам, а результирующий код не обязательно будет машинным – он даже может быть исходным кодом, написанном на другом языке программирования или промежуточным машинно-независимым кодом абстрактного процессора, который в различных компьютерных архитектурах станет выполняться с помощью интерпретатора или компилироваться в соответствующий машинный код.
Элементы объектной модели
Каждый стиль программирования имеет свою концептуальную базу. Каждый стиль требует своего умонастроения и способа восприятия решаемой задачи. Для объектно-ориентированного стиля концептуальная база — это объектная модель. Она имеет четыре главных элемента:
· абстрагирование;
· инкапсуляция;
· модульность;
· иерархия.
Эти элементы являются главными в том смысле, что без любого из них модель не будет объектно-ориентированной. Кроме главных, имеются еще три дополнительных элемента:
· типизация;
· параллелизм;
· сохраняемость.
Называя их дополнительными, мы имеем в виду, что они полезны в объектной модели, но не обязательны.
Без такой концептуальной основы вы можете программировать на языке типа Smalltalk, Object Pascal, C++, CLOS, Eiffel или Ada, но из-под внешней красоты будет выглядывать стиль FORTRAN, Pascal или С. Выразительная способность объектно-ориентированного языка будет либо потеряна, либо искажена. Но еще более существенно, что при этом будет мало шансов справиться со сложностью решаемых задач.
Абстрагирование
Абстрагирование является одним из основных методов, используемых для решения сложных задач.
Абстракция выделяет существенные характеристики некоторого объекта, отличающие его от всех других видов объектов и, таким образом, четко определяет его концептуальные границы с точки зрения наблюдателя.
Абстрагирование концентрирует внимание на внешних особенностях объекта и позволяет отделить самые существенные особенности поведения от несущественных. Абельсон и Суссман назвали такое разделение смысла и реализации барьером абстракции, который основывается на принципе минимизации связей, когда интерфейс объекта содержит только существенные аспекты поведения и ничего больше. Существует еще один дополнительный принцип, называемый принципом наименьшего удивления, согласно которому абстракция должна охватывать все поведение объекта, но не больше и не меньше, и не привносить сюрпризов или побочных эффектов, лежащих вне ее сферы применимости.
Выбор правильного набора абстракций для заданной предметной области представляет собой главную задачу объектно-ориентированного проектирования.
По мнению Сейдвица и Старка "существует целый спектр абстракций, начиная с объектов, которые почти точно соответствуют реалиям предметной области, и кончая объектами, не имеющими право на существование". Вот эти абстракции:
Абстракция сущности | Объект представляет собой полезную модель некой сущности в предметной области |
Абстракция поведения | Объект состоит из обобщенного множества операций |
Абстракция виртуальной машины | Объект группирует операции, которые либо вместе используются более высоким уровнем управления, либо сами используют некоторый набор операций более низкого уровня |
Произвольная абстракция | Объект включает в себя набор операций, не имеющих друг с другом ничего общего |
Абстракция фокусируется на существенных с точки зрения наблюдателя характеристиках объекта.
Инкапсуляция
Абстракция и инкапсуляция дополняют друг друга: абстрагирование направлено на наблюдаемое поведение объекта, а инкапсуляция занимается внутренним устройством. Чаще всего инкапсуляция выполняется посредством скрытия информации, то есть маскировкой всех внутренних деталей, не влияющих на внешнее поведение. Обычно скрываются и внутренняя структура объекта и реализация его методов.
Инкапсуляция, таким образом, определяет четкие границы между различными абстракциями. Возьмем для примера структуру растения: чтобы понять на верхнем уровне действие фотосинтеза, вполне допустимо игнорировать такие подробности, как функции корней растения или химию клеточных стенок. Аналогичным образом при проектировании базы данных принято писать программы так, чтобы они не зависели от физического представления данных; вместо этого сосредотачиваются на схеме, отражающей логическое строение данных. В обоих случаях объекты защищены от деталей реализации объектов более низкого уровня.
Дисков утверждает, что "абстракция будет работать только вместе с инкапсуляцией". Практически это означает наличие двух частей в классе: интерфейса и реализации. Интерфейс отражает внешнее поведение объекта, описывая абстракцию поведения всех объектов данного класса. Внутренняя реализация описывает представление этой абстракции и механизмы достижения желаемого поведения объекта. Принцип разделения интерфейса и реализации соответствует сути вещей: в интерфейсной части собрано все, что касается взаимодействия данного объекта с любыми другими объектами; реализация скрывает от других объектов все детали, не имеющие отношения к процессу взаимодействия объектов.
Инкапсуляцию можно определить следующим образом:
Инкапсуляция — это процесс отделения друг от друга элементов объекта, определяющих его устройство и поведение; инкапсуляция служит для того, чтобы изолировать контрактные обязательства абстракции от их реализации.
Инкапсуляция скрывает детали реализации объекта.
Модульность
По мнению Майерса "Разделение программы на модули до некоторой степени позволяет уменьшить ее сложность... Однако гораздо важнее тот факт, что внутри модульной программы создаются множества хорошо определенных и документированных интерфейсов. Эти интерфейсы неоценимы для исчерпывающего понимания программы в целом". В некоторых языках программирования, например в Smalltalk, модулей нет, и классы составляют единственную физическую основу декомпозиции. В других языках, включая Object Pascal, C++, Ada, CLOS, модуль — это самостоятельная языковая конструкция. В этих языках классы и объекты составляют логическую структуру системы, они помещаются в модули, образующие физическую структуру системы. Это свойство становится особенно полезным, когда система состоит из многих сотен классов.
Согласно Барбаре Лисков "модульность — это разделение программы на фрагменты, которые компилируются по отдельности, но могут устанавливать связи с другими модулями". Мы будем пользоваться определением Парнаса: "Связи между модулями — это их представления друг о друге". В большинстве языков, поддерживающих принцип модульности как самостоятельную концепцию, интерфейс модуля отделен от его реализации. Таким образом, модульность и инкапсуляция ходят рука об руку. В разных языках программирования модульность поддерживается по-разному. Например, в C++ модулями являются раздельно компилируемые файлы. Для C/C++ традиционным является помещение интерфейсной части модулей в отдельные файлы с расширением .h (так называемые файлы-заголовки). Реализация, то есть текст модуля, хранится в файлах с расширением с (в программах на C++ часто используются расширения .ее, .ср и .срр). Связь между файлами объявляется директивой макропроцессора #include. Такой подход строится исключительно на соглашении и не является строгим требованием самого языка. В языке Object Pascal принцип модульности формализован несколько строже. В этом языке определен особый синтаксис для интерфейсной части и реализации модуля (unit). Язык Ada идет еще на шаг дальше: модуль (называемый package) также имеет две части - спецификацию и тело. Но, в отличие от Object Pascal, допускается раздельное определение связей с модулями для спецификации и тела пакета. Таким образом, допускается, чтобы тело модуля имело связи с модулями, невидимыми для его спецификации.
Правильное разделение программы на модули является почти такой же сложной задачей, как выбор правильного набора абстракций.
Модули выполняют роль физических контейнеров, в которые помещаются определения классов и объектов при логическом проектировании системы. Такая же ситуация возникает у проектировщиков бортовых компьютеров. Логика электронного оборудования может быть построена на основе элементарных схем типа НЕ, И-НЕ, ИЛИ-НЕ, но можно объединить такие схемы в стандартные интегральные схемы (модули), например, серий 7400, 7402 или 7404.
Модульность позволяет хранить абстракции раздельно.
В традиционном структурном проектировании модульность - это искусство раскладывать подпрограммы по кучкам так, чтобы в одну кучку попадали подпрограммы, использующие друг друга или изменяемые вместе. В объектно-ориентированном программировании ситуация несколько иная: необходимо физически разделить классы и объекты, составляющие логическую структуру проекта.
Модульность — это свойство системы, которая была разложена на внутренне связные, но слабо связанные между собой модули.
Принципы абстрагирования, инкапсуляции и модульности являются взаимодополняющими. Объект логически определяет границы определенной абстракции, а инкапсуляция и модульность делают их физически незыблемыми.
В процессе разделения системы на модули могут быть полезными два правила. Во-первых, поскольку модули служат в качестве элементарных и неделимых блоков программы, которые могут использоваться в системе повторно, распределение классов и объектов по модулям должно учитывать это. Во-вторых, многие компиляторы создают отдельный сегмент кода для каждого модуля. Поэтому могут появиться ограничения на размер модуля. Динамика вызовов подпрограмм и расположение описаний внутри модулей может сильно повлиять на локальность ссылок и на управление страницами виртуальной памяти. При плохом разбиении процедур по модулям учащаются взаимные вызовы между сегментами, что приводит к потере эффективности кэш-памяти и частой смене страниц.
Иерархия
Значительное упрощение в понимании сложных задач достигается за счет образования из абстракций иерархической структуры. Определим иерархию следующим образом:
Иерархия — это упорядочение абстракций, расположение их по уровням.
Наследование — создание новых объектов из уже существующих. Начиная с определения самых общих абстрактных объектов, можно создавать более конкретные объекты нижнего уровня, которые не только унаследуют все функции своих предшественников, но могут добавлять им свои собственные. Принцип наследования позволяет упростить выражение абстракций, делает проект менее громоздким и более выразительным.
Типизация
Типизация — это способ защититься от использования объектов одного класса вместо другого, или по крайней мере управлять таким использованием.
Типизация заставляет нас выражать наши абстракции так, чтобы язык программирования, используемый в реализации, поддерживал соблюдение принятых проектных решений.
Идея согласования типов занимает в понятии типизации центральное место. Например, возьмем физические единицы измерения. Деля расстояние на время, мы ожидаем получить скорость, а не вес. В умножении температуры на силу смысла нет, а в умножении расстояния на силу — есть. Все это примеры сильной типизации, когда прикладная область накладывает правила и ограничения на использование и сочетание абстракций.
Сильная типизация заставляет нас соблюдать правила использования абстракций, поэтому она тем полезнее, чем больше проект. Однако у нее есть и теневая сторона. А именно, даже небольшие изменения в интерфейсе класса требуют перекомпиляции всех его подклассов. Кроме того, не имея параметризованных классов трудно представить себе, как можно было бы создать собрание разнородных объектов.
Полиморфизм означает, что разные объекты могут описывать различные реализации одного и того же метода.
Строгая типизация предотвращает смешивание абстракций.
Параллелизм
Есть задачи, в которых автоматические системы должны обрабатывать много событий одновременно. В других случаях потребность в вычислительной мощности превышает ресурсы одного процессора. В каждой из таких ситуаций естественно использовать несколько компьютеров для решения задачи или задействовать многозадачность на многопроцессорном компьютере. Процесс (поток управления) — это фундаментальная единица действия в системе. Каждая программа имеет по крайней мере один поток управления, параллельная система имеет много таких потоков: век одних недолог, а другие живут в течении всего сеанса работы системы. Реальная параллельность достигается только на многопроцессорных системах, а системы с одним процессором имитируют параллельность за счет алгоритмов разделения времени.
Параллелизм — это свойство, отличающее активные объекты от пассивных.
Параллелизм позволяет различным объектам действовать одновременно.
Сохраняемость любой программный объект существует в памяти и живет во времени. Аткинсон предположил, что есть непрерывное множество продолжительности существования объектов: существуют объекты, которые присутствуют лишь во время вычисления выражения, но есть и такие, как базы данных, которые существуют независимо от программы. Этот спектр сохраняемости объектов охватывает:
· "Промежуточные результаты вычисления выражений.
· Локальные переменные в вызове процедур.
· Собственные переменные, глобальные переменные и динамически создаваемые данные.
· Данные, сохраняющиеся между сеансами выполнения программы.
· Данные, сохраняемые при переходе на новую версию программы.
· Данные, которые вообще переживают программу" .
Традиционно, первыми тремя уровнями занимаются языки программирования, а последними — базы данных. Этот конфликт культур приводит к неожиданным решениям: программисты разрабатывают специальные схемы для сохранения объектов в период между запусками программы, а конструкторы баз данных переиначивают свою технологию под короткоживущие объекты.
Языки программирования, как правило, не поддерживают понятия сохраняемости; примечательным исключением является Smalltalk, в котором есть протоколы для сохранения объектов на диске и загрузки с диска. Однако, записывать объекты в неструктурированные файлы — это подход, пригодный только для небольших систем.
До сих пор мы говорили о сохранении объектов во времени. В большинстве систем объектам при их создании отводится место в памяти, которое не изменяется и в котором объект находится всю свою жизнь. Однако для распределенных систем желательно обеспечивать возможность перенесения объектов в пространстве, так, чтобы их можно было переносить с машины на машину и даже при необходимости изменять форму представления объекта в памяти.
Определим сохраняемость следующим образом:
Сохраняемость — способность объекта существовать во времени, переживая породивший его процесс, и (или) в пространстве, перемещаясь из своего первоначального адресного пространства.
Сохраняемость поддерживает состояние и класс объекта в пространстве и во времени.
Содержание
Введение
1. Понятия зыка программирования
1.1 Машинный код
1.2 Алгоритм и программа
1.3 Что такое язык программирования
1.4 Уровни языков программирования
1.5 Компилируемые и интерпретируемые языки
2.Классификация языков программирования
3. Исторический обзор языков программирования
4. Характеристики языков программирования
4.1 Элементы объектной модели
4.2 Характеристики языков программирования с точки зрения элементов объектной модели
Приложение. Популярность языков программирования
Заключение
Литература
Введение
Бурное развитие информационных технологий повлекло за собой создание множества искусственных языков, ориентированных на решение проблемы общения человека с компьютером. Любой обзор по языкам программирования первым делом неизбежно затрагивает вопросы классификации этих языков. Не стремясь к соблюдению слишком строгой и исчерпывающей классификации и опираясь на ряд традиционных подходов, попробуем проанализировать современное состояние языков программирования.
Один из подходов, помогающий провести обзор языков программирования, — подход исторический. Действительно, на первый взгляд все выглядит очень просто. Сначала было программирование в машинных кодах, когда программист являлся единственным посредником между остальными смертными и Машиной — гигантским "ламповым монстром", занимающим если не целое здание, то почти целый этаж. Затем появились мнемонические представления машинного кода, ассемблер и, наконец, макроассемблер. В конце 50-х возникли языки формульного программирования, из которых наиболее замечательным был Фортран, затем (в 60-х) центр тяжести стал понемногу смещаться к нечисленным методам — появился АЛГОЛ. Еще немного, и к 70-м годам произошла структурная революция — АЛГОЛ-W и, наконец, Паскаль. Далее настала очередь "модульного" программирования — Модула и Модула-2. Приблизительно в это же время рождается знаменитый язык Си, идет новая революция логического программирования — в моде ПРОЛОГ и экспертные системы. Пентагон проводит свой знаменитый конкурс, на котором побеждает Ада, а Япония заявляет о проекте машин пятого поколения, основанных на SmallTalk. В результате происходит объектно-ориентированная революция, появляются С++, Оберон, Eiffel и Модула-3.
Общие тенденции развития языков программирования при историческом подходе проследить вполне возможно, однако изложение получается сумбурным и путаным. Удивляться тут нечему — ладно если бы произошла, например, структурная революция: программистская общественность присягнула на верность программированию без "goto" и прощай Фортран! Но нет, и Фортран сейчас "в ходу", а если вспомнить об его преуспевших детях Basic и Visual Basic, то придется признать, что "некрологи" Фортрана более чем двадцатилетней давности выглядят в наше время как забавный исторический курьез. Хотя верно и то, что тех версий языка Фортран, что были четверть века назад, уже не осталось, да и машин, на которых с ними работали, сейчас найдешь разве что в музее. Язык Паскаль также, по сравнению со многими другими языками, сейчас уже не молод, но это не мешает ему оставаться одним из наиболее популярных языков и в наши дни. А Кобол? У него еще более преклонный возраст, а если посмотреть по конференциям на Internet — окажется, что очень много работ и сейчас проводится на Коболе.
Другой возможный классификационный критерий языков программирования — это революционные идеи программирования, воплотившиеся в соответствующих решениях: структурное программирование, модульное программирование, объектно-ориентированное программирование. Однако и тут четкой классификации не получится. К примеру, Паскаль возник как "продукт" структурной революции, удачно впитал в себя идеи революции "модульной", и сегодня существует практически на всех компьютерных платформах в объектно-ориентированных воплощениях. Другой пример: приверженцы языка С++, как правило, самым важным его достоинством называют объектно-ориентированное программирование. Однако было бы неверно считать, что С++ стал популярным только благодаря объектам — как и объектно-ориентированный Паскаль, С++ является языком гибридным. Применение объектно-ориентированной парадигмы при работе на нем совсем не обязательно, и многие программисты в практической работе этими возможностями как в С++, так и в объектно-ориентированном Паскале не пользуются. Точно так же, работая с современными компиляторами языка Паскаль, например с широко известными Borland Pascal/Turbo Pascal (Borland) 7.0 для IBM PC или Think Pascal (Symantec) для компьютеров Macintosh, можно в явном виде не пользоваться модульными возможностями, оформляя исходный код программы почти в полном соответствии со стандартным Паскалем. Ошибочный подход, скажет иной поклонник прогресса. Однако исходный код, соответствующий стандарту, будет обладать высокой переносимостью на разные платформы. Могут быть и иные резоны как для стандартных, так и для гибридных подходов. Видимо, поэтому разработчики объектно-ориентированного языка Модула-3 сделали принцип "гибридности" одним из основных в своем языке. С другой стороны, существует большая группа чистых объектно-ориентированных языков, где объектно-ориентированная парадигма является обязательной. Примером такого языка может служить Dee .
Казалось бы, еще один удобный классификационный признак — популярность языка: чем язык популярней — тем он лучше, так может, недолго думая, и разбить все языки на "плохие" и "хорошие"? Однако хорошо известно, что коммерческий успех того или иного продукта не является объективной оценкой качества. Мода — преходяща, особенно если ее приход стимулируется громкой рекламой и значительными капиталовложениями. И чем популярней язык, тем больше споров вокруг него, чем больше у него сторонников — тем больше и противников. Так, в самое ближайшее время много споров можно будет услышать об языке Java. Не вызовет ли приверженность этого языка принципам объектно-ориентированного программирования оттока его сторонников — и тех, кто не стремится использовать объектно-ориентированное программирование на практике, и тех, кто считает, что в ряде современных языков (например в С++ или в Eiffel) эти принципы реализованы полнее?
И, наконец, еще один критерий — уровень языка. Традиционно к языкам низкого уровня относят ассемблеры, а к языкам высокого уровня все остальные универсальные языки программирования, впрочем, для таких языков, как Форт (FORTH), Си и т. д., иногда выделяется некий "промежуточный" уровень. Помимо этого, делались неоднократные попытки выделить какой-либо язык или группу языков на "сверхвысокий" уровень, например для макросредств электронных таблиц. Не нужно вдаваться в детали, чтобы почувствовать всю условность и этой классификации. Тем более, если учесть, что большинство реализаций современных языков программирования высокого уровня имеют богатые низкоуровневые возможности. Скажем, Inline-директива, позволяющая записывать в исходном тексте машинные коды, или встроенный ассемблер, как, например, это сделано в Borland Pascal. Отметим, что, как правило, встроенный ассемблер гораздо удобнее — запись в кодах на его фоне выглядит анахронизмом. При необходимости программирования какого-либо фрагмента программы на низком уровне можно применять и обычный "не встроенный" ассемблер. В общем случае в современных языковых средах вполне возможно программировать разные модули одной и той же программы на разных языках, например и на нескольких языках высокого уровня. Отметим, однако, что на практике этого лучше не делать без особых причин.
Весьма проблематична классификация языков и по названию. Например, Н. Вирт заявляет, что недостатки концепций языка Паскаль преодолеваются в языках Модула-2 и Оберон: "Назови я эти языки Паскаль-2 и Паскаль-3... их эволюционная линия была бы очевидна". Напрашивается вопрос — что есть язык, а что есть диалект языка: например, стандартный Паскаль, расширенный Паскаль (Extended Pascal) и Turbo Pascal — три разных языка или три диалекта Паскаля?
Итак, подведем итог: несмотря на неполноту традиционных классификаций, они позволяют выявить ряд важнейших характеристик языков программирования. То же самое можно сказать о проблеме сравнения языков. Периодически такие сравнения появляются как в компьютерных журналах, так и в сетевых конференциях. Естественно, главная цель здесь недостижима, и большинство участников дискуссии обычно остается при своем мнении: одним язык Y нравится — другие его терпеть не могут. Однако, при малоинтересных общих выводах, сравнительные оценки деталей двух языков содержат иногда много оригинальных, интересных и плодотворных подходов.
Понятие языка программирования
Машинный код
Процессор компьютера — большая интегральная микросхема. Все команды и данные он получает в виде электрических сигналов. Фактически процессор можно рассматривать как огромную совокупность достаточно простых электрических элементов — транзисторов. Транзистор имеет три вывода. На два крайних подается напряжение, необходимое для создания в транзисторе электрического тока, а на средний вывод — напряжение, с помощью которого можно управлять внутренним сопротивлением транзистора, а значит, управлять и током, и напряжением на его выводах.
В электронике транзисторы имеют 3 применения: для создания усилителей, в электронных схемах, обладающих автокабельными свойствами, и в электронных переключателях. Последний способ и применяется в цифровой вычислительной технике. В процессоре компьютера транзисторы сгруппированы в микроэлементы, называемые триллерами и вентилями. Триллеры имеют два устойчивых состояния ( открыт – закрыт) и переключается из одного состояния в другое электрическими сигналами. Этим устойчивым состояниям соответствуют математические понятия 0 и 1 . Вентили немного сложнее – они могут иметь несколько входов ( напряжение на выходах зависит от комбинаций напряжений на входах) и служат для простейших арифметических и логических операций).
Команды, поступающие в процессор по его шинам, на самом деле являются электрическими сигналами, но их тоже можно представить как совокупность нулей и единиц. Разным командам соответствуют разные числа. Поэтому реально программа, с которой работает процессор, представляет собой последовательность чисел, называемую машинным кодом.
Алгоритм и программа
Управлять компьютером нужно по определенному алгоритму. Алгоритм – точно определенное описание способа решения задачи в виде конечной (по времени) последовательности действий. Такое описание еще называют формальным. Для представления алгоритма в виде, понятным компьютеру, служат языки программирования. Сначала всегда разрабатывают алгоритм действий, а потом он записывается на одном из таких языков. В итоге получается текст программы – полное, законченное и детальное описание алгоритма на языке программирования. Затем этот текст программы специальными служебными приложениями, которые называются трансляторами, либо переводится в машинный код, либо исполняется.
Дата: 2019-12-22, просмотров: 255.