Главная » Просмотр файлов » М. Бен-Ари - Языки программирования. Практический сравнительный анализ (2000)

М. Бен-Ари - Языки программирования. Практический сравнительный анализ (2000) (1160781), страница 36

Файл №1160781 М. Бен-Ари - Языки программирования. Практический сравнительный анализ (2000) (М. Бен-Ари - Языки программирования. Практический сравнительный анализ (2000)) 36 страницаМ. Бен-Ари - Языки программирования. Практический сравнительный анализ (2000) (1160781) страница 362019-09-19СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 36)

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

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

13.1. Раздельная компиляция

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

Раздельная компиляция в языке Fortran

Когда был разработан Fortran, программы вводились в компьютер с помощью перфокарт, и не было никаких дисков или библиотек программ, которые из­вестны сегодня.

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

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

Поскольку каждая подпрограмма компилируется независимо, нельзя со­вместно использовать глобальные объявления данных. Вместо этого опреде­лены общие (common) блоки:

subroutine S1

common /block1/distance(100), speed(100), time(100)

real distance, speed, time

end

Это объявление требует выделить 300 ячеек памяти для значений с плаваю­щей точкой. Все другие объявления для этого же блока распределяются в те же самые ячейки памяти, поэтому, если другая подпрограмма объявляет:

subroutine S2

common /block1/speed(200), time(200), distance(200)

integer speed, time, distance

….

End

то две подпрограммы будут использовать различные имена и различные типы для доступа к одной и той же памяти! Отображение common-блоков друг на друга делается по их расположению в памяти, а не по именам переменных. Если для переменной типа real выделяется столько памяти, сколько для двух пере­менных типа integer, speed(8O) в подпрограмме S2 размещается в той же са­мой памяти, что и половина переменной distance(40) в S1. Эффект подобен неаккуратному использованию типов union в языке С или вариантных запи­сей в языке Pascal.

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

Раздельная компиляция в языке С

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

Вначале немного терминологии: объявление вводит имя в программу:

void proc(void);

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

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

/* File main.c */

int global; /* Внешняя по умолчанию */

int func(int); /* Внешняя по умолчанию */

int main(void)

{

global = 4;

return func(global);

}

В отдельном файле дается определение (реализация) функции; переменная global объявляется снова, чтобы функция имела возможность к ней обратиться:

/* File func.c */

extern int global; /* Внешняя, только объявление */

int func(int parm)

{

return parm + global:

}

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

Компиляция в языке С независима в том смысле, что результат одной ком­пиляции не сохраняется для использования в другой. Если кто-то из вашей группы случайно напишет:

/* File func.c */

extern float global; /* Внешняя, только объявление */

int func(int parm) /* Внешняя по умолчанию */

{

return parm + global;

}

программа все еще может быть откомпилирована и скомпонована, а ошибка произойдет только во время выполнения. На моем компьютере целочисленное значение 4, присвоенное переменной global в main, воспринимается в файле func.c как очень малое число с плавающей точкой; после обратного преобразо­вания к целому числу оно становится нулем, и функция возвращает 4, а не 8.

Как и в языке Fortran, проблему можно частично решить, используя вклю­чаемые файлы так, чтобы одни и те же объявления использовались во всех файлах. И объявление extern для функции или переменной, и определение могут появиться в одном и том же вычислении. Поэтому мы помещаем все внешние объявления в один или несколько включаемых файлов, в то время как единственное определение для каждой функции или переменной будет содержаться не более чем в одном файле «.с»:

/* File main.h */

extern int global; /* Только объявление */

/* File func.h */

extern int func(int parm); /* Только объявление */

/* File main.c */

#include "main.h"

#include "func.h"

int global; /* Определение */

int main(void)

{

return func(global) + 7;

}

/* File func.c */

#include "main.h"

#include "func.h"

int func(int parm) /* Определение */

{

return parm + global;

}

Спецификатор static

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

static int g 1; /* Глобальная переменная только в этом файле */

int g2; /* Глобальная переменная для всех файлов */

static int f1 (int i) {...}; /* Глобальная функция только в этом файле */

intf2(int i) {...}; /* Глобальная функция для всех файлов */

Здесь уместно говорить об области действия файла (file scope), которая выступает в роли области действия модуля (module scope), используемой в других языках. Было бы, конечно, лучше, если бы по умолчанию принимался спецификатор static, а не extern; однако нетрудно привыкнуть приписывать к каждому глобальному объявлению static.

Источником недоразумений в языке С является тот факт, что static имеет другое значение, а именно он определяет, что время жизни переменной явля­ется всем временем выполнения программы. Как мы обсуждали в разделе 7.4, локальные переменные внутри процедуры имеют время жизни, ограниченное одним вызовом процедуры. Глобальные переменные, однако, имеют стати­ческое время жизни, то есть они распределяются, когда программа начинает­ся, и не освобождаются, пока программа не завершится. Статическое время жизни — нормальный режим для глобальных переменных; на самом деле, гло­бальные переменные, объявленные с extern, также имеют статическое время жизни!

Спецификатор static также можно использовать для локальных перемен­ных, чтобы задать статическое время жизни:

void proc(void)

{

static bool first_time = true;

if (first_time) {

/* Операторы, выполняемые при первом вызове proc */

first_time = false;

}

….

}

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

13.2. Почему необходимы модули?

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

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

Но, чтобы понять всю программу, мы должны понять связи между под­программами, которые ее составляют. По аналогии должны быть понятны программы, содержащие от 25 до 100 подпрограмм, что составляет от 625 до 10000 строк. Такой размер программ относительно невелик по сравнению с промышленными и коммерческими программными системами, содержащи­ми 100000, если не миллион, строк. Опыт показывает, что 10000 строк, воз­можно, является верхним пределом для размера монолитной программы и что необходим новый механизм структурирования, чтобы создавать и поддержи­вать большие программные системы.

Стандартным термином для механизма структурирования больших про­грамм является модуль (module), хотя два языка, на которых мы сосредоточили внимание, используют другие термины: пакеты (packages) в языке Ada и клас­сы (classes) в языке C++. В стандарте языка Pascal не определено никакого ме­тода раздельной компиляции или декомпозиции программ. Например, пер­вый Pascal-компилятор был единой программой, содержащей свыше 8000 строк кода на языке Pascal. Вместо того чтобы изменять Pascal, Вирт разрабо­тал новый (хотя и похожий) язык, названный Modula, так как центральным понятием в нем является модуль. К сожалению, многие поставщики расши­рили язык Pascal несовместимыми модульными конструкциями, поэтому Pascal не годится для написания переносимого программного обеспечения. Поскольку модули очень важны для разработки программного обеспечения, мы сосредоточим обсуждение на языке Ada, в котором разработана изящная модульная конструкция — так называемые пакеты.

13.3. Пакеты в языке Ada

Основной идеей, лежащей в основе модулей вообще и пакетов Ada в частно­сти, является то, что такие вычислительные ресурсы, как данные и подпро­граммы, должны быть инкапсулированы в некий единый модуль. Доступ к компонентам модуля разрешается только в соответствии с явно специфи­цированным интерфейсом. На рисунке 13.1 показана графическая запись (называемая диаграммой Буча Бухера), применяемая в разработках на языке Ada.

Большой прямоугольник обозначает пакет Airplane_Package, содер­жащий скрытые вычислительные ресурсы, а малые прямоугольники — ок­на, которые дают пользователю пакета доступ к скрытым ресурсам, овал обозначает, что экспортируется тип; а два прямоугольника — что экспор­тируются подпрограммы. Из каждого модуля, использующего ресурсы па­кета, выходит стрелка, которая указывает на пакет.

Характеристики

Тип файла
Документ
Размер
2,54 Mb
Тип материала
Высшее учебное заведение

Список файлов книги

Свежие статьи
Популярно сейчас
А знаете ли Вы, что из года в год задания практически не меняются? Математика, преподаваемая в учебных заведениях, никак не менялась минимум 30 лет. Найдите нужный учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
6363
Авторов
на СтудИзбе
310
Средний доход
с одного платного файла
Обучение Подробнее