|
||||
Меню:
Главная
Форум
Литература: Программирование и ремонт Импульсные блоки питания Неисправности и замена Радиоэлектронная аппаратура Микросхема в ТА Рубрикатор ТА Кабельные линии Обмотки и изоляция Радиоаппаратура Гибкие диски часть 2 часть 3 часть 4 часть 5 Ремонт компьютера часть 2 Аналитика: Монтаж Справочник Электроника Мощные высокочастотные транзисторы 200 микросхем Полупроводники ч.1 Часть 2 Алгоритмические проблемы 500 микросхем 500 микросхем Сортировка и поиск Монады Передача сигнала Электроника Прием сигнала Телевидиние Проектирование Эвм Оптимизация Автомобильная электроника Поляковтрансиверы Форт Тензодатчик Силовые полевые транзисторы Распределение частот Резисторные и термопарные Оберон Открытые системы шифрования Удк |
[67] Глава 3 Модульность, объекты и состояние Metap&XXov (Ьотаиетса (Изменяясь, оно остается неподвижным) Гераклит Plus §a change, plus cest la meme chose Альфонс Карр В предыдущих главах мы ввели основные элементы, из которых строятся программы. Мы видели, как элементарные процедуры и элементарные данные, сочетаясь, образуют составные сущности; мы стали понимать, что без абстракции нельзя справиться со сложностью больших систем. Однако этих инструментов недостаточно для разработки программ. Для эффективного синтеза программ требуются также организационные принципы, которые помогали бы нам сформулировать общий проект программы. В частности, нам нужны стратегии для построения больших программ по принципу модульности (modularity): чтобы программы «естественным» образом делились на логически цельные куски, которые можно разрабатывать и поддерживать независимо друг от друга. Существует мощная стратегия разработки, которая особенно хорошо подходит для построения программ, моделирующих физические системы: воспроизводить в структуре программы структуру моделируемой системы. Для каждого объекта в системе мы строим соответствующий ему вычислительный объект. Для каждого действия в системе определяем в рамках нашей вычислительной модели символьную операцию. Используя эту стратегию, мы надеемся, что расширение нашей модели на новые объекты или действия не потребует стратегических изменений в программе, а позволит обойтись только добавлением новых символьных аналогов этих объектов или действий. Если наша организация системы окажется удачной, то для добавления новых возможностей или отладки старых нам придется работать только с ограниченной частью системы. Таким образом, способ, которым мы организуем большую программу, в значительной степени диктуется нашим восприятием моделируемой системы. В этой главе мы исследуем две важных организационных стратегии, которые соответствуют двум достаточно различным взглядам на мир и структуру систем. Первая из них сосредотачивается на объектах (objects), и большая система рассматривается как собрание индивидуальных объектов, поведение которых может меняться со временем. Альтернативная стратегия строится вокруг потоков (streams) информации в системе, во многом подобно тому, как в электронике рассматриваются системы обработки сигналов. Как подход, основанный на объектах, так и подход, основанный на потоках, высвечивают важные вопросы, касающиеся языков программирования. При работе с объектами нам приходится думать о том, как вычислительный объект может изменяться и при этом сохранять свою индивидуальность. Из-за этого нам придется отказаться от подстановочной модели вычислений (раздел 1.1.5) в пользу более механистичной и в то же время менее привлекательной теоретически модели с окружениями (environment model). Сложности, связанные с объектами, их изменением и индивидуальностью являются фундаментальным следствием из потребности ввести понятие времени в вычислительные модели. Эти сложности только увеличиваются, когда мы добавляем возможность параллельного выполнения программ. Получить наибольшую отдачу от потокового подхода удается тогда, когда моделируемое время отделяется от порядка событий, происходящих в компьютере в процессе вычисления. Мы достигнем этого при помощи метода, называемого задержанными вычислениями (delayed evaluation). 3.1 Присваивание и внутреннее состояние объектов Обычно мы считаем, что мир состоит из отдельных объектов, и у каждого из них есть состояние, которое изменяется со временем. Мы говорим, что объект «обладает состоянием», если на поведение объекта влияет его история. Например, банковский счет обладает состоянием потому, что ответ на вопрос «Могу ли я снять 100 долларов?» зависит от истории занесения и снятия с него денег. Состояние объекта можно описать набором из одной или более переменных состояния (state variables), которые вместе содержат достаточно информации, чтобы определить текущее поведение объекта. В простой банковской системе состояние счета можно охарактеризовать его текущим балансом, вместо того, чтобы запоминать всю историю транзакций с этим счетом. Если система состоит из многих объектов, они редко совершенно независимы друг от друга. Каждый из них может влиять на состояние других при помощи актов взаимодействия, связывающих переменные состояния одного объекта с переменными других объектов. На самом деле, взгляд, согласно которому система состоит из отдельных объектов, полезнее всего в том случае, когда ее можно разделить на несколько подсистем, в каждой из которых внутренние связи сильнее, чем связи с другими подсистемами. Такая точка зрения на систему может служить мощной парадигмой для организации вычислительных моделей системы. Чтобы такая модель была модульной, ее требуется разделить на вычислительные объекты, моделирующие реальные объекты системы. Каждый вычислительный объект должен содержать собственные внутренние переменные состояния (local state variables), описывающие состояние реального объекта. Поскольку объекты в моделируемой системе меняются со временем, переменные состояния соответствующих вычислительных объектов также должны изменяться. Если мы решаем, что поток времени в системе будет моделироваться временем, проходящим в компьютере, то нам требуется способ строить вычислительные объекты, поведение которых меняется по мере выполнения программы. В частности, если нам хочется моделировать переменные состояния обыкновенными символическими именами в языке программирования, в языке должен иметься оператор присваивания (assignment operator), который позволял бы изменять значение, связанное с именем. 3.1.1 Внутренние переменные состояния Чтобы показать, что мы имеем в виду, говоря о вычислительном объекте, состояние которого меняется со временем, давайте промоделируем ситуацию снятия денег с банковского счета. Воспользуемся для этого процедурой withdraw, которая в качестве аргумента принимает сумму, которую требуется снять. Если на счету имеется достаточно средств, чтобы осуществить операцию, то withdraw возвращает баланс, остающийся после снятия. В противном случае withdraw возвращает сообщение «Недостаточно денег на счете». Например, если вначале на счету содержится 100 долларов, мы получим следующую последовательность результатов: (withdraw 25) 75 (withdraw 25) 50 (withdraw 60) "недостаточно денег на счете" (withdraw i5) 35 Обратите внимание, что выражение (withdraw 25), будучи вычислено дважды, дает различные результаты. Это новый тип поведения для процедуры. До сих пор все наши процедуры можно было рассматривать как описания способов вычисления математических функций. Вызов процедуры вычислял значение функции для данных аргументов, и два вызова одной и той же процедуры с одинаковыми аргументами всегда приводили к одинаковому результату.1 При реализации withdraw мы используем переменную balance, которая показывает остаток денег на счете, и определяем withdraw в виде процедуры, которая обращается к этой переменной. Процедура withdraw проверяет, что значение balance не меньше, чем значение аргумента amount. Если это так, withdraw уменьшает значение balance на amount и возвращает новое значение balance. В противном случае она возвращает сообщение «Недостаточно денег на счете». Вот определения balance и withdraw: (define balance i00) (define (withdraw amount) (if (>= balance amount) (begin (set! balance (- balance amount)) balance) "Недостаточно денег на счете")) Значение переменной balance уменьшается, когда мы выполняем выражение 1 На самом деле это не совсем правда. Одно исключение - генератор случайных чисел из раздела 1.2.6. Второе связано с таблицами операций и типов, которые мы ввели в разделе 2.4.3, где значения двух вызовов get с одними и теми же аргументами зависели от того, какие были в промежутке между ними вызовы put. С другой стороны, пока мы не ввели присваивание, мы лишены возможности самим создавать такие процедуры. |
Среды: Smalltalk80 MicroCap Local bus Bios Pci 12С ML Микроконтроллеры: Atmel Intel Holtek AVR MSP430 Microchip Книги: Емкостный датчик 500 схем для радиолюбителей часть 2 (4) Структура компьютерных программ Автоматическая коммутация Кондиционирование и вентиляция Ошибки при монтаже Схемы звуковоспроизведения Дроссели для питания Блоки питания Детекторы перемещения Теория электропривода Адаптивное управление Измерение параметров Печатная плата pcad pcb Физика цвета Управлении софтверными проектами Математический аппарат Битовые строки Микроконтроллер nios Команды управления выполнением программы Перехода от ahdl к vhdl Холодный спай Усилители hi-fi Электронные часы Сердечники из распылённого железа Анализ алгоритмов 8-разрядные КМОП Классификация МПК История Устройства автоматики Системы и сети Частотность Справочник микросхем Вторичного электропитания Типы видеомониторов Радиобиблиотека Электронные системы Бесконтекстный язык Управление техническими системами Монтаж печатных плат Работа с коммуникациями Создание библиотечного компонента Нейрокомпьютерная техника Parser Пи-регулятор ч.1 ПИ-регулятор ч.2 Обработка списков Интегральные схемы Шина ISAВ Шина PCI Прикладная криптография Нетематическое: Взрывной автогидролиз Нечеткая логика Бытовые установки (укр) Автоматизация проектирования Сбор и защита Дискретная математика Kb радиостанция Энергетика Ретро: Прием в автомобиле Управление шаговым двигателем Магнитная запись Ремонт микроволновки Дискретные системы часть 2 | ||