Абстрагирование
Смысл абстрагирования. Абстрагирование является одним из основных методов, используемых для решения сложных задач. Хоар считает, что "абстрагирование проявляется в нахождении сходств между определенными объектами, ситуациями или процессами реального мира, и в принятии решений на основе этих сходств, отвлекаясь на время от имеющихся различий" [42]. Шоу определила это понятие так: "Упрощенное описание или изложение системы, при котором одни свойства и детали выделяются, а другие опускаются. Хорошей является такая абстракция, которая подчеркивает детали, существенные для рассмотрения и использования, и опускает те, которые на данный момент несущественны" [43]. Берзинс, Грей и Науман рекомендовали, чтобы "идея квалифицировалась как абстракция только, если она может быть изложена, понята и проанализирована независимо от механизма, который будет в дальнейшем принят для ее реализации" [44]. Суммируя эти разные точки зрения, получим следующее определение абстракции:
Абстракция выделяет существенные характеристики некоторого объекта, отличающие его от всех других видов объектов и, таким образом, четко определяет его концептуальные границы с точки зрения наблюдателя.
Абстрагирование концентрирует внимание на внешних особенностях объекта и позволяет отделить самые существенные особенности поведения от несущественных. Абельсон и Суссман назвали такое разделение смысла и реализации барьером абстракции [45], который основывается на принципе минимизации связей, когда интерфейс объекта содержит только существенные аспекты поведения и ничего больше [46]. Мы считаем полезным еще один дополнительный принцип, называемый принципом наименьшего удивления, согласно которому абстракция должна охватывать все поведение объекта, но не больше и не меньше, и не привносить сюрпризов или побочных эффектов, лежащих вне ее сферы применимости.
Выбор правильного набора абстракций для заданной предметной области представляет собой главную задачу объектно-ориентированного проектирования.
Ввиду важности этой темы ей целиком посвящена глава 4.
По мнению Сейдвица и Старка "существует целый спектр абстракций, начиная с объектов, которые почти точно соответствуют реалиям предметной области, и кончая объектами, не имеющими право на существование" [47]. Вот эти абстракции, начиная от наиболее полезных к наименее полезным:
• Абстракция сущности | Объект представляет собой полезную модель некой сущности в предметной области |
• Абстракция поведения | Объект состоит из обобщенного множества операций |
• Абстракция виртуальной машины | Объект группирует операции, которые либо вместе используются более высоким уровнем управления, либо сами используют некоторый набор операций более низкого уровня |
• Произвольная абстракция | Объект включает в себя набор операций, не имеющих друг с другом ничего общего |
Клиентом называется любой объект, использующий ресурсы другого объекта (называемого сервером). Мы будем характеризовать поведение объекта услугами, которые он оказывает другим объектам, и операциями, которые он выполняет над другими объектами. Такой подход концентрирует внимание на внешних проявлениях объекта и приводит к идее, которую Мейер назвал контрактной моделью программирования [48]: внешнее проявление объекта рассматривается с точки зрения его контракта с другими объектами, в соответствии с этим должно быть выполнено и его внутреннее устройство (часто во взаимодействии с другими объектами). Контракт фиксирует все обязательства, которые объект-сервер имеет перед объектом-клиентом. Другими словами, этот контракт определяет ответственность объекта - то поведение, за которое он отвечает [49].
Каждая операция, предусмотренная этим контрактом, однозначно определяется ее формальными параметрами и типом возвращаемого значения. Полный набор операций, которые клиент может осуществлять над другим объектом, вместе с правильным порядком, в котором эти операции вызываются, называется протоколом. Протокол отражает все возможные способы, которыми объект может действовать или подвергаться воздействию, полностью определяя тем самым внешнее поведение абстракции со статической и динамической точек зрения.
Абстракция фокусируется на существенных с точки зрения наблюдателя характеристиках объекта.
Центральной идеей абстракции является понятие инварианта. Инвариант - это некоторое логическое условие, значение которого (истина или ложь) должно сохраняться. Для каждой операции объекта можно задать предусловия (инварианты предполагаемые операцией) и постусловия (инварианты, которым удовлетворяет операция). Изменение инварианта нарушает контракт, связанный с абстракцией. В частности, если нарушено предусловие, то клиент не соблюдает свои обязательства и сервер не может выполнить свою задачу правильно. Если же нарушено постусловие, то свои обязательства нарушил сервер, и клиент не может более ему доверять. В случае нарушения какого-либо условия возбуждается исключительная ситуация. Как мы увидим далее, некоторые языки имеют средства для работы с исключительными ситуациями: объекты могут возбуждать исключения, чтобы запретить дальнейшую обработку и предупредить о проблеме другие объекты, которые в свою очередь могут принять на себя перехват исключения и справиться с проблемой.
Заметим, что понятия операция, метод и функция-член происходят от различных традиций программирования (Ada, Smalltalk и C++ соответственно). Фактически они обозначают одно и то же и в дальнейшем будут взаимозаменяемы.
Все абстракции обладают как статическими, так и динамическими свойствами. Например, файл как объект требует определенного объема памяти на конкретном устройстве, имеет имя и содержание. Эти атрибуты являются статическими свойствами. Конкретные же значения каждого из перечисленных свойств динамичны и изменяются в процессе использования объекта: файл можно увеличить или уменьшить, изменить его имя и содержимое. В процедурном стиле программирования действия, изменяющие динамические характеристики объектов, составляют суть программы. Любые события связаны с вызовом подпрограмм и с выполнением операторов. Стиль программирования, ориентированный на правила, характеризуется тем, что под влиянием определенных условий активизируются определенные правила, которые в свою очередь вызывают другие правила, и т.д.
Объектно-ориентированный стиль программирования связан с воздействием на объекты (в терминах Smalltalk с передачей объектам сообщений). Так, операция над объектом порождает некоторую реакцию этого объекта. Операции, которые можно выполнить по отношению к данному объекту, и реакция объекта на внешние воздействия определяют поведение этого объекта.
Примеры абстракций. Для иллюстрации сказанного выше приведем несколько примеров. В данном случае мы сконцентрируем внимание не столько на выделении абстракций для конкретной задачи (это подробно рассмотрено в главе 4), сколько на способе выражения абстракций.
В тепличном хозяйстве, использующем гидропонику, растения выращиваются на питательном растворе без песка, гравия или другой почвы. Управление режимом работы парниковой установки - очень ответственное дело, зависящее как от вида выращиваемых культур, так и от стадии выращивания. Нужно контролировать целый ряд факторов: температуру, влажность, освещение, кислотность (показатель рН) и концентрацию питательных веществ. В больших хозяйствах для решения этой задачи часто используют автоматические системы, которые контролируют и регулируют указанные факторы. Попросту говоря, цель автоматизации состоит здесь в том, чтобы при минимальном вмешательстве человека добиться соблюдения режима выращивания.
Одна из ключевых абстракций в такой задаче - датчик. Известно несколько разновидностей датчиков. Все, что влияет на урожай, должно быть измерено, так что мы должны иметь датчики температуры воды и воздуха, влажности, рН, освещения и концентрации питательных веществ. С внешней точки зрения датчик температуры - это объект, который способен измерять температуру там, где он расположен. Что такое температура? Это числовой параметр, имеющий ограниченный диапазон значений и определенную точность, означающий число градусов по Фаренгейту, Цельсию или Кельвину. Что такое местоположение датчика? Это некоторое идентифицируемое место в теплице, температуру в котором нам необходимо знать; таких мест, вероятно, немного.
Для датчика температуры существенно не столько само местоположение, сколько тот факт, что данный датчик расположен именно в данном месте и это отличает его от других датчиков. Теперь можно задать вопрос о том, каковы обязанности датчика температуры? Мы решаем, что датчик должен знать температуру в своем местонахождении и сообщать ее по запросу. Какие же действия может выполнять по отношению к датчику клиент? Мы принимаем решение о том, что клиент может калибровать датчик и получать от него значение текущей температуры.
Для демонстрации проектных решений будет использован язык C++. Читатели, недостаточно знакомые с этим языком, а также желающие уточнить свои знания по другим объектным и объектно-ориентированным языкам, упоминаемым в этой книге, могут найти их краткие описания с примерами в приложении. Итак, вот описания, задающие абстрактный датчик температуры на C++.
// Температура по Фаренгейту
typedef float Temperature;
// Число, однозначно определяющее положение датчика
typedef unsigned int Location;
class TemperatureSensor {
public:
TemperatureSensor (Location);
~TemperatureSensor();
void calibrate(Temperature actualTemperature);
Temperature currentTemperature() const;
private:
...
};
Здесь два оператора определения типов Temperature и Location вводят удобные псевдонимы для простейших типов, и это позволяет нам выражать свои абстракции на языке предметной области [К сожалению, конструкция typedef не определяет нового типа данных и не обеспечивает его защиты. Например, следующее описание в C++: "typedef int Count;" просто вводит синоним для примитивного типа int. Как мы увидим в следующем разделе, другие языки, такие как Ada и Eiffel, имеют более изощренную семантику в отношении строгой типизации базовых типов]. Temperature - это числовой тип данных в формате с плавающей точкой для записи температур в шкале Фаренгейта. Значения типа Location обозначают места фермы, где могут располагаться температурные датчики.
Класс TemperatureSensor - это только спецификация датчика; настоящая его начинка скрыта в его закрытой (private) части.
Класс TemperatureSensor это еще не объект. Собственно датчики - это его экземпляры, и их нужно создать, прежде чем с ними можно будет оперировать. Например, можно написать так:
Temperature temperature;
TemperatureSensor greenhouse1Sensor(1);
TemperatureSensor greenhouse2Sensor(2);
temperature = greenhouse1Sensor.currentTemperature();
Рассмотрим инварианты, связанные с операцией currentTemperature. Предусловие включает предположение, что датчик установлен в правильным месте в теплице, а постусловие - что датчик возвращает значение температуры в градусах Фаренгейта.
До сих пор мы считали датчик пассивным: кто-то должен запросить у него температуру, и тогда он ответит. Однако есть и другой, столь же правомочный подход. Датчик мог бы активно следить за температурой и извещать другие объекты, когда ее отклонение от заданного значения превышает заданный уровень. Абстракция от этого меняется мало: всего лишь несколько иначе формулируется ответственность объекта. Какие новые операции нужны ему в связи с этим? Обычной идиомой для таких случаев является обратный вызов. Клиент предоставляет серверу функцию (функцию обратного вызова), а сервер вызывает ее, когда считает нужным. Здесь нужно написать что-нибудь вроде:
class ActiveTemperatureSensor {
public: ActiveTemperatureSensor (Location, void (*f)(Location, Temperature));
~ActiveTemperatureSensor();
void calibrate(Temperature actualTemperature);
void establishSetpoint(Temperature setpoint, Temperature delta);
Temperature currentTemperature() const;
private:
...
};
Новый класс ActiveTemperatureSensor стал лишь чуть сложнее, но вполне адекватно выражает новую абстракцию. Создавая экземпляр датчика, мы передаем ему при инициализации не только место, но и указатель на функцию обратного вызова, параметры которой определяют место установки и температуру. Новая функция установки establishSetpoint позволяет клиенту изменять порог срабатывания датчика температуры, а ответственность датчика состоит в том, чтобы вызывать функцию обратного вызова каждый раз, когда текущая температура actualTemperature отклоняется от setpoint больше чем на delta.
При этом клиенту становится известно место срабатывания и температура в нем, а дальше уже он сам должен знать, что с этим делать.
Заметьте, что клиент по-прежнему может запрашивать температуру по собственной инициативе. Но что если клиент не произведет инициализацию, например, не задаст допустимую температуру? При проектировании мы обязательно должны решить этот вопрос, приняв какое-нибудь разумное допущение: пусть считается, что интервал допустимых изменений температуры бесконечно широк.
Как именно класс ActiveTemperatureSensor выполняет свои обязательства, зависит от его внутреннего представления и не должно интересовать внешних клиентов. Это определяется реализацией его закрытой части и функций-членов.
Рассмотрим теперь другой пример абстракции. Для каждой выращиваемой культуры должен быть задан план выращивания, описывающий изменение во времени температуры, освещения, подкормки и ряда других факторов, обеспечивающих высокий урожай. Поскольку такой план является частью предметной области, вполне оправдана его реализация в виде абстракции.
Для каждой выращиваемой культуры существует свой отдельный план, но общая форма планов у всех культур одинакова. Основу плана выращивания составляет таблица, сопоставляющая моментам времени перечень необходимых действий. Например, для некоторой культуры на 15-е сутки роста план предусматривает поддержание в течении 16 часов температуры 78¦F, из них 14 часов с освещением, а затем понижение температуры до 65¦F на остальное время суток. Кроме того, может потребоваться внесение удобрений в середине дня, чтобы поддержать заданное значение кислотности.
Таким образом, план выращивания отвечает за координацию во времени всех действий, необходимых при выращивании культуры. Наше решение заключается в том, чтобы не поручать абстракции плана само выполнение плана, - это будет обязанностью другой абстракции. Так мы ясно разделим понятия между различными частями системы и ограничим концептуальный размер каждой отдельной абстракции.
С точки зрения интерфейса объекта-плана, клиент должен иметь возможность устанавливать детали плана, изменять план и запрашивать его.
Например, объект может быть реализован с интерфейсом "человек-компьютер" и ручным изменением плана. Объект, который содержит детали плана выращивания, должен уметь изменять сам себя. Кроме того, должен существовать объект-исполнитель плана, умеющий читать план. Как видно из дальнейшего описания, ни один объект не обособлен, а все они взаимодействуют для обеспечения общей цели. Исходя из такого подхода, определяются границы каждого объекта-абстракции и протоколы их связи.
На C++ план выращивания будет выглядеть следующим образом. Сначала введем новые типы данных, приближая наши абстракции к словарю предметной области (день, час, освещение, кислотность, концентрация):
// Число, обозначающее день года
typedef unsigned int Day;
// Число, обозначающее час дня
typedef unsigned int Hour;
// Булевский тип
enum Lights {OFF, ON};
// Число, обозначающее показатель кислотности в диапазоне от 1 до 14
typedef float pH;
// Число, обозначающее концентрацию в процентах: от 0 до 100
typedef float Concentration;
Далее, в тактических целях, опишем следующую структуру:
// Структура, определяющая условия в теплице
struct Condition {
Temperature temperature;
Lights lighting;
pH acidity;
Concentration concentration;
};
Мы использовали структуру, а не класс, поскольку Condition - это просто механическое объединение параметров, без какого-либо внутреннего поведения, и более богатая семантика класса здесь не нужна.
Наконец, вот и план выращивания:
class GrowingPlan (
public: GrowingPlan (char *name);
virtual ~GrowingPlan();
void clear();
virtual void establish(Day, Hour, const Condition&);
const char* name() const;
const Condition& desiredConditions(Day, Hour) const;
protected:
...
};
Заметьте, что мы предусмотрели одну новую обязанность: каждый план имеет имя, и его можно устанавливать и запрашивать. Кроме того заметьте, что операция establish описана как virtual для того, чтобы подклассы могли ее переопределять.
В открытую (public) часть описания вынесены конструктор и деструктор объекта (определяющие процедуры его порождения и уничтожения), две процедуры модификации (очистка всего плана clear и определение элементов плана establish) и два селектора-определителя состояния (функции name и desiredCondition).Мы опустили в описании закрытую часть класса, заменив ее многоточием, поскольку сейчас нам важны внешние ответственности, а не внутреннее представление класса.
Агрегация
Семантика. В то время, как связи обозначают равноправные или "клиент-серверные" отношения между объектами, агрегация описывает отношения целого и части, приводящие к соответствующей иерархии объектов, причем, идя от целого (агрегата), мы можем придти к его частям (атрибутам). В этом смысле агрегация - специализированный частный случай ассоциации. На рис. 3-3 объект rampController имеет связь с объектом growingRamp и атрибут h класса Heater (нагреватель). В данном случае rampController - целое, a h - его часть. Другими словами, h - часть состояния rampController. Исходя из rampController, можно найти соответствующий нагреватель. Однако по h нельзя найти содержащий его объект (называемый также его контейнером), если только сведения о нем не являются случайно частью состояния h.
Рис. 3-3. Агрегация.
Агрегация может означать физическое вхождение одного объекта в другой, но не обязательно. Самолет состоит из крыльев, двигателей, шасси и прочих частей. С другой стороны, отношения акционера с его акциями - это агрегация, которая не предусматривает физического включения. Акционер монопольно владеет своими акциями, но они в него не входят физически. Это, несомненно, отношение агрегации, но скорее концептуальное, чем физическое по своей природе.
Выбирая одно из двух - связь или агрегацию - надо иметь в виду следующее. Агрегация иногда предпочтительнее, поскольку позволяет скрыть части в целом. Иногда наоборот предпочтительнее связи, поскольку они слабее и менее ограничительны. Принимая решение, надо взвесить все.
Объект, являющийся атрибутом другого объекта (агрегата), имеет связь со своим агрегатом. Через эту связь агрегат может посылать ему сообщения.
Пример. Добавим в спецификацию класса TemperatureController описание нагревателя:
Heater h;
После этого каждый объект TemperatureController будет иметь свой нагреватель. В соответствии с нашим определением класса Heater в предыдущей главе мы должны инициализировать нагреватель при создании нового контроллера, так как сам этот класс не предусматривает конструктора по умолчанию. Мы могли бы определить конструктор класса TemperatureController следующим образом:
TemperatureController::TemperatureController(Location 1) : h(1) {}
3.3. Природа классов
Конечно, как уже говорилось, агрегация не требует обязательного физического включения, ни по значению, ни по ссылке. Например, акционер владеет акциями, но они не являются его физической частью. Более того, время жизни этих объектов может быть совершенно различным, хотя концептуально отношение целого и части сохраняется и каждая акция входит в имущество своего акционера. Поэтому агрегация может быть очень косвенной. Например, объект класса Shareholder (акционер) может содержать ключ записи об этом акционере в базе данных акций. Это тоже агрегация без физического включения. "Лакмусовая бумажка" для выявления агрегации такова: если (и только если) налицо отношение "целое/часть" между объектами, их классы должны находиться в отношении агрегации друг с другом.
Рис. 3-9. Отношение использования.
Часто агрегацию путают с множественным наследованием. Действительно, в C++ скрытое (защищенное или закрытое) наследование почти всегда можно заменить скрытой агрегацией экземпляра суперкласса. Решая, с чем вы имеете дело - с наследованием или агрегацией - будьте осторожны. Если вы не уверены, что налицо отношение общего и частного (is а), вместо наследования лучше применить агрегацию или что-нибудь еще.
Анализ
Цель. Как утверждает Меллор, "цель анализа - дать описание задачи. Описание должно быть полным, непротиворечивым, пригодным для чтения и обозрения всеми заинтересованными сторонами, реально проверяемым" [16]. Говоря нашим языком, цель анализа - представить модель поведения системы.
Надо подчеркнуть, что анализ сосредоточен не на форме, а на поведении. На этой фазе неуместно заниматься проектированием классов, представлением или другими тактическими решениями. Анализ должен объяснить, что делает система, а не то, как она это делает. Любое, сделанное на стадии анализа (вопреки этому правилу) утверждение о том "как", может считаться полезным только для демонстрации поведения системы, а не как проверяемое требование к ее проектированию.
В этом отношении цели анализа и проектирования весьма различны. В анализе мы ищем модель мира, выявляя классы и объекты (их роли, обязанности и взаимодействия), которые формируют словарь предметной области. В проектировании мы изобретаем искусственные персонажи, которые реализуют поведение, требуемое анализом. В этом смысле, анализ - это деятельность, которая сводит вместе пользователей и разработчиков системы, объединяя их написанием общего словаря предметной области.
Сосредоточившись на поведении, мы приступаем к выяснению функциональных точек системы. Функциональные точки, впервые описанные Аланом Альбрехтом, обозначают видимые извне и поддающиеся проверке элементы поведения системы [17]. С точки зрения конечного пользователя, функциональная точка представляет некоторое простейшее действие системы в ответ на некоторое событие [Как отмечает Дрегер, в теории управления информационными системами функциональная точка представляет отдельную бизнес-функцию конечного пользователя [18]]. Функциональные точки часто (но не всегда) обозначают отображение входов на выходы и таким образом представляют преобразования, совершаемые системой. С точки зрения аналитика, функциональные точки представляют кванты поведения. Действительно, функциональные точки - мера сложности системы: чем их больше, тем она сложнее.
На стадии анализа мы передаем семантику функциональных точек сценариями.
Анализ никогда не происходит независимо. Мы не стремимся к исчерпывающему пониманию поведения системы и даже утверждаем, что сделать полный анализ до начала проектирования не только невозможно, но и нежелательно. Процесс построения системы поднимает вопросы о ее поведении, на которые реально нельзя дать гарантированный ответ, занимаясь только анализом. Достаточно выполнить анализ всех первичных элементов поведения системы и некоторого количества вторичных, добавляемых для гарантии того, что никакие существенные шаблоны поведения не пропущены.
Достаточно полный и формальный анализ необходим в первую очередь для того, чтобы ход проекта можно было проследить. Возможность проследить проект нужна для обеспечения возможности его просчитать, дабы гарантировать, что не пропущено ни одной функциональной точки. Возможность проследить проект является также основой управления риском. При разработке любой нетривиальной системы, менеджеры столкнутся с необходимостью сделать нелегкий выбор либо в распределении ресурсов, либо в решении некоторой тактической проблемы. Имея возможность проследить процесс от функциональных точек до реализации, гораздо легче оценить влияние подобных проблем на архитектуру.
Результаты. ДеШампо считает, что результатом анализа должно быть описание назначения системы, сопровождаемое характеристиками производительности и перечислением требуемых ресурсов [19]. В объектно-ориентированном проектировании мы получаем такие описания с помощью сценариев. Каждый сценарий представляет одну функциональную точку. Мы используем первичные сценарии для иллюстрации ключевого поведения и вторичные для описания поведения в исключительных ситуациях.
Как говорилось в предыдущих главах, мы используем технику CRC-карточек для раскадровки сценариев, а потом применяем диаграммы объектов для более точной иллюстрации семантики каждого сценария. Такие диаграммы должны демонстрировать взаимодействие объектов, обеспечивающее выполнение функций системы, и упорядоченный процесс этого взаимодействия, состоящий в посылке объектами сообщений друг другу.
Кроме диаграмм объектов, в рассмотрение можно включить диаграммы классов (чтобы показать существующие ассоциации между классами объектов) и состояний (чтобы показать жизненный цикл важнейших объектов).
Часто эти результаты анализа объединяют в один формальный документ, который формулирует требования анализа к поведению системы, иллюстрируя их диаграммами, и показывает такие неповеденческие аспекты системы, как эффективность, надежность, защищенность и переносимость [20].
Побочным результатом анализа будет оценка риска: выявление опасных мест, которые могут повлиять на процесс проектирования. Обнаружение имеющегося риска в начале процесса проектирования облегчит возможные архитектурные компромиссы на поздних этапах разработки.
Виды деятельности. С анализом связаны два основных вида деятельности: анализ предметной области и планирование сценариев.
Как мы описали в главе 4, анализ области должен идентифицировать обитающие в данной проблемной области классы и объекты. Прежде, чем взяться за разработку новой системы, обычно изучают уже существующие. В этом случае мы можем извлечь выгоду из опыта других проектов, в которых принимались сходные решения. Лучшим результатом анализа предметной области может явиться вывод, что нам не надо проектировать новый продукт, а следует повторно использовать или адаптировать существующую программу.
Планирование сценариев является центральным действием анализа. Интересно, что по этому вопросу, кажется, имеется совпадение мнений среди других методологов, особенно у Рубина и Голдберга (Rubin adn Goldberg), Адамса (Adams), Вирфс-Брока (Wirfs-Brock), Коада (Coad) и Джекобсона (Jacobson). Типичный порядок его выполнения следующий:
Идентифицировать основные функциональные точки системы и, если возможно, сгруппировать функционально связанные виды поведения. Рассмотреть возможность создания иерархии функций, в которой высшие функции вытекают из низших.
Для каждого представляющего интерес набора функциональных точек сделать раскадровку сценария, используя технику анализа поведения и примеров использования, описанную в главе 4 [Всесторонний анализ этого предмета можно найти в работах Джекобсона [22] и Рубина и Голдберга [23]].
В мозговом штурме каждого сценария эффективна техника CRC-карточек. Когда прояснится семантика сценариев, следует документировать их, используя диаграммы объектов, которые иллюстрируют объекты, инициирующие и обеспечивающие поведение, и их взаимодействие при выполнении действий сценария. Приложить описание событий, происходящих при выполнении сценария, и порядок выполняемых в результате действий. Кроме того, необходимо перечислить все предположения, ограничения и показатели эффективности для каждого сценария [21].
Если необходимо, сделать вторичные сценарии, иллюстрирующие поведение системы в исключительных ситуациях.
Для объектов с особо важным жизненным циклом описать диаграммы состояний (построить конечный автомат).
Найти в сценариях повторяющиеся шаблоны и выразить их в терминах более абстрактных обобщенных сценариев или в терминах диаграмм классов, показывающих связи между ключевыми абстракциями.
Внести изменения в словарь данных; включить в него новые классы и объекты, выявленные для каждого сценария, вместе с описанием их ролей и обязанностей.
Как описано в следующей главе, планирование сценариев выполняется аналитиками в сотрудничестве с экспертами в предметной области и архитекторами. В планировании сценария дополнительно должен участвовать контролер качества, так как сценарии представляют тестируемое поведение. Привлечение контролеров в самом начале процесса помогает сразу установить высокие стандарты качества. Эффективно также привлекать и других членов коллектива, чтобы дать им возможность включиться в процесс проектирования и ускорить понимание строения системы.
Путевые вехи и характеристики. Мы благополучно завершим эту фазу, когда мы будем иметь уточненные и подписанные сценарии для всех фундаментальных типов поведения системы. Говоря подписанные, мы предполагаем, что конечные результаты анализа проверялись экспертами, конечными пользователями, аналитиками и архитекторами; говоря фундаментальные, мы имеем в виду типы поведения, основные для данного приложения.Повторим, мы не ожидаем полного анализа, - достаточно рассмотреть только основные и несколько второстепенных видов поведения.
Степень совершенства анализа будет измеряться, в частности, его полнотой и простотой. Хороший анализ выявляет все первичные сценарии и, как правило, важнейшие вторичные. Разумный анализ включает также просмотр всех стратегически важных сценариев, так как это помогает привить единое видение системы всему коллективу разработчиков. Наконец, следует найти шаблоны поведения, которые давали бы возможно более простую структуру классов и учитывали бы все, что есть общего в различных сценариях.
Другой важной составной частью анализа является оценка риска, которая облегчит будущие стратегические и тактические компромиссы.
Анализ схем данных
Дэйт задается следующим вопросом: "Пусть дан набор данных, которые надо расположить в базе данных. Как определить подходящую логическую структуру для этих данных? Другими словами, как определить связи и атрибуты? Это и есть задача проектирования базы данных" [19]. Оказывается, что идентификация ключевых абстракций базы данных во многом напоминает процесс идентификации классов и объектов. По этой причине мы начнем разработку системы складского учета сразу с объектно-ориентированного анализа, в процессе которого будет формироваться структура базы данных, а не будем сперва браться за создание схемы базы данных, и затем выводить из нее объектную модель.
Начнем с уже перечисленного нами списка основных абстракций. Применив к нему правила Румбаха, мы получим следующие таблицы базы данных (сначала перечислим те из них, которые соответствуют ролям групп, принимающих участие в работе системы):
CustomerTable
SupplierTable
OrderAgentTable
AccountantTable
ShippingAgentTable
StockPersonTable
RecetvingAgentTable
FlannelTable
Затем следуют таблицы, отражающие классификацию продуктов и их наличие на складе:
ProductTable
InventoryTable
И, наконец, мы вводим таблицы для документопотока:
OrderTable
PurchaseOrderTable
InvoiceTable
PackingOrderTable
StockOrderTable
ShippingLabelTable
Мы не создавали таблиц для классов Report и Transaction, - результаты анализа подсказывают, что объекты этих классов не нуждаются в хранении.
На следующем этапе анализа можно в деталях определить состав атрибутов всех перечисленных таблиц. Наверно, нет смысла обсуждать на страницах этой книги данные вопросы; мы уже останавливались на наиболее интересных свойствах этих абстракции (см. рис. 10-4), а оставшиеся атрибуты дают мало нового с точки зрения архитектуры системы.
10.2. Проектирование
Формулируя подходы к архитектуре системы складского учета, мы должны помнить о трех моментах организационного характера: разделение функций между клиентской и серверной частью, механизм управления транзакциями, стратегия реализации клиентской части приложения.
Архитектура информационной доски
Теперь у нас есть все, чтобы приступить к решению поставленной задачи с использованием метафоры информационной доски. Это классический пример повторного использования "в большом": мы повторно применяем испытанный архитектурный шаблон как основу проекта. Метод информационной доски предполагает следующие объекты верхнего уровня: информационная доска, несколько источников знаний и контроллер. Остается только определить классы и объекты предметной области, которые специализируют эти общие абстракции.
Объекты информационной доски. Объекты на доске образуют иерархию, отражающую иерархичность различных уровней абстракции источников знаний. Таким образом, у нас есть три следующих класса:
Sentence - Полная криптограмма.
Word - Отдельное слово в криптограмме.
CipherLetter - Отдельная буква в слове.
Источники знаний должны пользоваться общей информацией о сделанных в процессе решения предположениях, поэтому в число объектов информационной доски включается следующий класс:
Assumption - Предположение, сделанное источником знаний.
Наконец, источники знания делают предположения о связи между буквами реального и шифровального алфавитов, так что мы вводим следующий класс:
Alphabet - Алфавит исходного текста, алфавит криптограммы и соответствие между ними.
Есть ли между этими пятью классами что-либо общее? Ответ однозначно утвердительный: все они соответствуют объектам информационной доски и этим существенно отличаются от других объектов, например, источников знаний и контроллера. Поэтому вводится следующий суперкласс для всех ранее перечисленных объектов:
class BlackboardObject ...
С точки зрения внешнего поведения определим для этого класса две операции:
register - Добавить объект на доску.
resign -Удалить объект с доски.
Почему мы определили эти две операции над объектами класса BlackboardObject, а не над самой доской? Это похоже на ситуацию, когда объект должен сам нарисовать себя в некотором окне. "Лакмусовый" тест в таких случаях, это вопрос: "Имеет ли сам объект достаточно знаний и умений, чтобы выполнять такие операции?".
Объекты информационной доски как раз лучше всех понимают, как им правильно появляться на доске или удаляться с нее (конечно, они нуждаются при этом в помощи самой доски). Мы уже установили ранее, что объекты, взаимодействующие с доской, по своей сути должны самостоятельно включаться в процесс решения задачи.
Зависимости и подтверждения. Предложения, слова и буквы также связаны определенной общностью: для всех них есть соответствующие источники знаний. Конкретный источник знаний, со своей стороны, может проявлять интерес к одному или нескольким таким объектам (зависеть от них) и поэтому фраза, слово и символ шифра должны поддерживать связь с источником знаний, чтобы при появлении предположения относительно объекта уведомлялись соответствующие источники знаний. Это напоминает механизм зависимостей языка Smalltalk, упомянутый в главе 4. Для реализации этого механизма введем следующий класс-примесь:
class Dependent {
public:
Dependent();
Dependent(const Dependent&);
virtual ~Dependent();
...
protected
UnboundedCollection<KnowledgeSource*> references;
};
Мы забежали несколько вперед и намекнули на возможную реализацию класса, чтобы показать связь с библиотекой фундаментальных классов, описанной в главе 9. В классе определен один внутренний элемент - коллекция указателей на источники знаний [В главе 9 мы отмечали, что неограниченные структуры требуют менеджера памяти. Для простоты мы опускаем этот аргумент шаблона всюду в данной главе. Конечно, полная реализация должна быть согласована с механизмами среды разработки].
Определим для этого класса следующие операции:
add - Добавить ссылку на источник знаний.
remove - Удалить ссылку на источник знаний.
numberOfDependents - Возвратить число зависящих объектов.
notify - Известить каждого зависимого.
Последняя операция является пассивным итератором: при ее вызове передается как параметр действие, которое надо выполнить над всеми зависящими объектами в коллекции.
Зависимость может примешиваться к другим классам.
Например, буква шифра - это объект информационной доски, от которого зависят другие, так что мы можем скомбинировать две этих абстракции для получения нужного поведения. Такое применение примесей поощряет повторное использование и разделение понятий в нашей архитектуре.
Символы шифра и алфавиты имеют еще одно общее свойство: относительно объектов этих классов могут делаться предположения. Вспомните, что предположение (Assumption) является одним из объектов на доске (BlackboardObject). Так, некоторый источник знаний может допустить, что буква K в шифре соответствует букве P исходного текста. По мере решения задачи может абсолютно точно выясниться, что G означает J. Поэтому введен еще один класс:
class Affirmation ...
Этот класс отвечает за высказывания (предположения или утверждения) относительно связанного с ним объекта. Мы используем этот класс не как примесь, а для агрегации. Буква, например, не является предположением, но может иметь предположение о себе.
В нашей системе предположения допускаются только в отношении отдельных букв и алфавитов. Можно, например, предположить, что какая-либо буква шифра соответствует некоторой букве алфавита. Алфавит состоит из набора букв, относительно которых делаются предположения. Определяя Affirmation как независимый класс, мы выражаем в нем сходное поведение этих двух классов, несвязанных наследованием.
Определим следующий набор операций для экземпляров этого класса:
make - Сделать высказывание.
retract - Отменить высказывание.
chiphertext - Вернуть шифрованный эквивалент для заданной буквы исходного текста.
plaintext - Вернуть исходный текстовый эквивалент для заданной буквы шифра.
Из предыдущего обсуждения видно, что надо ясно различать две роли высказываний: временные предположения о соответствиях между буквами шифра и текста и окончательно доказанные соответствия - утверждена. По мере расшифровки криптограммы может делаться множество различных предположений о соответствии букв шифра и текста, но в конце концов находятся окончательные соответствия для всего алфавита.
Чтобы отразить эти роли, уточним ранее выявленный класс Assumption в подклассе Assertion (утверждение). Экземпляры обоих классов управляются объектами класса Affirmation и могут помещаться на доску. Для поддержки введенных ранее операций make и retract нам необходимо определить следующие селекторы:
isPlainLetterAsserted - определена ли эта буква текста достоверно?
isCipherLetterAsserted - определена ли эта буква шифра достоверно?
plainLetterHasAssumptlon - есть ли предположение об этой букве текста?
cipherLetterHasAssumption - есть ли предположение об этой букве шифра?
Теперь мы можем определить класс Assumption. Поскольку данная абстракция носит исключительно структурный характер, ее состояние можно сделать открытым:
class Assumption : public BlackboardObject
{
public:
...
BlackboardObject* target;
KnowledgeSource* creator;
String<char> reason;
char plainLetter;
char cipherLetter;
};
Отметим, что мы повторно использовали еще один класс среды, описанной в главе 9, а именно, параметризуемый класс String.
Класс Assumption является объектом информационной доски, поскольку информация о сделанных предположениях используется всеми источниками знаний. Отдельные члены класса выражают следующие его свойства:
target - Объект доски, о котором делается предположение.
creator - Источник знаний, который сделал предположение.
reason - Основание для сделанного предположения.
cipherLetter - Предполагаемое значение буквы исходного текста.
Необходимость каждого из перечисленных свойств в значительной степени объясняется природой предположений: источник знании формирует предполагаемое соответствие "буква исходного текста - буква шифра" на основании каких-то причин (обычно, некоторого правила). Назначение первого свойства target менее очевидно. Оно нужно для отката. Если сделанное предположение не подтвердится, то нужно восстановить состояние объектов на доске, которые воспользовались предположением, а они должны известить источники знаний, что их смысл изменился.
Далее определим подкласс Assertion:
class Assertion : public Assumption ...
Общим для классов Assumption и Assertion является следующий селектор:
isRetractable - Является ли соответствие потенциально неверным?
Для всех высказанных предположений значение предиката isRetractable является истинным, а для утверждений - ложным. Сделанное утверждение уже нельзя ни изменить ни отвергнуть.
Рис. 11-2. Классы зависимостей и высказываний.
На рис. 11-2 приведена диаграмма, поясняющая связь классов зависимостей и высказываний. Обратите особое внимание на роли, которые играют упомянутые абстракции в различных ассоциациях. Например, класс KnowledgeSource в одном аспекте является создателем (creator) предположения, а в другом - ссылается (referencer) на букву шифра. Из различия ролей естественным образом вытекают различия протоколов взаимодействия.
Проектирование объектов информационной доски. Завершим проектирование, добавив кроме класса алфавита классы для предложения (Sentence), слова (Word) и буквы шифра (cipherLetter). Предложение представляет собой просто объект доски (от которого зависят другие объекты), содержащий список слов, Исходя из этого, запишем:
class Sentence : public BlackboardObject, virtual public Dependent {
public:
...
protected:
List<Word*> words;
};
Суперкласс Dependent определен виртуальным, поскольку мы ожидаем, что будут подклассы от sentence, которые захотят наследовать также и от Dependent. При этом для всех таких подклассов члены класса Dependent будут общими.
В дополнение к операциям register и resign (определенным в суперклассе BlackboardObject) и четырем операциям, унаследованным от класса Dependent, мы добавляем еще две специфические операции для предложения:
value - Текущее значение предложения.
isSolved - Истинно, если о всех словах в предложении сделаны утверждения.
Первоначальное значение value совпадает с текстом криптограммы. Когда isSolved станет истиной, value вернет исходный расшифрованный текст.
Слово является объектом доски и источником зависимости.
Оно состоит из букв. Для удобства источников знаний в класс слова введены указатели на все предложение, а также на предыдущее и следующее слова в предложении. Описание класса Word выглядит так:
class Word : public BlackboardObject, virtual public Dependent {
public:
...
Sentence& sentence() const;
Word* previous() const;
Word* next() const;
protected:
List<CipherLetter*> letters;
};
Так же как для предложения, в класс слова введены две дополнительные операции:
value - Текущее значение слова.
isSolved - Истинно, если о всех буквах слова сделаны утверждения.
Теперь можно определить класс cipherLetter (буква шифра). Буквы шифра являются объектами информационной доски и порождают зависимости. Кроме того, они имеют значение (буква, как она записывается в шифровке, например, н) и коллекцию возможных предположений и утверждений о соотнесении ее с буквами исходного текста. Для организации коллекции мы используем класс Affirmation. Опишем класс буквы следующим образом:
class CipherLetter : public BlackboardObject, virtual public Dependent {
public:
...
char value() const;
int isSolved() const;
...
protected:
char letter;
Affirmation affirmations;
};
Отметим, что и в этот класс добавлена та же пара селекторов по аналогии с классами слова и предложения. Для клиентов этого объекта нужно предусмотреть защищенные операции доступа к предположениям и утверждениям.
Объект affirmations, включенный в этот класс, содержит коллекцию предположений и утверждений в порядке их выдвижения. Последний элемент коллекции содержит текущее предположение или утверждение. Смысл хранения последовательности решения задачи состоит в возможности обучения источников знании на собственных ошибках. Поэтому в класс Affirmation введены два дополнительных селектора:
mostRecent - возвращает последнее предположение или утверждение;
statementAt - возвращает n-ое высказывание (предположение или утверждение).
Уточнив поведение класса, мы можем принять правильные решения о его реализации.
В частности, нам потребуется ввести в класс следующий защищенный объект:
UnboundedOrderedCollection<Assumption*> statements;
Этот объект также позаимствован нами из библиотеки фундаментальных классов главы 9.
Теперь обратимся к классу Alphabet (алфавит). Он содержит данные об алфавитах исходного текста и шифра, а также о соответствии между ними. Эта информация необходима для того, чтобы источники знаний могли узнать о выявленных соответствиях между буквами шифра и текста и тех, которые еще предстоит найти. Например, если уже доказано, что буква с а шифре соответствует букве и исходного текста, то это соответствие фиксируется в алфавите и источники знаний уже не будут делать других предположений в отношении буквы м исходного текста. Для эффективности обработки полезно получать данные о соответствии букв шифра и текста двумя способами: по букве шифра и по букве исходного текста. Определим класс Alphabet следующим образом:
class Alphabet : public BlackboardObject {
public:
char plaintext(char) const;
char ciphertext(char) const;
int isBound(char) const;
};
Так же, как и в класс CipherLetter, в класс Alphabet необходимо включить защищенный объект affirmations и определить операции доступа к его состоянию.
Наконец, определим класс Blackboard, который является коллекцией экземпляров класса Blackboardobject и его подклассов:
class Blackboard : public DynamicCollection<BlackboardObject*>
...
Поскольку доска есть разновидность коллекции (тест на наследование), мы предпочитаем образовать этот класс методом наследования, а не с помощью включения экземпляра класса DynamicCollectlon. Операции включения в коллекцию и исключения из нее наследуются от класса Collection, а следующие пять операций, специфичных для информационной доски, вводятся нами:
reset - Очистить доску.
assertProblem - Поместить на доске начальные условия задачи.
connect - Подключить к доске источник знании.
issolved - Истинно, если предложение расшифровано.
retriaveSolution - Значение расшифрованного текста.
Вторая операция устанавливает зависимость между доской и источником знании. На рис. 11-3 приведена итоговая диаграмма классов, связанных с Blackboard. Она в первую очередь отражает отношения наследования. Отношения использования (например, между Assumption и информационной доской) для простоты опушены.
Рис. 11-3. Диаграмма классов информационной доски.
Обратите внимание на то, что класс Blackboard одновременно и инстанцирует от шаблона DynamicCollection, и наследует от него. Кроме того, становится понятным использование класса Dependent в качестве примеси. Не привязывая этот класс жестко к иерархии Blackboard, мы повышаем шансы на его последующее повторное использование.
Проектирование источников знаний
В предыдущем разделе мы выделили тринадцать источников знаний, относящихся к решаемой задаче. Теперь можно приступить к проектированию структур классов для них (как это было сделано для информационной доски) и обобщению их в более абстрактные классы.
Проектирование специализированных источников знаний. Предположим, что существует абстрактный класс KnowledgeSource (по аналогии с классом BlackboardObject). Прежде чем определять все тринадцать источников в качестве подклассов одного общего суперкласса, нужно посмотреть, не группируются ли они каким-нибудь образом. Действительно, такие группы находятся: некоторые источники знаний оперируют целым предложением, другие - словами, фрагментами слов или отдельными буквами. Отразим этот факт в следующих определениях:
class SentenceKnowledgeSource : public KnowledgeSource ...
class WordKnowledgeSource : public KnowledgeSource ...
class LetterKnowledgeSource : public KnowledgeSource ...
Для каждого из этих абстрактных классов в дальнейшем мы определим специализированные подклассы. Для класса SentenceKnowledgeSource они будут выглядеть следующим образом:
class SentenceStructureKnowledgeSource : public SentenceKnowledgeSource ...
class SolvedKnowledgeSource : public SentenceKnowledgeSource ...
Аналогично, подклассы класса WordKnowledgeSource определяются так:
class WordStructureKnowledgeSource : public WordKnowledgeSource ...
class SmallWordKnowledgeSource : public WordKnowledgeSource ...
class PatternMatchingKnowledgeSource : public WordKnowledgeSource ...
Последний класс требует некоторых пояснений. Ранее упоминалось, что его цель состоит в нахождении слов по шаблону. Для описания шаблона можно воспользоваться системой записи регулярных выражении, принятой, в частности, в утилите grep системы UNIX:
Любой элемент - ?
Не элемент - ~
Несколько элементов - *
Начало группы - {
Конец группы - }
Используя такие обозначения, мы можем передать объекту этого класса шаблон ?E~{A E I O U}, чтобы он искал в своем словаре слово из трех букв, начинающееся с некоторой буквы, после которой идет E, а затем - любая буква кроме гласной.
Поскольку проверка по шаблону является методом, полезным как для данной системы в целом, так и в других областях, соответствующий класс целесообразно выделить в качестве самостоятельной абстракции. Поэтому неудивительно, что мы воспользуемся классом из нашей библиотеки (см. главу 9). В результате наш класс для проверки по шаблону будет выглядеть следующим образом:
class PatternMatchingKnowledgeSource : public WordKnowledgeSource {
public:
...
protected:
static BoundedCollection<Word*> words;
REPatternMatching patternMatcher;
};
Все экземпляры этого класса разделяют общий словарь, но каждый из них может иметь собственного агента для сравнения с шаблонами.
На данном этапе проектирования подробности реализации этого класса для нас не существенны, поэтому мы не будем на них подробно останавливаться.
Определим теперь подклассы класса StringKnowledgeSource следующим образом:
class CommonPrefixKnowledgeSource : public StringKnowledgeSource ...
class CommonSuffixKnowledgeSource : public StringKnowledgeSource ...
class DoubleLetterKnowledgeSource : public StringKnowledgeSource ...
class LegalStringKnowledgeSource : public StringKnowledgeSource ...
Наконец, определим подклассы класса LetterKnowledgeSource:
class DirectSubstitutionKnowledgeSource : public LetterKnowledgeSource ...
class VowelKnowledgeSource : public LetterKnowledgeSource ...
class ConsonantKnowledgeSource : public LetterKnowledgeSource ...
class LetterFrequencyKnowledgeSource : public LetterKnowledgeSource ...
Общее в источниках знаний. Анализ показал, что только две операции определены для всех упомянутых специализированных классов:
Reset - Перезапуск источника знаний.
evaluate - Определение состояния информационной доски.
Причина упрощения интерфейса - в относительной автономности знаний: мы указываем на интересующий объект информационной доски и даем источнику команду применить его правила, учитывая глобальное состояние доски. При выполнении правил каждый из источников знаний может осуществлять следующие действия:
Высказать предположение о подстановке.
Найти противоречие в ранее предложенных подстановках и откатить их.
Высказать утверждение о подстановке.
Сообщить контроллеру о своем желании записать на доску что-то интересное.
Все эти действия являются общими для всех источников знаний. Перечисленные операции образуют механизм вывода заключений. Определим механизм вывода (InferenceEngine) как объект, который выполняет известные правила для того, чтобы либо найти новые правила (прямая последовательность рассуждений), либо доказать некоторую гипотезу (обратная последовательность рассуждений). На основании сказанного введем следующий класс:
class InferenceEngine {
public:
InferenceEngine(<DynamicSet<Rules*>);
...
};
Конструктор класса создает экземпляр объекта и населяет его правилами. Лишь одна операция сделана в этом классе видимой для источников знании:
evaluate - Выполнить правило механизма вывода.
Теперь о том, как сотрудничают источники знаний: каждый специализированный источник определяет свои собственные правила и возлагает ответственность за их выполнение на класс InferenceEngine. Точнее, операция KnowledgeSource::evaluate вызывает метод InferenceEngine::evaluate, что приводит к выполнению одной из четырех упомянутых выше операций.
На рис. 11- 4 показан сценарий такого взаимодействия:
Рис. 11-4. Взаимодействия с источником знаний.
Что такое правило? Для иллюстрации приведем (в формате Lisp) правило, касающееся знаний об общеупотребительных суффиксах:
((* I ? ?)
(* I N G)
(* I E S)
(* I E D))
Это правило означает, что заданному шаблону *I?? (условие - antecedent) могут соответствовать суффиксы ING, IES и IED (заключение - consequent). В C++ можно определить следующий класс для представления правил:
class Rule {
public:
...
int bind(String<char>& antecedent, String<char>& consequent);
int remove(Strlng<char>& antecedent);
int remove(String<char>t antecedent, String<char>& conseiruent);
int hasConflict(const String<char>& antecedent) const;
protected:
String<char> antecedent;
List<String<char>> consequents;
};
Смысл приведенных операций полностью понятен из их наименований. Мы здесь повторно использовали некоторые классы из главы 9.
С точки зрения строения данного класса можно утверждать, что источники знаний являются разновидностью механизма вывода. Кроме того, они ассоциированы с объектами доски, поскольку находят там приложение своим усилиям. Наконец, каждый источник знаний связан с контроллером и посылает ему свои соображения. Контроллер, в свою очередь, может активизировать источники знаний.
Выразим все сказанное следующим образом:
class KnowledgeSource : public InferenceEngine, public Dependent {
public:
KnowledgeSource(Blackboard*, Controller*);
void reset();
void evaluate();
protected:
Blackboard* blackboard;
Controller* controller;
UnboundedOrderedCollection<Assumption*> pastAssumptions;
};
В этот класс введен защищенный элемент данных pastAssumptions, позволяющий сохранять всю историю предположений в целях самообучения.
Экземпляры класса Blackboard служат для хранения объектов информационной доски. По схожим соображениям, необходим также класс KnowledgeSources, охватывающий все источники знаний, относящиеся к решаемой задаче:
class KnowledgeSources : public DynamicCollection<KnowledgeSource*>
...
Одно из свойств этого класса состоит в том, что при создании его экземпляра создаются также 13 специализированных источников знаний. Для объектов этого класса определяются три операции:
restart - Перезапустить источник знаний.
StartKnowledgeSource - Задать начальные условия для источника знаний.
connect - Связать источник знаний с доской или контроллером.
Рис. 11-5. Диаграмма классов источников знаний.
На рис. 11-5 показана структура созданных в процессе проектирования классов источников знаний.
Проектирование контроллера
Рассмотрим более подробно взаимодействие контроллера с отдельными источниками знаний. В процессе поэтапной расшифровки криптограммы отдельные источники знаний выявляют полезную информацию и сообщают ее контроллеру. С другой стороны, может быть обнаружено, что ранее переданная информация оказалась ложной и ее надо устранить. Поскольку все источники знаний имеют равные права, контроллер должен опросить их все, выбрать тот, информация которого кажется наиболее полезной, и разрешить ему внести изменения вызовом его операции evaluate.
Каким образом контроллер определяет, какой из источников знаний следует активизировать? Можно предложить несколько разумных правил:
Утверждение более приоритетно чем предположение.
Если кто-то говорит, что решил всю фразу, надо дать ему возможность высказаться.
Проверка по шаблону более приоритетна, чем источник, анализирующий структуру предложения.
Контроллер действует в качестве агента, ответственного за взаимодействие источников знаний.
Контроллер должен быть в ассоциативной связи с источниками знаний через класс KnowledgeSources. Кроме того, он должен иметь в качестве одного из своих свойств коллекцию высказываний, упорядоченных по приоритету. Тем самым контроллер легко может выбрать для активизации источник знаний с наиболее интересным высказыванием.
После изолированного анализа класса мы предлагаем ввести для класса controller следующие операции:
reset - Перезапуск контроллера.
addHint - Добавить высказывание от источника знаний.
removeHint - Удалить высказывание от источника знаний.
processNextHint - Разрешить выполнение следующего по приоритету высказывания.
isSolved - Селектор. Истина, если задача решена.
UnableToProceed - Селектор. Истина, если источники знаний застряли.
connect - Устанавливает связь с источником знаний.
Все эти решения можно описать следующим образом:
class Controller {
public:
...
void reset();
void connect(Knowledgesource&);
void addHint(KnowledgeSource&);
void removeHint(KnowledgeSource&);
void processNextHint();
int isSolved() const;
int unableToProceed() const;
};
Контроллер в некотором смысле управляется источниками знаний, поэтому для описания его поведения наилучшим образом подходит схема конечного автомата.
Рассмотрим диаграмму состояний и переходов на рис. 11-6. Из нее видно, что контроллер может находиться в одном из пяти основных состояний: инициализация (Initializing), выбор (Selecting), вычисление (Evaluating), тупик (Stuck) и решение (Solved). Наибольший интерес для нас представляет поведение контроллера при переходе от выбора к вычислению. В состоянии selecting контроллер переходит от создания стратегии (CreatingStrategy) к вычислению высказывания (ProcessingHint) и, в конце концов, выбирает источник знаний (SelectingKS).
Рис. 11-6. Контроллер как конечный автомат.
Дав одному из источников возможность высказаться, контроллер переходит в состояние Evaluating, где прежде всего изменяет состояние информационной доски. Это вызывает переход в состояние Connecting при добавлении источника знании или к Backtracking, если предположение не оправдалось и надо откатить его, оповестив при этом все зависимые источники знаний.
Конечной точкой работы нашего механизма является solved (задача решена) или stuck (тупиковая ситуация).
11.3. Эволюция
Архитектура клиент-сервер
Хотя данный раздел и не является подробным обзором архитектуры клиент-сервер, некоторые замечания по этой теме необходимо сделать, так как они напрямую относятся к выбору архитектурных решений для нашей системы.
Что можно отнести к категории клиент-сервер, а что нет, до сих пор является предметом жарких дискуссий [Также как и вопрос о том, что можно считать объектно-ориентированным, а что - нет]. В нашем случае будет достаточно определения решений на базе клиент-сервер как "децентрализованной архитектуры, позволяющей конечным пользователям получать гарантированный доступ к информации в разнородной аппаратной и программной среде. Приложения клиент-сервер сочетают пользовательский графический интерфейс клиента с реляционной базой данных, расположенной на сервере" [2]. Структура таких приложений подразумевает возможность совместной работы пользователей; при этом ответственность за выполнение тех или иных функций ложится на различные, независимые друг от друга элементы открытой распределенной среды. Берсон далее утверждает, что приложение клиент-сервер обычно можно разделить на четыре компонента:
<
Один из основных вопросов при проектировании архитектуры системы состоит в оптимальном распределении узлов обработки в сети. Принятие решений здесь усложняется тем, что инструменты и стандарты для архитектур клиент-сервер обновляются с ошеломляющей быстротой. Архитектор должен разобраться, например, с POSIX (Portable Operating System Interface, интерфейс переносимых операционных систем), OSI (Open Systems Interconnection, связь открытых систем), CORBA (Common Object Request Broker, единый брокер объектных запросов), объектно-ориентированным расширением языка SQL (SQL3), и рядом специальных решений фирм-поставщиков типа OLE (Object Linking and Embedding, связывание и внедрение объектов) фирмы Microsoft [Именно по этой причине хорошие архитекторы информационных систем получают либо громадные деньги за свое мастерство, либо - массу удовольствия от самого процесса сборки многих разрозненных технологий в одно согласованное целое].
Но на архитектурные решения оказывает влияние не только обилие стандартов. Имеют значение и такие вопросы, как защита данных, производительность системы и ее объем. Берсон предлагает архитектору несколько основных правил проектирования приложении клиент-сервер:
Компонент логики представления обычно устанавливается там же, где и терминал ввода-вывода, то есть на компьютере конечного пользователя.
Учитывая возросшую мощность рабочих станций, а также тот факт, что логика представления установлена на машине клиента, имеет смысл там же разместить и некоторую часть бизнес-логики.
Если механизмы обращения к базе данных связаны с бизнес-логикой, и если клиенты поддерживают некоторое взаимодействие низкого уровня и квазистатические данные, то механизмы обращения к базе данных можно также разместить на стороне клиента.
Принимая во внимание тот факт, что сетевые пользователи обычно организованы в рабочие группы, и что рабочая группа совместно использует базу данных, фрагменты бизнес-логики и механизмов обращения к базе данных, которые являются общими, и сама СУБД должны находиться на сервере [4].
Если нам удастся выбрать верные архитектурные решения и успешно реализовать их тактические детали, модель клиент-сервер даст системе целый ряд преимуществ. Берсон особо выделяет, что архитектура клиент-сервер:
Позволяет более эффективно использовать новые компьютерные технологии автоматизации.
Позволяет перенести обработку данных ближе к клиенту, что снижает загрузку сети и уменьшает продолжительность транзакций.
Облегчает использование графических интерфейсов пользователя, которые стали доступны на мощных современных рабочих станциях.
Облегчает переход к открытым системам [5]. Надо выделить, однако, следующие моменты риска:
Если значительная часть логики приложения окажется вынесенной на сервер, то последний может стать узким местом системы, замедляющим работу пользователей (как это часто бывало при использовании мэйнфреймов в архитектуре хозяин-раб).
Распределенные приложения... сложнее нераспределенных [6].
Мы уменьшим этот риск, используя объектно-ориентированный подход к разработке.
Теперь вернемся к нашему примеру и рассмотрим более внимательно класс Product. Для этого класса мы определяем следующий набор операций:
construct
setDescription
setQuantity
setLocation
setSupplier
productID
description
quantity
location
supplier
Эти операции являются общими для всех видов товаров. Однако, анализ частных случаев показывает, что есть продукты, для которых эти характеристики недостаточны. С учетом того, что проектируемая система является открытой, а виды товаров могут быть самыми различными, приведем несколько примеров специфических товаров и их свойств:
Скоропортящиеся продукты, требующие определенного режима хранения.
Едкие и токсичные химические вещества, также требующие специального обращения.
Комплектные товары, которые поставляются в определенных сочетаниях (например, радиопередатчики и приемники) и поэтому взаимозависимы.
Высокотехнологичные компоненты, поставки которых ограничиваются законодательством стран-экспортеров.
Перечисленные примеры наводят на мысль о необходимости создания некоторой иерархии классов товаров. Однако, перечисленные свойства настолько различны, что не образуют никакой иерархии. В данной ситуации более целесообразно воспользоваться примесями, что иллюстрирует и рис. 10-7. Обратим внимание на использование в этой диаграмме украшений ограничения, уточняющих семантику каждой абстракции.
Каков смысл наследования для абстракций, отражающих сущности реляционной базы данных? Очень большой: построение иерархии наследования сопровождается вычленением общих признаков поведения и отображением их в структуре суперклассов. Эти суперклассы будут ответственны за реализацию общего поведения для всех объектов, за исключением тех подклассов, которые уточняют это поведение (через промежуточный суперкласс) или расширяют его (через суперкласс-примесь). Такой подход не только упрощает построение системы, но и повышает устойчивость к вносимым изменениям за счет сокращения избыточности и локализации общих структур и поведения.
Рис. 10-7. Классы товаров.
Архитектура клиент-сервер: складской учет
Создание большинства бизнес-приложений требует решения целого комплекса задач по хранению данных, обеспечению параллельного доступа к ним, их целостности и защиты. Для этой цели обычно используются готовые системы управления базами данных (СУБД).
Конечно, любая СУБД требует адаптации к условиям конкретного предприятия, которую организации часто разбивают на две задачи: проектирование данных поручается специалистам по базам данных, а программная поддержка выполнения транзакций - программистам. Реализация такого подхода, имеющего, конечно, свои преимущества, сопряжена с решением ряда серьезных проблем. Надо откровенно признать, что в деятельности разработчиков баз данных и программистов существуют серьезные различия, которые определяются различиями в технологии и в навыках разработки. Проектировщики баз данных обычно описывают проблемную область в терминах "долгоживущих" монолитных таблиц с информацией, в то время как программисты привыкли воспринимать мир в терминах потоков управления.
Если эти два подхода не удастся совместить в рамках одного проекта, то добиться целостности проектного решения для более или менее сложной системы будет практически невозможно. Для системы, в которой главное -данные, мы должны добиться равновесия между базой данных и приложением. База данных, разработанная без учета того, как она в дальнейшем будет использоваться, оказывается, как правило, неуклюжей и неэффективной. В свою очередь изолированное приложение может предъявить невыполнимые требования к базе данных, что приведет к серьезным проблемам с обеспечением целостности информации.
Еще в недалеком прошлом бизнес-приложения выполнялись на больших ЭВМ, что воздвигало для обычного служащего почти непреодолимые барьеры на пути к нужной ему информации. Однако с пришествием персонального компьютера ситуация резко переменилась: доступные инструменты обработки и хранения данных вкупе с компьютерными сетями позволили соединить компьютеры не только внутри офиса, но и между предприятиями, отделенными друг от друга тысячами километров. Одним из основных факторов, способствовавших такому изменению, было внедрение архитектуры клиент-сервер. Как отмечает Мимно, "Резкий переход к архитектурам клиент-сервер на базе персональных компьютеров был вызван прежде всего требованиями бизнеса. Перед лицом возросшей конкуренции и ускорившегося цикла выпуска новой продукции, возникла потребность в более быстром продвижении товаров на рынок, увеличении объема услуг, предоставляемых клиентам, более оперативном отслеживании тенденций развития рынка, общем уменьшении расходов" [1]. В этой главе мы рассмотрим пример информационно-управляющей системы (MIS, management information system) и покажем, как объектно-ориентированная технология предлагает единую концепцию организации базы данных и разработки соответствующего приложения для архитектуры клиент-сервер.
10.1. Анализ
Архитектура метафоры информационной доски
Энглемор и Морган для пояснения модели информационной доски использовали следующую аналогию с группой людей, собирающей фрагменты головоломки в нужную фигуру:
Вообразим себе комнату с большой доской, рядом с которой находится группа людей, держащих в руках фрагменты изображения. Процесс начинают добровольцы, которые размещают на доске наиболее "вероятные" фрагменты изображения (предположим, что они прилепляются к доске). Далее каждый участник группы смотрит на оставшиеся у него фрагменты и решает, есть ли такие, которые подходят к уже находящимся на доске. Участник, нашедший соответствие, подходит к доске и прилепляет свой кусок. В результате фрагмент за фрагментом занимают нужное место. При этом не существенно, что один из участников может иметь больше фрагментов, чем другой. Все изображение будет полностью собрано без всякого обмена информацией между членами группы. Каждый участник активизируется самостоятельно и знает, когда ему нужно включиться в процесс. Никакого порядка подхода к доске заранее не устанавливается. Совместное поведение регулируется только информацией на доске. Наблюдение за процессом демонстрирует его последовательность (по одному фрагменту за подход) и произвольность (когда возникает возможность, фрагмент устанавливается). Это существенно отличается от строгой систематичности, например, от прохождения с левого верхнего угла и перебора каждого фрагмента [7].
Из рис. 11-1 видно, что основу метода составляют три элемента: информационная доска, совокупность источников знаний и управляющий этими источниками контроллер [8]. Отметим, что следующее определение прямо соответствует принципам объектного подхода. Согласно Ни: "Информационная доска нужна для того чтобы хранить данные о ходе и состоянии решаемой задачи, используемые и формируемые источниками знаний. Доска содержит объекты из пространства решений. Эти объекты иерархически группируются по уровням анализа и вместе со своими атрибутами образуют словарь пространства решений" [9].
Энглемор и Морган уточняют: " необходимые для решения задачи знания о предметной области разделены на несколько независимых источников. Каждый источник знаний старается предложить информацию, полезную для решения за дачи. Текущая информация из каждого источника помещается на доске и модифицируется в соответствии с содержанием знаний. Формой представления источников знаний являются процедуры, наборы правил или логические заключения" [10].
Рис. 11-1. Информационная доска.
Источники знаний зависят от предметной области. В системах распознавания речи нас могут интересовать агенты, поставляющие знания о фонемах, словах и предложениях. В системах распознавания образов ими могут быть сведения об элементарных структурах изображения, таких, как стыки линий, участки одинаковой плотности, и, на более высоком уровне абстракции, объекты, относящиеся к конкретной сцене (дома, дороги, поля, автомобили и люди).
В общем случае источники знаний соответствуют иерархической структуре объектов, размещаемых на информационной доске. Более того, каждый источник использует объекты одного уровня иерархии в качестве входных данных, а в качестве выхода генерирует или изменяет объекты на другом уровне. Например, в системе распознавания речи источник знаний о словах наблюдает за потоком фонем (низкий уровень абстракции), чтобы обнаружить слово (более высокий уровень абстракции). Источник знаний о предложениях может предположить, что здесь нужен глагол (высокий уровень абстракции) и проверить это предположение, перебрав список возможных слов (низкий уровень абстракции).
Эти два подхода к поиску решения называются соответственно прямой и обратной последовательностью рассуждений. Прямая последовательность
рассуждений позволяет перейти от более частных предположений к более общим, а обратная последовательность, отталкиваясь от некоторой гипотезы, позволяет проверить ее, сравнив с известными предпосылками. Вот почему управление информационной доской мы охарактеризовали как произвольное: в зависимости от обстоятельств, источники знаний могут активизировать либо прямые, либо обратные последовательности рассуждений.
Источники знаний, как правило, состоят из двух компонент: предусловия и действия. Предусловием называется такое состояние информационной доски, которое представляет "интерес" для конкретного источника знаний (потенциально способно его активизировать). Например, в распознавании образов предусловием может быть наличие прямой линии (которая может означать дорогу). Выполнение предусловий заставляет источник знаний сфокусировать внимание на конкретном участке информационной доски, а затем привести в действие соответствующие правила или процедурные знания.
В этих условиях очередность активизации не имеет значения: если источник знаний обнаруживает данные, полезные для решения задачи, он сигнализирует об этом контроллеру доски, фигурально выражаясь, он как бы поднимает руку, показывая, что желает сделать что-то полезное. Из нескольких источников, делающих такой жест, контроллер вызывает того, кто ему представляется наиболее перспективным.
Анализ источников знаний
Вернемся теперь к поставленной задаче и рассмотрим источники знаний, полезные для ее решения. При построении большинства приложений, основанных на знаниях, лучше всего сесть рядом с экспертом в предметной области и фиксировать те эвристики, которые он использует. В нашем случае придется попытаться расшифровать некоторое количество криптограмм и отметить особенности процесса поиска решений.
Действуя таким образом мы выявили тринадцать источников знаний, относящихся к нашей проблеме:
• Префиксы | Наиболее часто используемые начала слов (например, re, anti, un). |
• Суффиксы | Наиболее часто используемые окончания слов (ly, ing, es, ed). |
• Согласные | Буквы, не являющиеся гласными. |
• Непосредственно известные подстановки | Подстановки, известные нам априори, до решения задачи. |
• Двойные буквы | Наиболее часто сдваиваемые буквы (tt, ll, ss). |
• Частота букв | Вероятность появления букв в тексте. |
• Правильные строки | Допустимые и недопустимые сочетания букв (например, qu и zg). |
• Сравнение с шаблоном | Слова, соответствующие шаблону. |
• Структура фраз | Грамматика, включая знания об именных и глагольных оборотах. |
• Короткие слова | Одно-, двух-, трех- и четырехбуквенные слова. |
• Решение | Найдено ли решение или мы зашли в тупик. |
• Гласные | Буквы, не являющиеся согласными. |
• Структура слова | Расположение гласных и типичная структура существительных, глаголов, прилагательных, наречий, предлогов, союзов и т.д. |
Исходя из объектно-ориентированного подхода, все эти источники знаний являются потенциальными кандидатами на роль классов, на основе которых создаются объекты, обладающие состоянием (знания), поведением (источник знаний о суффиксах может среагировать на слово с характерным окончанием) и индивидуальностью (знания о коротких словах не зависят от умения сравнивать с шаблоном).
Перечисленные источники знаний можно организовать в иерархию. В частности, существуют группы источников знаний о предложениях, о словах, о группах букв и об отдельных буквах. Такая иерархия соответствует объектам на информационной доске: предложениям, словам, частям слов и буквам.
11.2. Проектирование
Архитектурный каркас
Каждая программная система должна иметь простую и в то же время всеобъемлющую организационную философию. Система мониторинга погоды не является в этом смысле исключением. На следующем этапе нашей работы мы должны четко определить архитектуру проекта. Это даст нам стабильный фундамент, на основе которого мы будем строить отдельные функциональные части системы.
Существует целый ряд архитектурных моделей для решения задач сбора и обработки данных и управления, но наиболее часто встречаются синхронизация автономных исполнителей и схема покадровой обработки.
В первом случае архитектура системы скомпонована из ряда относительно независимых объектов, каждый из которых выполняется как поток управления. Можно было бы, например, создать несколько новых объектов-датчиков, построенных с помощью более примитивных абстракций, каждый из которых отвечал бы за считывание информации с определенного датчика и за передачу ее центральному агенту, обрабатывающему всю информацию. Подобная архитектура имеет свои преимущества и является, пожалуй, единственной приемлемой моделью в случае проектирования распределенной системы, которая должна производить обработку большого числа параметров, поступающих с удаленных датчиков. Эта модель также позволяет эффективнее оптимизировать процесс сбора данных (каждый объект-датчик может содержать в себе информацию о том, как надо приспосабливаться к изменению окружающих условий - увеличивать или уменьшать частоту опроса, например).
Однако подобные архитектуры оказываются не всегда приемлемыми при создании жестких систем реального времени, где требуется обеспечить предсказуемость процесса обработки. Метеорологическую станцию нельзя отнести к таким системам, но для нее, тем не менее, требуется определенная степень предсказуемости и надежности. По этой причине мы выбираем для нашей системы модель покадровой обработки.
Рис. 8-12. Покадровая обработка.
Как показано на рис. 8-12, процесс мониторинга осуществляется в данном случае как последовательность считывания, обработки и вывода на экран значений параметров через определенные промежутки времени.
Каждый элемент такой последовательности называется кадром, его, в свою очередь, можно разбить на ряд подкадров, соответствующих определенному функциональному поведению. Различные кадры могут нести информацию о различных параметрах. Направление ветра, например, необходимо измерять через каждые 10 кадров, а скорость ветра - через 30 кадров [Например, если кадры считываются через каждую 1/60 секунды, то 30 кадров занимают 0.5 секунды]. Основное преимущество такой модели состоит в том, что мы можем более жестко контролировать последовательность действий системы по сбору и обработке информации.
На рис. 8-13 приведена диаграмма классов, отражающая особенности архитектуры системы. Здесь присутствуют, в основном, те же самые классы, которые были определены на этапе анализа. Главное отличие от предыдущих диаграмм состоит в том, что теперь мы видим, каким образом ключевые абстракции нашего программного приложения взаимодействуют друг с другом. Мы, естественно, не можем отразить на одной диаграмме все существующие классы и связи между ними. Здесь, например, не воспроизведена иерархия классов-датчиков.
Рис. 8-13. Архитектура системы мониторинга погоды.
Кроме того, мы ввели один новый класс Sensors, который служит для объединения в коллекцию всех объектов-датчиков. Поскольку по крайней мере два агента (Sampler и InputManager) в нашей системе должны ассоциироваться с целой коллекцией датчиков, помещение их в один контейнерный класс позволяет рассматривать все датчики единым образом.
Ассоциация
Пример. Желая автоматизировать розничную торговую точку, мы обнаруживаем две абстракции - товары и продажи. На рис. 3-4 показана ассоциация, которую мы при этом усматриваем. Класс Product - это то, что мы продали в некоторой сделке, а класс Sale - сама сделка, в которой продано несколько товаров. Надо полагать, ассоциация работает в обе стороны: задавшись товаром, можно выйти на сделку, в которой он был продан, а пойдя от сделки, найти, что было продано.
В C++ это можно выразить с помощью того, что Румбах называет погребенными указателями [24]. Вот две выдержки из объявления соответствующих классов:
class Product;
class Sale;
class Product {
public:
...
protected: Sale* lastSale;
};
class Sale {
public:
...
protected: Product** productSold;
};
Это ассоциация вида "один-ко-многим": каждый экземпляр товара относится только к одной последней продаже, в то время как каждый экземпляр Sale может указывать на совокупность проданных товаров.
Семантические зависимости. Как показывает этот пример, ассоциация - смысловая связь. По умолчанию, она не имеет направления (если не оговорено противное, ассоциация, как в данном примере, подразумевает двухстороннюю связь) и не объясняет, как классы общаются друг с другом (мы можем только отметить семантическую зависимость, указав, какие роли классы играют друг для друга). Однако именно это нам требуется на ранней стадии анализа. Итак, мы фиксируем участников, их роли и (как будет сказано далее) мощность отношения.
Мощность. В предыдущем примере мы имели ассоциацию "один ко многим". Тем самым мы обозначили ее мощность (то есть, грубо говоря, количество участников). На практике важно различать три случая мощности ассоциации:
"один-к-одному"
"один-ко-многим"
"многие-ко-многим".
Отношение "один-к-одному" обозначает очень узкую ассоциацию. Например, в розничной системе продаж примером могла бы быть связь между классом Sale и классом CreditCardTransaction: каждая продажа соответствует ровно одному снятию денег с данной кредитной карточки. Отношение "многие-ко-многим" тоже нередки. Например, каждый объект класса Customer (покупатель) может инициировать транзакцию с несколькими объектами класса Saleperson (торговый агент), и каждый торговый агент может взаимодействовать с несколькими покупателями. Как мы увидим в главе 5, все три вида мощности имеют разного рода вариации.
Библиография
Библиография разделена на одиннадцать разделов, пронумерованных латинскими буквами от A до K. В конце каждой главы присутствуют ссылки на пункты в библиографии, имеющие вид [<метка> <год>]. Например, Брукс (Brooks) [H 1975] обозначает книгу 1975 года указанного автора, The Mythical Man-Month, раздел H (Прикладное программирование) библиографии.
А. Классификация
Allen, Т. and Starr, T. 1982. Hierarchy: Perspectives for Ecological Complexity. Chicago, Illinois: The University of Chicago Press.
Aquinas, T. Summa Theologica. Vol.19 of Great Books of the Western World. Chicago, IL: Encyclopedia Britannica.
Aristotle. Categories. Vol.8 of Creat Books of the Western World. Chicago, IL: Encyclopedia Britannica.
Bateson, G. 1979. Mind and Nature: A Necessary Unity. New York, New York Bantam Books.
Brachman, R., McGuinness, D., Patel-Schneider, P., and Resnick, L. Living with Classic. Principles of Semantic Networks. San Mateo, California: Morgan Kaufman Publishers.
Bulman, D. January 1991. Refining Candidate Objects. Computer Language vol.8(1).
Cant, S., Jeffery, D. and Henderson-Sellers, B. October 1991. A Conceptual Model of Cognitive Complexity of Elements of the Programming Process. New South Wales, Australia University of New South Wales.
Classification Society of North America. Jоurnal of Classification New York, NY: Springer-Verlag. Coad, P. September 1992. Object-Oriented Patterns. Communications of the ACM vol.35(9) Coad, P. 1993. The Object Game. Austin, TX: Object International.
Coombs, C., Raiffa, H., and Thrall, R. 1954. Some Views on Mathematical Models and Measurement Theory. Psychological Review vol.61(2).
Courtois, P. June 1985. On Time and Space Decomposition of Complex Structures. Communications of the ACM vol.2S(6).
Cunningham, W. and Beck, K. July/August 1989. Constructing Abstractions for Object-oriented Abstractions. Journal of Object-Oriented Programming vol.2(2).
Darwin, С. The Origin of Species. Vol.49 of Great Books of the Western World.
Chicago, IL: Encyclopedia Britannica.
Descartes, R. Rules for the Direction ofthe Mind. Vol.31 of Great Books of the Western World. Chicago, IL: Encyclopedia Britannica.
Flood, R., and Carson, E. 1988. Dealing with Complexity. New York, NY: Plenum Press.
Gould, S. June 1992. We Are All Monkey's Uncles. Natural History.
Johnson, R. Documenting Frameworks using Patterns. Vancouver, Canada: OOPSLA'92.
Lakoff, G. 1987. Women, Fire, and Dangerous Things: What Categories Reveal About the Mind Chicago, IL: The University of Chicago Press.
Lefrancois, G. 1977. Of Children: An Introduction to Child Development, 2nd ed. Belmont, CA: Wadsworth.
Lewin, R. 4 November 1988. Family Relationships Are a Biological Conundrum. Science vol.242. Maccoby, M. December 1991. The Innovative Mind at Work. IEEE Spectrum vol.28(12).
Maier, H. 1969. Three Theories of Child Development: The Contributions of Erik H. EricksonJean Piaget and Robert R. Sears and Their Applications. New York, NY: Harper and Row.
May, R. 16 September 1988. How Many Species Are There on Earth? Science vol.241.
Michalski, R., and Steep, R. 1983. Learning from Observation: Conceptual Clustering, in Machine Learning: An Artificial Intelligence Approach ed. R. Michalski, J. Carbonell, and T. Mitchell. Palo Alto, CA: Tioga.
Miller, G. March 1956. The Magical Number Seven, Plus or Minus Two: Some Limits on Our Capacity for Processing Information. The Psychological Review vol.63(2).
Minsky, M. 1986. The Society of Mind New York, NY: Simon and Schuster.
-- April 1970. Form and Content in Computer Science. Journal of the Association for Computing Machinery vol.17(2).
Moldovan, D., and Wu, C. December 1988. A Hierarchical Knowledge-Based System for Airplane Classification. IEEE Transactions on Software Engineering vol.14(12).
Newell, A. 1990. Unified Theories of Congnition. Cambridge, Massachusetts: Harvard University Press. Newell, A., and Simon, H. 1972. Human Problem Solving. Englewood Cliffs, New Jersey: Prentice-Hall.
Papert, S. 1980. Mindstorms: Children Computers and Powerful Ideas. New York, I: Basic Books.
Plato. Statesman. Vol.7 of Great Books of the Western World. Chicago, IL: Encyclopedia Britannica.
Prieto-Diaz, R. and Arango, G. 1991. Domain Analysis and Software Systems Modeling. Las Alamitos, California: Computer Society Press of the IEEE.
Shaw, M. 1989. Larger Scale Systems Require Higher-Level Abstractions. Proceedings of the Fifth International Workshop on Software Specification and Design. IEEE Computer Society.
-- 1990. Elements of a Design Language for Software Architecture. Pittsburgh, PA: Carnegie Mellon University.
-- 1991. Heterogeneous Design Idioms for Software Architecture. Pittsburgh, Pennsylvania: Carnegie Mellon University.
Siegler, R., and Richards, D. 1982. The Development of Intelligence, in Handbook of Human Intelligence, ed. R. Sternberg. Cambridge, London: Cambridge University Press.
Simon, H. 1962. The Architecture of Complexity. Proceedings of the American Philosophical Society. vol.106.
-- 1982. The Sciences of the Artificial. Cambridge, MA: The MIT Press.
Sowa, J. 1984. Conceptual Structures: Information Processing in Mind and Machine. Reading, MA: Addison-Wesley.
-- 1991. Principles of Semantic Networks. San Mateo, California: Morgan Kaufman Publishers.
Stepp, R., and Michalski, R. 1986. Conceptual Clustering of Structured Objects: A Goal-Oriented Approach. Artificial Intelligence vol.28(1).
Stevens, S. June 1946. On the Theory of Scales of Measurement, Science vol.103(2684).
Stillings, N., Feinstein. M., Garfield, J., Rissland, E., Rosenbaum, D., Weisler, S., and Baker-Ward, L. 1987. Cognitive Science: An Introduction. Cambridge, MA: The MIT Press.
Waldrop, M. 1992. Complexity: The Emerging Science at the Edge of Order and Chaos. New York, New York: Simon and Schuster.
В. Объектно-ориентированный анализ
Arango, G. May 1989. Domain Analysis: From Art Form to Engineering Discipline. SIGSOFT Engineering Notes vol.14(3).
Bailin, S. 1988.
Remarks on Object- oriented Requirements Specification. Laurel, MD: Computer Technology Associates.
Bailin, S., and Moore, J. 1987. An Object-oriented Specification Method for Ada. Laurel. MD:
Computer Technology Associates.
Barbier, F. May 1992. Object-oriented Analysis of Systems through their Dynamical Aspects. Journal ofObject-oriented Programming vol.5(2).
Borgida, A., Mylopoulos, J., and Wong, H. 1984. Generalization/Specialization as a Basis for Software Specification, in On Conceptual Modeling: Perspectives from Artificial Intelligence, Databases, and Programming Languages, ed. M. Brodie, J. Mylopoulos, and J. Schmidt. New York, NY: Springer-Verlag.
Cemosek, G., Monterio, E., and Pribyl, W. 1987. An Entity-Relationship Approach to Software Requirements Analysis for Object-Based Development. Houston, TX: McDonnell Douglas Astronautics.
Coad, P. Summer 1989. OOA: Object-oriented Analysis. American Programmer vol.2(7-8).
-- April 1990. New Advances in Object-oriented Analysis. Austin, Texas: Object International.
Coad, P., and Yourdon, E. 1991. Object-oriented Analysis, Second Edition. Englewood Cliffs, New Jersey: Yourdon Press.
Dahl, O-J. 1987. Object-Oriented Specifications, in Research Directions in Object-Oriented Programming, ed. B. Schriver and P. Wegner. Cambridge, MA: The MIT Press.
deChampeaux, D. April 1991. A Comparative Study of Object-oriented Analysis Methods. Palo Alto, California: Hewlett-Packard Laboratories.
-- April 1991. Object-oriented Analysis and Top-Down Software Development. Palo Alto, California: Hewlett-Packard Laboratories.
DeMarco, T. 1979. Structured Analysis and System Specification. Englewood Cliffs, NJ: Prentice-Hall.
Embley, D., Kurtz, В., and Woodfield, S. 1992. Object-oriented Systems Analysis: A Model-Driven Approach. Englewood Cliffs, New Jersey: Yourdon Press.
EVB Software Engineering. 1989. Object-oriented Requirements Analysis. Frederick, MD. Gane, C., and Sarson, T. 1979. Structured Systems Analysis. Englewood Cliffs, NJ: Prentice-Hall.
Hatley, D., and Pirbhai, 1. 1988. Strategies for Real-Time System Specification. New York, NY:
Dorset House.
Ho, D. and Parry, T. July 1991. The Hewlett-Packard Method of Object-oriented Analysis. Palo Alto, California: Hewlett-Packard Laboratories.
Iscoe, N. 1988. Domain Models for Program Specification and Generation. Austin, TX: University of Texas.
Iscoe, N., Browne, J., and Werth, J. 1989. Modeling Domain Knowledge: An Object-oriented Approach to Program Specification and Generation. Austin, TX: The University of Texas.
Lang, N. January 1993. ShIaer-Mellor Object-oriented Analysis Rules. Software Engineering Notes vol.18(1).
Marca, D., and McGowan, C. 1988. SADTTM: Structured Analysis and Design Technique. New York, NY: McGraw-Hill.
Martin, J. and Odell, J. 1992. Object-oriented Analysis and Design. Englewood Cliffs, New Jersey: Prentice-Hall.
McMenamin, S., and Palmer, J. 1984. Essential Systems Analysis. New York, NY: Yourdon Press.
Mellor, S., Hecht, A., Tryon, D. and Hywari, W. September 1988. Object-oriented Analysis: Theory and Practice, Course Notes, from Object-Oriented Programming-Systems Languages, and Applications. San Diego, CA: OOPSLA'88.
Moore, J., and Bailin, S. 1988. Position Paper on Domain Analysis. Laurel, MD: Computer Technology Associates.
Page-Jones, M., and Weiss, S. Summer 1989. Synthesis: An Object-oriented Analysis and Design Method. American Programmer vol.2(7-8).
Rubin, K. and Goldberg, A. September 1992. Object Behavior Analysis. Communications of the ACM vol.35(9).
Saeki, M., Horai, H. and Enomoto, H. May 1989. Software Development Process from Natural Language Specification. Proceedings of the 11th International Conference on Software Engineering. New York, NY: Computer Society Press of the IEEE.
Shemer, I. June 1987. Systems Analysis: A Systemic Analysis of a Conceptual Model. Communications of 'the ACM vol.30(6).
Shlaer, S., and Mellor, S. 1988. Object-oriented Systems Analysis: Modeling the World in Data. Englewood Cliffs, NJ: Yourdon Press.
-- July 1989. An Object- oriented Approach to Domain Analysis. Software Engineering Notes vol.14(5).
-- Summer 1989. Understanding Object-oriented Analysis. American Programmer vol.2(7-8).
-- 1992. Object Lifecycles: Modeling the World in States. Englewood Cliffs, New Jersey: Yourdon Press.
Stoecklin, S., Adams, E., and Smith, S. 1987. Object-oriented Analysis. Tallahassee. FL: East Tennessee State University.
Sully, P. Summer 1989. Structured Analysis: Scaffolding for Object-oriented Development. American Programmer vol.2(7-8).
Tsai, J., and Ridge, J. November 1988. Intelligent Support for Specifications Transformation. IEEE Software vol.5(6).
Veryard, R. 1984. Pragmatic Data Analysis. Oxford, England: Blackwell Scientific Publications.
Ward, P. March 1989. How to Integrate Object Orientation with Structured Analysis and Design. IEEE Software vol.6(2).
Weinberg, G. 1988. Rethinking Systems Analysis and Design. New York, NY Dorset House.
С. Объектно-ориентированные приложения
Abdali, K., Cherry, G., and Soiffer, N. November 1986. A Smalltalk System for Algebraic Manipulation. SIGPLAN Notices vol.21(11).
Abdel-Hamid, T. and Madnick, S. December 1989. Lessons Learned from Modeling the Dynamics of Software Development. Communications of the ACM vol.32(12).
Almes, G., and Holman, C. September 1987. Edmas: An Object-oriented, Locally Distributed Mail System. IEEE Transactions on Software Engineering vol.SE-13(9).
Anderson, D. November 1986. Experience with Flamingo: A Distributed, Object-oriented User Interface System. SIGPLAN Notices vol.21(11).
Archer, J., and Devlin, M. 1987. Rationals Experience Using Ada for Very Large Systems. Mountain View, CA: Rational.
Bagrodia, R., Chandy, M., and Misra, J. June 1987. A Message-Based Approach to Discrete-Event Simulation. IEEE Transactions on Software Engineering vol.SE-13(6).
Barry, B. October 1989. Prototyping a Real-Time Embedded System in Smalltalk. SIGPLAN Notices vol.24(10).
Barry, В., Altoft, J., Thomas D., and Wilson, M.
October 1987. Using Object to Design and Build Radar ESM Systems. SIGPLAN Notices vol.22(12).
Basili, V., Caldiera, G., and Cantone, G. January 1992. A Reference Architecture for the Component Factory. A CM Transactions on Software Engineering and Methodology vol.1(1).
Batory, D. and O'Malley, S. October 1992. The Design and Implementation of Hierarchical Software Systems with Reusable Components. ACM Transactions on Software Engineering and Methodology vol.1(4).
Bezivin, J. October 1987. Some Experiments in Object-oriented Simulation. SIGPLAN Notices vol.22(12).
Bhaskar, K., and Peckol, J. November 1986. Virtual Instruments: Object-oriented Program Synthesis. SIGPLAN Notices vol.21(11).
Bihair, T. and Gopinath, P. December 1992. Object-oriented Real-Time Systems: Concepts and Examples. IEEE Computer vol.25(12).
Bjornerstedt, A., and Britts, S. September 1988. AVANCE: An Object Management System. SIGPLAN Notices vol.23(11).
Bobrow, D., and Stefik, M. February 1986. Perspectives on Artificial Intelligence Programming. Science vol.231.
Boltuck-Pasquier, J., Grossman, E., and Collaud, G. August 1988. Prototyping an Interactive Electronic Book System Using an Object-Oriented Approach. Proceedings of ECOOP'88:
European Conference on Object-oriented Programming. New York, NY: Springer-Verlag.
Bonar, J., Cunningham R., and Schultz, J. November 1986. An Object-oriented Architecture of Intelligent Tutoring Systems. SIGPLAN Notices vol.21(11).
Booch, G. 1987. Software Components with Ada: Structures, Tools, and Subsystems. Menio Park, CA: Benjamin/Cummings.
Borning, A. October 1981. The Programming Language Aspects of ThingLab, a Constraint-Oriented Simulation Laboratory. ACM Transactions on Programming Languages and Systems vol.3(4).
Bowman, W., and Flegal, B. August 1981. ToolBox: A Smalltalk Illustration System. Byte vol.6(8).
Britcher, R., and Craig, J. May 1986. Using Modern Design Practices to Upgrade Aging Software Systems. IEEE Software vol.3(3)
Britton K.
and Parnas, D. December 8, 1981. A-7E Software Module Guide, Report 4702. Washington, D.C.: Naval Research Laboratory.
Brooks, R. 1987. A Hardware Retargetable Distributed Layered Architecture for Mobile Robot Control. Cambridge, Massachusetts: MIT Artificial Intelligence Laboratory.
Brooks, R.and Flynn, A. June 1989. Fast, Cheap, and Out of Control A Robot Invasion of the Solar System. Cambridge, Massachusetts: MIT Artificial Intelligence Laboratory.
Bruck, D. 1988. Modeling of Control Systems with C++ and PHIGS. Proceedings of USENIX C++ Conference. Berkeley, CA: USENIX Association.
Budd, T. January 1989. The Design of an Object-oriented Command Interpreter. Software - Practice and Experience vol.19(1).
C++ Booch Components Class Catalog. 1992. Santa Clara, CA: Rational.
Call, L., Cohrs, D., and Miller, B. October 1987. CLAM - an Open System for Graphical User Interfaces. SIGPLAN Notices vol.22(12).
Campbell, R., Islam, N., and Madany, P. 1992. The Design of an Object-oriented Operating System: A Case Study of Choices. Vancouver, Canada: OOPSLA'92.
Caplinger, M. October 1987. An Information System Based on Distributed Objects. SIGPLAN Notices vol.22(i2).
Cargill, T. November 1986. Pi: A Case Study in Object-oriented Programming. SIGPLAN Notices vol.21(11).
Carroll, M. September 1990. Building Reusable C++ Components. Murray Hills, New Jersey: AT&T Bell Laboratories.
Cmelik, R., and Genani, N. May 1988. Dimensional Analysis with C++. IEEE Software vol.5(3).
Coggins, J. September 1990. Design and Management of C++ Libraries. Chapel Hill, North Carolina: University of North Carolina.
Cointe, P., Briot, J., and Serpette, B. 1987. The Formes System: A Musical Application of Object-oriented Concurrent Programming, in Object-oriented Concurrent Programming, ed. Yonezawa and M. Tokoro. Cambridge, MA: The MIT Press.
Collins, D. 1990. What is an Object-oriented User Interface? Thornwood, New York: IBM Systems Research Education Center.
Comeau, G. March 1991.
C++ In the Real World Interviews with C++ Application Developers. The C++ Report vol.3(3).
Coplien, J. September 1991. Experience with CRC Cards in AT&T. The C++ Report vol.3(8). Coutaz, J. September 1985. Abstractions for User Interface Design. IEEE Computer vol.18(9). Custer, H. 1993. Inside Windows NT. Redmond, Washington: Microsoft Press.
Dasgupta, P. November 1987. A Probe-Based Monitoring Scheme for an Object-oriented Operating System. SIGPLAN Notices vol.21(11).
Davidson, С., and Moseley, R. 1987. An Object-oriented Real-Time Knowledge-Based System. Albuquerque, NM: Applied Methods.
Davis, J. and Morgan, T. January 1993. Object-oriented Development at Brooklyn Union Gas. IEEE Software vol.10(1).
deChampeaux, D., Anderson, A., Lerman, D., Gasperina, M., Feldhousen, E., Glei, M., Fulton, F., Groh, C., Houston, D., Monroe, C., Raj, Rommel, and Shultheis, D. October 1991. Case Study of Object-oriented Software Development. Palo Alto, California Hewlett-Packard Laboratories.
Dietrich, W., Nackman, L, and Gracer, F. October 1989. Saving a Legacy with Objects. SIGPLAN Notices vol.24(10).
Dijkstra, E. May 1968. The Structure of the "THE" Multiprogramming System. Communications of the ACMvol.11(5).
Durand, G., Benkiran, A., Durel, C., Nga, H., and Tag, M. 9 March 1988. Distributed Mail Service in CSE System. Paris, France: Synergie Informatique et Development.
Englemore, R., and Morgan, T. 1988. Blackboard Systems. Wokingham, England: Addison-Wesley.
Epstein, D., and LaLonde, W. September 1988. A Smalltalk Window System Based on Constraints. SIGPLAN Notices vol.23(11).
Ewing, J. November 1986. An Object-oriented Operating System Interface. SIGPLAN Notices vol.21(11).
Fenton, J., and Beck, K. October 1989. Playground: An Object-oriented Simulation System with Agent Rules for Children of All Ages. SIGPLAN Notices vol.24(10).
Fischer, G. 1987. An Object-oriented Construction and Tool Kit for Human-Computer Communication. Boulder, CO: University of Colorado Department of Computer Science and Institute of Cognitive Science.
Foley, J., and van Dam, A. 1982. Fundamentals of Interactive Computer Graphics. Reading, MA: Addison-Wesley.
Frankowski, E. 20 March 1986. Advantages of the Object Paradigm for Prototyping. Golden Valley, MN: Honeywell.
Freburger, K. October 1987. RAPID: Prototyping Control Panel Interfaces. SIGPLAN Notices vol.22(12).
Freitas, M., Moreira, A., and Guerreiro, P. July/August 1990. Object-oriented Requirements Analysis in an Ada Project. Ada Letters vol.X(6).
Funk, D. 1986. Applying Ada to Beech Starship Avionics. Proceedings of the First International
Conference on Ada Programming Language Applications for the NASA Space Station. Houston, TX: NASA Lyndon B.Johnson Space Center.
Garrett, N. and Smith, K. November 1986 Building a Timeline Editor from Prefab Parts: The Architecture of an Object-Oriented Application. SIGPLAN Notices vol.21(11).
Goldberg, A. 1978. Smalltalk in the Classroom. Palo Alto, CA: Xerox Palo Alto Research Center.
Goldberg, A. and Rubin, K. October 1990. Taming Object-oriented Technology. Computer Language vol.7(10).
Goldstein, N. and Alger, J. 1992. Developing Object-oriented Software for the Macintosh. Reading, Massachusetts: Addison-Wesley Publishing Company.
Gorlen, K. December 1987. An Object-oriented Class Library for C++ Programs. Software - Practice and Experience vol.17(12).
Gray, L. 1987. Transferring Object-oriented Design Techniques into Use: AWIS Experience. Fairfax, VA: TRW Federal Systems Group.
Grimshaw, A., and Liu, J. October 1987. Mentat: An Object-oriented Macro Data Flow System. SIGPLAN Notices vol.22(12).
Grossman, M., and Ege, R. October 1987. Logical Composition of Object-oriented Interfaces. SIGPLAN Notices vol.22(12).
Gutfreund, S. October 1987. Manipllcons in ThinkerToy. SIGPLAN Notices vol.22(12). Gwinn, J. February 1992. Object-oriented Programs in Realtime. SIGPLAN Notices vol.27(2).
Harrison, W., Shilling, J., and Sweeney, P. October 1989. Good News, Bad News: Experience Building a Software Development Environment Using the Object-oriented Paradigm.
SIGPLAN Notices vol.24(10).
Hekmatpour, A., Orailoglu, A., and Chau, P. April 1991. Hierarchical Modeling of the VLSI Design Process. IEEE Expert vol.6(2).
Hollowell, G. November 1991. Leading the U.S. Semiconductor Manufacturing Industry Toward an Object-oriented Technology Standard. Hotline on Object-oriented Technology vol.3(1).
Ingalls, D., Wallace, S., Chow, Y., Ludolph, F., and Doyle, K. September 1988. Fabrik; A Visual Programming Environment. SIGPLAN Notices vol.23(11).
Jacky, J., and Kalet, I. November 1986. An Object-oriented Approach to a Large Scientific Application. SIGPLAN Notices vol.21(11).
Jacobson, I. January 1993. Is Object Technology Software's Industrial Platform? IEEE Software vol.10(1).
Jerrell, M. October 1989. Function Minimization and Automatic Differentiation using C++. SIGPLAN Notices vol.24(10).
Johnson, R., and Foote, B. June/July 1988. Designing Reusable Classes. Journal of Object-oriented Programming vol.1(2).
Jones, M., and Rashid, R. November 1986. Mach and Matchmaker: Kernel and Language Support fo Object-oriented Distributed Systems. SIGPLAN Notices vol.21(11).
Jurgen, R. May 1991. Smart Cars and Highways Go Global. IEEE Spectrum vol.28(5).
Kamath, Y. and Smith, J. November/December 1992. Experiences in C++ and O-O Design. Journal of Object-oriented Programming vol.5(7).
Kay, A., and Goldberg, A. March 1977. Personal Dynamic Media. IEEE Computer.
Kerr, R., and Percival, D. October 1987. Use of Object-oriented Programming in a Time Series Analysis System. SIGPLAN Notices vol.22(12).
Kiyooka, G. December 1992. Object-oriented DLLs. Byte vol.17(14).
Kozaczynski, W. and Kuntzmann-Combelles, A. January 1993. What it Takes to Make O-O Work. IEEE Software vol.10(1).
Krueger, C. June 1992. Software Reuse. ACM Computing Surveys vol.24(2).
Kuhl, F. 1988. Object-oriented Design for a Workstation for Air Traffic Control. McLean, VA: The MITRE Corporation.
LaPolla, M. 1988. On the Classificaition of Object-oriented Design. The Object-oriented Design of the Airland Battle Management Menu System.
Austin, TX Lockheed Software Technology Center.
Lea, D. 12 August 1988. User's Guide to GNU C++ Library. Cambridge, MA: Free Software Foundation.
-- 1988. The GNU C++ Library. Proceedings of USENIX C++ Conference. Berkeley, CA: USENIX Association.
Leathers, B. July 1990. Cognos and Eiffel A Cautionary Tale. Hotline on Object-Oriented Technology vol.1(9).
Ledbetter. L, and Cox. B. June 1985. Software-lCs. Byte vol.10(6).
Lee, K., and Rissman, M. February 1989. Object-oriented Solution Example: A Flight Simulator Electrical System. Pittsburgh, PA: Software Engineering Institute.
Lee, K., Rissman, M., D'lppolito, R., Plinta, C. and Van Scoy, R. December 1987. An OOD Paradigm for Flight Simulators, Report CMU/SE1-87-TR-43. Pittsburgh, PA: Software Engineering Institute.
Levy, P. 1987. Implementing Systems Software in Ada. Mountain Vie, CA: Rational.
Lewis, J., Henry, S., Kafura, D., and Shulman, R. July/August 1992. On the Relationship Between the Object-oriented Paradigm and Software Reuse: An Empirical Investigation.Jounia/ of Object-orientedProgramming vol.5 (4).
Linton, M., Vlissides, J. and Calder, P. February 1989. Composing User Interfaces with Interviews. IEEE Computer vol.22(2).
Liu, L, and Horowitz, E. February 1989. Object Database Support for a Software Project - Management Environment. SIGPLAN Notices vol.24(2).
Locke, D., and Goodenough, J. 1988. A Practical Application of the Ceiling Protocol in a Real-Time System, Report CMU/SEI-88-SR-3. Pittsburgh, PA: Software Engineering Institute.
Love, T. 1993. Object Lessons. New York, New York: SIGS Publications. Lu, Cary. December 1992. Objects For End Users. Byte vol.17(14).
Madany, P., Leyens, D., Russo, V., and Campbell, R. 1988. A C++ Class Hierarchy for Building UNIX-like File Systems. Proceedings of USENIX C++ Conference Berkeley, CA: USENIX Association.
Madduri, H., Raeuchle, T., and Silverman, J. 1987. Object-Oriented Programming for Fault-Tolerant Distributed Systems. Golden Valley, MN: Honeywell Computer Science Center.
Maloney, J., Borning, A., and Freeman-Benson, B. October 1989. Constraint Technology for User Interface Construction on in ThingLab II. SIGPLAN Notices vol.24(10).
McDonald, J. October 1989. Object-oriented Programming for Linear Algebra. SIGPLAN Notices vol.24(10)
Mentor's Lessons in the School of Hard Knocks. January 25, 1993. Business Week.
Meyrowitz, N. November 1986. Intermedia Architecture and Construction of an Object-oriented Hypermedia System and Applications Framework. SIGPLAN Notices vol.21(11).
Miller, M., Cunningham, H., Lee. С., and Vegdahl, S. November 1986. The Application Accelerator Illustration System. SIGPLAN Notices vol.21(11).
Mohan, L, and Kashyap, R. May 1988. An Object-Oriented Knowledge Representation for Spatial Information. IEEE Transactions on Software Engineering vol.14(5).
Morgan, Т. and Davis, J. March 1991. Large-Scale Object Systems Development. Hotline on Object-oriented Technology vol.2(5).
Mraz, R. December 1986. Performance Evaluation of Parallel Branch and Bound Search with the Intel iPSE Hypercube Computer. Wright-Patterson Air Force Base, Ohio: Air Force Institute of Technology.
Muller, H., Rose, J., Kempt, J., and Stansbury, T. October 1989. The Use of Multimethods and Method Combination in a CLOS-Based Window Interface. SIGPLAN Notices vol.24(10).
Murphy, E. December 1988. All Aboard for Solid State. IEEE Spectrum vol.25(13).
Nerson, J. September 1992. Applying Object-oriented Analysis and Design. Communications of the ACM vol.35(9).
NeXT Embraces a New Way of Programming. 25 November 1988. Science vol. 242.
Orden, E. 1987. Application Talk. HOOPLA: Hooray for Object-oriented Programming Languages vol.1(1). Everette, WA: Object-oriented Programming for Smalltalk Application Developers Association.
Orfali, R. and Harkey, D. 1992. Client/Server Programming with OS/2. New York, New York: Van Nostrand Reinhold.
Oshima, M., and Shirai, Y. July 1983. Object Recogration Using Three-Dimensional Information. IEEE Transactions on Pattern Analysis and Machine Intelligence vol.5(4).
Page, Т., Berson, S., Cheng, W., and Muntz, R. October 1989. An Object-oriented Modeling Environment. SIGPLAN Notices vol.24(10).
Pashtan, A. 1982. Object-oriented Operating Systems: An Emerging Design Methodology. Proceedings of the ACM'82 Conference. New York Association of Computing Machinery.
Piersol, K. November 1986. Object-oriented Spreadsheets: The Analytic Spreadsheet Package. SIGPLAN Notices vol.21(11).
Pinson, L. and Wiener, R. 1990. Applications of Object-oriented Programming. Reading, Massachusetts: Addison-Wesley Publishing Company.
Pittman, M. January 1993. Lessons Learned in Managing Object-oriented Development. IEEE Software vol.10(1).
Plinta, C., Lee, K., and Rissman, M. 29 March 1989. A Model Solution for C31: Message Translation and Validation. Pittsburgh, PA: Software Engineering Institute.
Pope, S. April/May 1988. Building Smalltalk-80-based Computer Music Too\s. Journal of Object-oriented Programming vol.1(1).
Raghavan, R. 1990. Taming Windows 3.0 and DOS Using C+ +. Lake Oswego, Oregon: Wyatt Software. Rockwell International. 1989. Rockwell Advanced Railroad Electronic Systems. Cedar Rapids, IA. Rombach, D. March 1990. Design Measurement: Some Lessons Learned. IEEE Software vol.7(2).
Rubin, K., Jones, P., Mitchell, C., and Goldstein, T. September 1988. A Smalltalk Implementation of an Intelligent Operator's Associate. SIGPLAN Notices vol.23(11).
Rubin, R., Walker, J., and Golin, E. October 1990. Early Experience with the Visual Programmer's WorkBench. IEEE Transactions on Software Engineering vol.16(10).
Ruspini, E., and Fraley, R. 1983. ID: An Intelligent Information Dictionary System, in Entity-Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Russo, V., Johnston, G., and Campbell, R. September 1988. Process Management and Exception Handling in Multiprocessor Operating Systems Using Object-oriented Design Techniques. SIGPLAN Notices vol.23(11).
Sampson, J., and Womble, B. 1988.
SEND: Simulation Environment for Network Design. Dallas, TX: Southern Methodist University.
Santori, M. August 1990. An Instrument that Isn't Really. IEEE Spectrum vol.27(8).
Scaletti, C., and Johnson, R. September 1988. An Interactive Environment for Object-oriented Music Composition and Sound Synthesis. SIGPLAN Notices vol.23(11).
Schindler, J. and Joy, S. February 1992. An Introduction to Object Technology at Liberty Mutual. Liberty Mutual Information Systems Research and Development.
Schoen, E., Smith, R., and Buchanan, B. December 1988. Design of Knowledge-Based Systems with a Knowledge-Based Assistant. IEEE Transactions on Software Engineering vol.14(12).
Schulert, A., and Erf, K. 1988. Open Dialogue: Using an Extensible Retained Object Workspace to Support a UIMS. Proceedings of USENIX C++ Conference Berkeley, CA: USENIX Association.
Scott. R., Reddy, P., Edwards. R., and Campbell. D. 1988 GPIO: Extensible Objects for Eleclronic Design. Proceedings of USENIX C++ Conference Berkeley. CA: USENIX Association.
Smith, R., Barth, P., and Young, R. 1987. A Substrate for Object-oriented Interface Design. Research Directions in Object-oriented Programming. Cambridge, MA: The MIT Press.
Smith, R., Dinitz, R., and Barth, P. November 1986. Impulse-86: A Substrate for Object-oriented Interface Design. SIGPLAN Notices vol.21(11).
Sneed, H., and Gawron, W. 1983. The Use of the Entity/Relationship Model as a Schema for Organizing the Data Processing Activities at the Bavarian Motor Works, in Entity-Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Snodgrass, R. 1987. An Object-oriented Command Language, in Object-oriented Computing: Implementations vol.2. ed. G. Peterson. New York, NY: Computer Society Press of the IEEE.
Software Made Simple. September 30, 1991. Business Week.
Sridhar, S. September 1988. Configuring Stand-Alone Smalltalk-80 Applications. SIGPLAN Notices vol.23(11).
Stadel, M. January 1991.
Object- oriented Programming Techniques to Replace Software Components on the Fly in a Running Program. SIGPLAN Notices vol. 26 (1).
Stevens, A. 1992. C++ Database Development. New York, New York: MIS Press.
Stokes, R. 1988. Prototyping Database Applications with a Hybrid of C++ and 4GL. Proceedings of USENIX C++ Conference. Berkeley, CA: USENIX Association.
Szcur, M., and Miller, P. September 1988. Transportable Applications Environment(TAE) PLUS:
Experiences in "Object"ively Modernizing a User Interface Environment. SIGPLAN Notices vol.23(11).
Szekely, P., and Myers, B. September 1988. A User Interface Toolkit Based on Graphical Objects and Constraints. SIGPLAN Notices vol.23(11).
Tanner, J. April 1986. Fault Tree Analysis in an Object-oriented Entironment. Mountain View, CA: IntelliCorp.
Taylor, D. 1992. Object-Oriented Information Systems. New York, New York John Wiley and Sons.
Temte, M. November/December 1984. Object-oriented Design and Ballistics Software. Ada Letters vol.4(3).
Tripathi, A., and Aksit. M. November/December 1988. Communication, Scheduling and Resource Management in SINA. Journal ofObject-oriented Programming vol.1(4).
Tripathi, A., Ghonami, A., and Schmitz, T. 1987. Object Management in the NEXUS Distributed Operating System. Proceedings of the Thirty-second IEEE Computer Society International Conference. New York, NY: Computer Society Press of the IEEE.
Ursprung, P., and Zehnder, C. 1983. HIQUEL: An Interactive Query Language to Define and Use Hierarchies, in Entity-relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
van der Meulen, P. October 1987. INSIST: Interactive Simulation in Smalltalk. SIGPLAN Notices vol.22(12).
Vernon, V. September/October 1989. The Forest for the Trees. Programmer's Journal vol.7(5). Vilot, M. Fall 1990. Using Object-oriented Design and C++. The C++ Journal vol.1(1).
Vines, D., and King, T. 1987. Experiences in Building a Prototype Object-oriented Framework in Ada.
Minneapolis, MN: Honeywell.
VlissidesJ., and Linton, M. 1988. Applying Object-oriented Design to Structure Graphics. Proceedings of USENIX C++ Conference Berkeley, CA: USENIX Association.
Volz, R. Mude, Т., and Gal, D. 1987. Using Ada as a Programming Language for Robot-Based Manufacturing Cells, in Object-oriented Computing; Concepts vol.1. ed. G. Peterson. New York, NY: Computer Society Press of the IEEE.
Walther, S., and Peskin, R. October 1989. Strategies for Scientific Prototyping in Smalltalk. SIGPLAN Notices vol.24(10).
Wasserman, A. and Pircher, P. January 1991. Object-oriented Structured Design and C++. Computer Language vol.8(1).
Weinand, A., Gamma, E., and Marty, R. September 1988. ET++ - An Object-oriented Application Framework in C++. SIGPLAN Notices vol.23(11).
Welch, B. July/August 1991. Securities Objects - The Complexity. Object Magazine vol.1(2).
White, S. October 1986. Panel Problem: Software Controller for an Oil Hot Water Heating System. Proceedings of COMPSAC. New York, NY: Computer Society Press of the IEEE.
Wirfs-Brock, R. September 1988. An Integrated Color Smalltalk-80 System. SIGPLAN Notices vol.23(11).
-- October 1991. Object-oriented Frameworks. American Programmer vol. 4(10).
WOSA Extensions for Financial Services. December 1992. Banking Systems Vendor Council.
Wu, P. January 1992. An Object-oriented Specification for a Compiler. SIGPLAN Notices vol.27(1).
Yoshida, N. and Hino, K. September 1988. An Object-oriented Framework of Pattern Recognition. SIGPLAN Notices vol.23(11).
Yoshida, Т., and Tokoro, M. 31 March 1986. Distributed Queueing Network Simulation:. An Application of a Concurrent Object-oriented Language. Yokohama, Japan: Keio University.
Young, R. October 1987. An Object-oriented Framework for Interactive Data Graphics. SIGPLAN Notices vol.22(12).
D. Объектно-ориентированные архитектуры
Athas, W., and Seitz, C. August 1988. Multicomputers: Message-Passing Concurrent Computers. IEEE Computer vol.21(8).
Dahlby, S., Henry, G., Reynold., D., and Taylor, P. 1982.
The IBM System/38: A High Level
Machine, in Computer Structures: Principles and Examples, ed. G. Bell and A. Newell. New York, NY: McGraw-Hill.
Dally, W. and Kajiya, J. March 1985. An Object-oriented Architecture. SIGARCH Newsletter vol.13(3).
Fabry, K. 1987. Capability-Based Addressing, in Object-oriented Computing: Implementations vol.2. ed. G. Peterson. New York, NY: Computer Society Press of the IEEE.
Flynn, M. October 1980. Directions and Issues in Architecture and Language. IEEE Computer vol.13(10).
Harland, D., and Beloff, B. December 1986. Microcoding an Object-oriented Instruction Set. Computer Architecture News vol.14(5).
Hillis, D. 1985. The Connection Machine. Cambridge, Massachusetts: The MIT Press. Iliffe, J. 1982. Advanced Computer Design. London, England: Prentice/Hall International. Intel. 1981. iAPX432 Object Primer. Santa Clara, CA.
Ishikawa, Y., and Tokoro, M. March 1984. The Design of an Object-oriented Architecture. SIGARCH Newsletter vol.12(3).
Kavi, K., and Chen, D. 1987. Architectural Support for Object-oriented Languages. Proceeding of the Thirty-second IEEE Computer Society International Conference. New York, NY: Computer Society Press of the IEEE.
Lahtinen, P. September/October 1982. A Machine Architecture for Ada. Ada Letters vol.2(2).
Lampson. В., and Pier, K. January 1981. A Processor for a High-Performance Personal Computer, in The Dorado: A High Performance Personal Computer, Report CSL-81-1. Palo Alto, CA: Xerox Palo Alto Research Center.
Langdon, G. 1982. Computer Design. San Jose, CA: Computeach Press. Levy, H. 1984. Capability-Based Computer Systems. Bedford, MA: Digital Press.
Lewis, D., Galloway, D., Francis, R., and Thomson, B. November 1986. Swamp: A Fast Processor for Smalltalk-80. SIGPLAN Notices vol.21(11).
Mashburn, H. 1982. The C.mmp/Hydra Project: An Architectural Overview, in Computer Structures: Principles and Examples, ed. G. Bell and A. Newell. New York, NY: McGraw-Hill.
Myers, G. 1982. Advances in Computer Architecture, 2nd ed.
New York, NY: John Wiley and Sons.
Rattner, J. 1982. Hardware/Software Cooperation in the iAPX-432. Proceedings of the Symposium on Architectural Support for Programming Languages and Operating Systems. New York, NY: Association of Computing Machinery.
Rose, J. September 1988. Fast Dispatch Mechanisms for Stock Hardware. SIGPLANNotices vol.23(11).
Samples, D., Ungar, D., and Hilfinger, P. November 1986. SOAR: Smalltalk Without Bytecodes. SIGPLAN Notices vol.21(11).
Soltis, R., and Hoffman, R. 1987. Design Considerations for the IBM System/38, in Object-oriented Computing Implementations vol.2. ed. G. Peterson. New York, NY: Computer Society Press of the IEEE.
Thacker, C., McCreight. E., Lampson, В., Sproull, R., and Boggs, D. August 1979. Alto: A Personal Computer, Report CSL-79-11. Palo Alto, CA: Xerox Palo Alto Research Center.
Ungar, D. 1987. The Design and Evaluation of a High-Performance Smalltalk System. Cambridge, MA: The MIT Press.
LJngar, D. and Patterson, D. January 1987. What Price Smalltalk? IEEE Computer vol.20(1).
Ungar, D., Blau, R., Foley, P., Samples, D., and Patterson, D. March 1984. Architecture of SOAR:
Smalltalk on a RISC. SIGARCH Newsletter vol.12(3).
Wah, В., and Li, G. April 1986. Survey on Special Purpose Computer Architectures for AI. SIGART Newsletter, no. 96.
Wulf, C. January 1980. Trends in the Design and Implementation of Programming Languages. IEEE Computer vol.13(1).
Wulf, W., Levin, R., and Harbison. S. 1981. HYDRA/C.mmp: An Experimental Computer System. New York, NY: McGraw-Hill.
E. Объектно-ориентированные СУБД
Alford, M. 1983. Derivation of Element-Relation-Attribute Database Requirements by Decomposition of System Functions, in Entity-Relationship Approach to Software Engineering. ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Andleigh, P. and Gretzinger, M. 1992. Distributed Object-Oriented Data-Systems Design. Englewood Cliffs, New Jersey: Prentice-Hall.
Atkinson, M., Bailey, P., Chisholm, K., Cockshott, P., and Morrison, R. 1983.
An Approach to Persistent Programming. The Computer Journal vol. 26(4).
Atkinson, M., and Buneman, P. June 1987. Types and Persistence in Database Programming Languages. ACM Computing Surveys vol.19(2).
Atkinson, M., and Morrison, R. October 1985. Procedures as Persistent Data Objects. ACM Transactions on Programming Languages and Systems vol. 7(4).
Atwood, Т. February 1991. Object-Oriented Databases. IEEE Spectrum vol. 28(2).
Bachman, C. 1983. The Structuring Capabilities of the Molecular Data Model, in Entity-Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Batini, C., and Lenzerini, M. 1983. A Methodology for Data Schema Integration in the Entity-Relationship Model, in Entity-Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Beech, D. 1987. Groundwork for an Object Database Model, in Research Directions in Object-oriented Programming. ed. B. Schriver and P. Wegner. Cambridge. MA: The MIT Press.
-- September 1988. Intensional Concepts in an Object Database Model. SIGPLAN Notices vol.23(11).
Bertino, E. 1983. Distributed Database Design Using the Entity-Relationship Model, in Entity-Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam , The Netherlands: Elsevier Science.
Blackwell, P., Jajodia, S. and Ng, P. 1983. A View Database Management Systems as. Abstract Data Types, in Entity-Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Bloom, T. October 1987. Issues in the Design of Object-oriented Database Programming Languages. SIGPLAN Notices vol.22(12).
Bobrow, D., Fogelsong.D., and Miller, M. 1987. Definition Group: Making Sources into First-class Objects, in Research Directions in Object-oriented Programming, ed. B. Schriver and P. Wegner. Cambridge, MA: The MIT Press.
Brathwait, K. 1983. An Implementation of A Databases Using the Entity-Relationship (E-R) Approach, in Entity-Relationship Approach to Software Engineering, ed. C.
Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Breazeal, J., Blattner, M., and Burton, H. 28 March 1986. Data Standardization Through the Use of Data Abstraction. Livermore, CA: Lawrence Livermore National Laboratory.
Brodie, M. 1984. On the Development of Data Models, in On Conceptual Modeling: Perspectives from Artificial Intelligence, Databases, and Programming Languages, ed. M. Brodie, J. Mylopoulos, and J. Schmidt. New York, NY: Springer-Verlag.
Brodie, M., and Ridjanovic, D. 1984. On the Design and Specification of Database Transactions, in On Conceptual Modeling: Perspectives from Artificial Intelligence Databases and Programming Languages, ed. M. Brodie, J. Mylopoulos, andJ. Schmidt. New York, NY: Springer-Verlag.
Butterworth, P., Otis, A. and Stein, J. October 1991. The GemStone Object Database Management System. Communications of the ACM vol.34(10).
Carlson, C., and Arora, A. 1983. UPM: A Formal Tool for Expressing Database Update Semantics, in Entity-Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Casanova, M. 1983. Designing Entity-Relationship Schemes for Conventional Information Systems, in Entity-Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Cattell, R. 1991. Object Data Management. Reading, Massachusetts: Addison-Wesley Publishing Company.
-- May 1983. Design and Implementation of a Relationship-Entity-Datum Data Model, Report CSL-83-4. Palo Alto, CA: Xerox Palo Alto Research Center.
Chen, P. 1983. ER - A Historical Perspective and Future Directions, in Entity-Relationship Approach to Software Engineering, ed. C. Davis al. Amsterdam, The Netherlands: Elsevier Science.
-- March 1976. The Entity-Relationship Model - Toward a Unified View of Data. ACM Transactions on Database Systems vol.1(1).
Claybrook, В., Claybrook, A., and Williams, J. January 1985. Defining Database Views as Data Abstractions. IEEE Transactions on Software Engineering vol.SE-11(1).
D'Cunha, A., and Radhakrishnan, T. 1983. Applications of E-R Concepts to Data Administration, Entity-Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Date, C. 1981, 1983. An Introduction to Database Systems. Reading, MA: Addison-Wesley.
-- 1986. Relational Database-. Selected Writings. Reading, MA: Addison-Wesley.
-- 1987. The Guide to The SQL Standard. Reading, MA Addison-Wesley.
Duhl, J., and Damon, C. September 1988. A Performance Comparison of Object and Relational Databases Using the Sun Benchmark. SIGPLAN Notices vol. 23(11).
Harland, D., and Beloff, B. April 1987. OBJEKT - A Persistent Object Store with an Integrated Garbage Collector. SIGPLAN Notices vol.22(4).
Hawryszkiewycz, 1.1984. Database Analysis and Design. Chicago, IL: Science Research Associates.
Higa, K., Morrison, M., Morrison, J. and Sheng, O. June 1992. An Object-Oriented Methodology for Knowledge Bas/Database Coupling. Communications of the ACM vol.35(6).
Hull, R., and King, R. September 1987. Semantic Database Modeling: Survey, Applications, and Research Issues. ACM Computing Surveys vol.19(3).
Jajodia, S., Ng, P., and Springsteel, F. 1983. On Universal and Representative Instances for Inconsistent Databases, in Entity-Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Ketabchi, M., and Berzins, V. January 1988. Mathematical Model of Composite Objects and Its Application for Organizing Engineering Databases. IEEE Transactions on Software Engineering vol.14(1).
Ketabchi M., and Wiens, R. 1987. Implementation of Persistent Multi-User Object-oriented Systems. Proceedings of the Thirty-second IEEE Computer Society International Conference. New York, NY: Computer Society Press of the IEEE.
Khoshafian, S., and Abnous, R. 1990. Object-Orientation: Concepts, Languages, Databases, User, Interfaces. New York, New York: John Wiley and Sons.
Kim, W., and Lochovsky, K. 1989.
Object- oriented Concepts, Databases, and Applications. Reading, MA: Addison-Wesley.
Kim, W., Ballou, N., Chou, H., Garze, J., Woelk, D., and Banerjee, J. September 1988. Integrating an Object-oriented Programming System with a Database System. SIGPLAN Notices vol.23(11).
Kim, W., Banerjee, J., Chou, H., Garza, J., and Woelk, D. October 1987. Composite Object Support in an Object-oriented Database System. SIGPLAN Notices vol.22(12).
Kung, С. Object Subclass Hierarchy in SQL A Simple Approach. Communcations of the ACM vol.33(7).
Laenens, E., and Vermeir, D. August 1988. An Overview of OOPS+, An Object-oriented Database Programming Language. Proceedings of ECOOP'88. European Conference on Object-oriented Programming. New York, NY: Springer-Verlag.
Lamb, C., Landis, G., Orenstein, J., and Weinreb, D. October 1991. The ObjectStore Database System. Communications of the ACM vol.34(10).
Larson, J. and Dwyer, P. 1983. Defining External Schemas for an Entity-Relationship Database, in Entity-Relationship Approach to Software Engineering, ed.C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Maier, D., and Stein, J. 1987. Development and Implementation of an Object-oriented DBMS, in Research Directions in Object-oriented Programming, ed. B. Schriver and P. Wegner. Cambridge, MA: The MIT Press.
Margrave, G., Lusk, E., and Overheek, R. 1983. Tools for the Creation of IMS Database Designs from Entity-Relationship Diagrams, in Entity-Relationship Approach to Software Engineering. ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Mark, L, and Poussopoulos, N. 1983. Integration of Data, Schema, and Meta-schema in the Context of Self-documenting Data Models, in Entity-Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Markowitz, V., and Makowsky, J. August 1990. Identifying Extended Entity-Relationship Object Structures in Relational Schemas. IEEE Transactions on Software Engineering vol.16(8).
Marti, R. 1983. Integrating Database and Program Descriptions using an ER Data Dictionary, in Entity-Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Merrow, Т., and Laursen, J. October 1987. A Pragmatic System for Shared Persistent Objects. SIGPLAN Notices vol.22(12).
Mitchell, J., and Wegbreit; B. 1977. Schemes: A High-Level Data Structuring Concept, in Current * Trends in Programming Methodology Data Structuring vol.14 ed. R. Yeh. Englewood Cliffs, NJ: Prentice-Hall.
Morrison, R., Atkinson, M., Brown, A., and Dearie, A. April 1988. Bindings in Persistent Programming Languages. SIGPLAN Notices vol.23(4).
Moss, E., Herlihy, M., and Zdonik S. September 1988. Object-oriented Databases. Course Notes, from Object-oriented Programming Systems Language, and Applications. San Diego, CA: OOPSLA'88.
Moss, J. August 1992. Worcing with Persistent Objects To Swizzle or Not to Swizzle. IEEE Transactions on Software Engineering vol.18(8).
Nastos, M. January 1988. Databases, Etc. HOOPLA: Hooray for Object-oriented Programming Languages vol.1(2). Everette. WA: Object-oriented Programming for Smalltalk Application Developers Association.
Navathe, S., and Cheng, A. 1983. A Methodology for Database Schema Mapping from Extended Entity Relationship Models into the Hierarchical Model, in Entity-Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Ontologic. 1987. Vbase Technical Overview. Billerica, MA. Oracle. 1989. Oracle for Macintosh: Reference, Version 1.1. Belmont, CA.
Penny, J., and Stein, J. October 1987. Class Modification in the GemStone Object-oriented DBMS. SIGPLAN Notices vol.22(12).
Peterson, R. 1987. Object-oriented Database Design, in Object-oriented Computing Implementation vol.2. ed. G. Peterson. New York, NY: Computer Society Press of the IEEE.
Sakai, H. 1983. Entity-Relationship Approach to Logical Database Design, in Entity-Relationship Approach to Software Engineering, ed. C.
Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Skarra, A., and Zdonik, S. 1987. Type Evolution in an Object-oriented Database, in Research Directions in Object-oriented Programming, ed. B. Schriver and P. Wegner. Cambridge, MA: The MIT Press.
Skarra, A., and Zdonik, S. November 1986. The Management of Changing Types in an Object-oriented Database. SIGPLAN Notices vol.21(11).
Smith, D., and Smith, J. 1980. Conceptual Database Design, in Tutorial on Software Design
Techniques, 3rd ed. ed. P. Freeman and A. Wasserman. New York, NY: Computer Society Press of the IEEE.
Smith, J., and Smith, D. Database Abstractions: Aggregation and Generalization. ACM Transactions on Database Systems vol.2(2).
Smith, K., and Zdonik, S. October 1987. Intermedia: A Case Study of the Differences Between Relational and Object-oriented Database Systems. SIGPLAN Notices vol.22(12).
Stein, J. March 1988 Object-oriented Programming and Database Design. Dr. Dobb's Journal vol.13(3).
-- March 1988. Object-oriented Programming and Database Design. Dr. Dobb's Journal of Software Tools for the Professional Programmer, no. 137.
Teorey, Т., Yang, D., and Fry, J. June 1986. A Logical Design Methodology for Relational Databases Using the Extended Entity-Relationship Model. ACM Computing Surveys vol.18(2).
Thuraisingham, M. October 1989. Mandatory Security in Object-Oriented Database Systems. SIGPLAN Notices vol.24(10).
Veloso, P., and Furtado, A. 1983. View Constructs for the Specification and Design of External Schemas, in Entity-Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Wiebe, D. November 1986. A Distributed Repository for Immutable Persistent Objects. SIGPLAN Notices vol.21(11).
Wiederhold G. December 1986. Views, Objects, and Databases. IEEE Computer vol.19(12).
Wile, D., and Allard D May 1982. Worlds: an Organizing Structure for Object-bases. SIGPLAN Notices vol.19(5).
Zdonik, S., and Maier. D. 1990. Reading in Object-oriented Database Systems.
San Mateo, CA: Morgan Kaufmann.
Zhang, Z., and Mendelzon, A. 1983. A Graphical Query Language for Entity-Relationship Databases, in Entity-Relationship Approach to Software Engineering, ed. C. David et al. Amsterdam, The Netherlands: Elsevier Science.
F. Объектно-ориентированное проектирование
Abbott, R. August 1987. Knowledge Abstraction. Communications of the ACM vol.30(8).
-- November 1983. Program Design by Informal English Descriptions. Communications of the ACM vol.26(11).
Ackroyd, M. and Daum, D. 1991. Graphical Notation for Object-oriented Design and Programming. Journal of Object- Oriented Programming vol.3 (5).
Abbott, R.August 1987. Knowledge Abstraction. Communications ofthe ACM vol.30(8)
Alabios, В. September 1988. Transformation of Data Flow Analysis Models to Object-oriented Design. SIGPLAN Notices vol.23(11).
Arnold, P., Bodoff, S., Coleman, D., Gilchrist, H., and Hayes, F. June 1991. An Evaluation of Five Object-oriented Development Methods. Bristol, England: Hewlett-Packard Laboratories.
Bear, S., Alien, P., Coleman, D., and Hayes, F. Graphical Specification of Object-oriented Systems. Object-oriented Programming Systems, Languages, And Applications. Ottawa, Canada: OOPSLA'90.
Beck, K., and Cunningham, W. October 1989. A Laboratory for Teaching Object-oriented Thinking. SIGPLAN Notices vol.24(10).
Berard, E. 1986. An Object-oriented Design Handbook. Rockville, MD: EVB Software Engineering.
Berzins, V., Gray, M., and Naumann, D. May 1986. Abstraction-Based Software Development. Communications of the ACM vol.29(5).
Blaha, M. April 1988. Relational Database Design Using Object-oriented Methodology. Communications of the ACM vol.31(4).
Booch, G. September 1981. Describing Software Design in Ada. SIGPLAN Notices vol.16(9). - March/April 1982. Object-oriented Design. Ada Letters vol.1(3).
-- February, 1986 Object-oriented Development. IEEE Transactions of Software Engineering vol.12(2).
-- 1987. On the Concepts of Object-oriented Design. Denver, CO: Rational.
-- Summer 1989. What Is and What Isn't Object-oriented Design. American Programmer vol.2(7-8). Booch, G. and Vilot, M. Object-oriented Design. The C++ Report.
Booch, G.Jacobson, I., and Kerth, N. September 1988. Specification and Design Methodologies in Support of Object-oriented Programming Course Notes from Object-oriented Programming Systems, Languages, and Applications. San Diego, CA: OOPSLA'88.
Bowles, A. November/December 1991. Evolution Vs Revolution: Should Structured Methods Be Objectified? Object Magazine vol.1(4).
Boyd, S. July/August 1987. Object-oriented Design and PAMELATM. Ada Letters vol.7(4)
Bril, R., deBunje, Т., and Ouvry, A. October 1991. Development of SCORE: Towards the Industrialization of an Object-oriented Method using the Formal Design Language COLD-1 as Notation. Eindhoven, The Netherlands: Philips Research Laboratories.
Brookman, D. November/December 1991. SA/SD versus OOD. Ada Letters vol. XI(9).
Bruno, G., and Balsamo, A. November 1986 Petri Net-Based Object-oriented Modelling of Distributed of Systems. SIGPLAN Notices vol.21(11).
Buhr, R. 1984. System Design with Ada. Englewood Cliffs, NJ: Prentice-Hall.
-- 22 August 1988. Machine Charts for Visual Prototyping in System Design. SCE Report 88-2. Ottawa, Canada; Carleton University.
-- 14 September 1988. Visual Prototyping in System Design. SCE Report 88-14. Ottawa, Canada; Carleton University.
-- 1989. System Design with Machine Charts: A CAD Approach with Ada Examples. Englewood Cliffs, NJ: Prentice-Hall.
Buhr, R., Karam, G., Hayes, C., and Woodside, M. March 1989. Software CAD: A Revolutionary Approach. IEEE Transactions on Software Engineering vol.15(3).
Bulman, D. August 1989. An Object-Based Development Model. Computer Language vol.6(8).
Cherry, G. 1987. PAMELA 2: Ada-Based Object-oriented Design Method. Reston, VA: Thought* *Tools.
-- 1990. Software Construction by Object-oriented Pictures. Canandaigua, NY: Thought* *Tools.
Clark, R. June 1987. Designing Concurrent Objects.
Ada Letters vol.7 (6).
Coad, P. September 1991. OOD Criteria. Journal of Object-oriented Programming vol.(5).
Coleman, D., Hayes, F., and Bear, S. December 1990. Introducing Objectcharts or How to Use Statecharts in Object-oriented Design. Bristol, England: Hewlett-Packard Laboratories.
Comer, E. July 1989. Ada Box Structure Methodology Handbook. Melbourne, FL: Software Productivity Solutions.
Constantine, L. Summer 1989. Object-oriented and Structured Methods: Towards Integration. American Programmer vol.2(7-8).
CRI, CISI Ingenierie, and Matra. 20 June 1987. HOOD: Hierarchical Object-oriented Design. Paris, France.
Cribbs, J., Moon, S., and Roe, C. 1992. An Evaluation of Object- Oriented Analysis and Design Methodologies. Raleigh, North Carolina: Alcatel Network Systems.
Cunningham, W., and Beck, K. November 1986. A Diagram for Object-oriented Programs. SIGPLAN Notices vol.21(11).
Davis, N., Irving, M., and Lee, J. The Evolution of Object-Oriented Design from Conceptto Method. 1988. Surrey, United Kingdom: Logica Space and Defence Systems Limited.
Dean, H. May 1991. Object-Oriented Design Using Message Flow Decomposition, Jowna/ of Object-Oriented Programming vol.4(2).
deChampeaux, D., Balzer, В., Bulrnan, D., Culver-Lozo, K., Jacobson, I., Mellor, S. The Object-oriented Software Development Process. Vancouver, Canada: OOPSLA'92.
deChampeaux, D., Lea, D., and Faure, P. The Process of Object-oriented Design. Vancouver, Canada: OOPSLA'92.
Edwards, J. and Henderson-Sellers, B. November 1991. A Graphical Notation for Object-oriented Analysis and Design. New South Wales, Australia University of New South Wales.
Felsinger, R. 1987a. Integrating Object-oriented Design, Structured Analysis/Structured Design and Ada for Real-time Systems. Mt. Pleasant, SC.
-- 1987b. Object-oriented Design Course Notes. Torrance CA: Data Processing Management Association.
Fichman, R. and Kemerer, C. October 1992. Object-oriented and Conventional Analysis and Design Methodologies.
IEEE Computer vol.25(10).
Firesmith, D. May 6, 1986. Object- oriented Development. Fort Wayne, Indiana: Magnavox Electronic Systems Co.
-- 1993. Object-oriented Requirements Analysis and Logical Design. New York, New York: John Wiley and Sons.
Fowler, M. 1992. A Comparison of Object-Oriented Analysis and Design Methods. Vancouver, Canada: OOPSLA'92.
Gamma, E., Helm, R.Johnson, R., Vlissides, J. 1993. A Catalog of Object-Oriented Design Patterns. Cupertino, California: Taligent.
Gane, C. Summer 1989. Object-oriented Data, Process Modeling. American Programmer vol.2(7-8).
Giddings, R. May 1984. Accommodating Uncertainty in Software Design. Communications of the ACM vol.27(5).
Gomaa, H. September 1984. A Software Design Method for Real-Time Systems. Communications of the ACM vol.27(9).
Gossain, S. and Anderson, B. An Iterative Design Modelfor Reusable Objects. Ottawa, Canada: OOPSLA'90.
Gouda, M., Han, Y.Jensen, E., Johnson, W., and Kain, R. November 1977. Towards a Methodology of Distributed Computer System Design, 6th Texas Conference on Computing Systems. New York, NY: Association of Computing Machinery.
Graham, 1.1991. Object-Oriented Methods. Workingham, England: Addison-Wesley Publishing Company.
Grosch, J. December 1983. Type Derivation Graphs - A Way to Visualize the Type Building Possibilities of Programming Languages. SIGPLAN Notices vol.18(12).
Harel, D. 1987. Statecharts: A Visual Formalism for Complex Systems. Science of Computer Programming, vol.8.
-- May 1988. On Visual Formalisms. Communications of the ACM vol.31 (5).
Henderson-Sellers, B. 1992. A Book of Object-oriented Knowledge. Englewood Cliffs, New Jersey: Prentice Hall.
Inwood, C. 1992. Analysis versus Design: Is there a Difference? The C++Journal vol.2(1). Jackson, M. Summer 1989. Object-oriented Software. American Programmer vol.2(7-8)
Jacobson, I. August 1985. Concepts for Modeling Large Real-Time Systems Academic dissertation. Stockholm Sweden: Royal Institute of Technology, Department of Computer Science.
-- October 1987. Object- oriented Development in an Industrial Environment SIGPLAN Notices vol.22(12).
Jacobson, I., Christerson, M., Jonsson, P., and Overgaard, G. 1992. Object-oriented Software Engineering. Workingham, England: Addison-Wesley Publishing Company.
Jamsa, K. January 1984. Object-oriented Design vs. Structured Design - A Student's Perspective. Software Engineering Notes vol.9(1).
Johnson, R. and Russo, V. May 1991. Reusing Object-oriented Designs. Urbana, Illinois: University of Illinois.
Jones, A. 1979. The Object Model: A Conceptual Tool for Structuring Software, in Operating Systems, ed. R. Bayer et. al. New York, NY: Springer-Verlag.
Kadie, C. 1986. Refinement Through Classes: A Development Methodology for Object-Objected Languages. Urbana, IL: University of Illinois.
Kaplan, S., and Johnson, R. 21 July 1986. Design and Implementing for Reuse. Urbana, IL: University of Illinois, Department of Computer Science.
Kay, A. August 1969. The Reactive Engine. Salt Lake City, Utah: The University of Utah, Department of Computer Science.
Kelly, J. 1986. A Comparison of Four Design Methods for Real-Time Systems. Proceedings of the Ninth International Conference on Software Engineering. New York, NY: Computer Society Press of the IEEE.
Kent, W. 1983. Fact-Based Data Analysis and Design, in Entity-Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Kim, J. and Lerch, J. 1992. Towards a Model of Cognitive Process in Logical Design: Comparing Object-oriented and Traditional Functional Decomposition Software Methodologies. Pittsburgh, Pennsylvania: Carnegie Mellon University.
Ladden, R. July 1988. A Survey of Issues to Be Considered in the Development of an Object-oriented Development Methodology for Ada. Software Engineering Notes vol.13(3).
Lieberherr, K., and Riel, A. October 1989. Contributions to Teaching Object-oriented Design and Programming. SIGPLAN Notices vol.24(10).
Liskov, B. 1980.
A Design Methodology for Reliable Software Systems, in Tutorial on Software Design Techniques, 3rd ed. ed. P. Freeman and A. Wasserman. New York, NY: Computer Society Press of the IEEE.
Lorenz, M. 1993. Object-oriented Software Development. Englewood Cliffs, New Jersey: Prentice-Hall.
Mannino, P. April 1987. A Presentation and Comparison of Four Information System Development Methodologies. Software Engineering Notes vol.12(2).
Martin, B. 1993. Designing Object-oriented C++ Applications Using the Booch Method. Englewood Cliffs, New Jersey: Prentice-Hall.
Masiero, P., and Germano, F. July 1988. JSD As an Object-oriented Design Method. Software Engineering Notes vol.13(3).
Meyer, B. 1988. Object-oriented Software Construction. New York, NY: Prentice Hall.
Meyer, B. March 1987. Reusability: The Case for Object-Oriented Design. IEEE Software vol.4(2).
-- 1989. From Structured Programing to Object-oriented Design: The Road to Eiffel. Structured Programming vol.10(1).
Mills, H. June 1988. Stepwise Refinement and Verification in Box-Structured System. IEEE Computer vol.21(6).
Mills, H., Linger, R., and Hevner, A. 1986. Principles of Information System Design and Analysis. Orlando, FL: Academic Press.
Minkowitz, C., and Henderson, P. March 1987. Object-Oriented Programming of Discrete Event Simulation Using Petri Nets. Stirling, Scotland: University of Stirling.
Mostow, J. Spring, 1985. Toward Better Models of the Design Process. AI Magazine vol.6(1).
Moulin, В. 1983. The Use of EPAS/lPSO Approach for Integrating Entity Relationship Concepts and Software Engineering Techniques, in Entity-Relationship Approach to Software Engineering. ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Mullin, M. 1989. Object-oriented Program Design with Examples in C++. Reading, MA: Addison-Wesley.
Nielsen, K., and Shumate, K. August 1987. Designing Large Real-Time Systems with Ada Communications of the Л CM vol.30(8).
Nielsen, K. March 1988. An Object-oriented Design Methodology for Real-Time Systems in Ada.
San Diego, CA: Hughes Aircraft Company.
Nies, S. 1986. The Ada Object-oriented Approach. Proceedings on Ada Programming Language Applications for the NASA Space Station Houston, TX: NASA Lyndon B. Johnson Space Center.
Ossher, H. 1987. A Mechanism for Specifying the Structure of Large Layered, Systems, in Research Directions in Object-oriented Programming, ed. B. Schriver and P. Wegner Cambridge. MA: The MIT Press.
Page-Jones, M., Constantine, L, and Weiss, S. October 1990. Modeling Object-oriented Systems: The Uniform Object Notation. Computer Language vol.7(10).
Parnas, D. 1979. On the Criteria to be Used in Decomposing Systems into Modules. Classics In Software Engineering, ed. E. Yourdon. New York, NY Yourdon Press.
Parnas, D., Clements, P., and Weiss, D. March 1985. The Modular Structure of Complex Systems. IEEE Transactions on Software Engineering vol.SE-11 (3).
Pasik, A., and Schor, M. January 1984. Object-oriented Representation and Reasoning. SIGART Newsletter, no. 87.
Rajlich, V., and Silva, J. 1987. Two Object-oriented Decomposition Methods. Detroit, Michigan: Wayne State University.
Ramamoorthy, C., and Sheu, P. Fall 1988. Object-oriented Systems. IEEE Expert vol.3(3). Reenskaug, Т. August 1981. User-Oriented Descriptions of Smalltalk Systems. Byte vol.6(8).
Reiss, S. 1987. An Object-oriented Framework for Conceptual Programming in Research Directions in Object-oriented Programming, ed. B. Schriver and P. Wegner. Cambridge, MA: The MIT Press.
Richter, C. August 1986. An Assessment of Structured Analysis and Structured Design. Software Engineering Notes, vol.11(4).
Rine, D. October 1987. A Common Error in the Object Structure of Object-oriented Methods. Software Engineering Notes vol.12(4).
Rosenberg, D. and Jennett, P. July 1992. Object-oriented Analysis and Design Methods. Frameworks vol.6(4).
Ross, R. 1987. Entity Modeling: Techniques and Application. Boston, MA: Database Research Group.
Rosson, M., and Gold, E. October 1989. Problem-Solution Mapping in Object-oriented Design.
SIGPLAN Notices vol.24(10).
Rumbaugh, J. April 1991. Relational Database Design Using an Object-oriented Methodology. Communications of the A CM vol.31(4).
Sahraoui, A. 1987. Towards a Design Approach Methodology Combining OOP and Petri Nets for
Software Production. Toulouse, France: Laboratoire d'Automatique et d'analyses des systemes du C.N.R.S.
Sakai, H. 1983. A Method for Entity-Relationship Behavior Modeling, in Entity Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Seidewitz, E. May 1985. Object Diagrams. Greenbelt, MD: NASA Goddard Space Flight Center.
Seidewitz, E., and Stark, M. 1986. Towards a General Object-oriented Software Development
Methodology. Proceedings of the First International Conference on Ada Programming Language Applications for the NASA Space Station Houston TX: NASA Lyndon B. Johnson Space Center.
-- 1986. General Object-oriented Software Development, Report SEL-86-002. Greenbelt, MD:
NASA Goddard Space Flight Center.
-- July/August 1987. Towards a General Object-oriented Design Methodology. Ada Letters vol.7(4).
-- 1988. An Introduction to General Object-oriented Software Development. Rockville, MD: Millennium Systems.
Shilling, J., and Sweeney, P. October 1989. Three Steps to Views: Extending the Object-oriented Paradigm. SIGPLAN Notices vol.24(10).
Shiaer, S., Mellor, S., and Hywari, W. 1990. OODLE: A Language-Independent Notation for Object-oriented Design. Berkeley, California: Project Technology, California.
Shumate, K. 1987. Layered Virtual Machine/Object-Oriented Design. San Diego, CA: Hughes Aircraft Company.
Smith, M., and Tockey, S. 1988. An Integrated Approach to Software Requirements Definition Using Objects. Seattle, WA: Boeing Commercial Airplane Support Division.
Soisi, S. and Jones, E. March/April 1991. Simple Yet Complete Heuristice for Transforming Data Flow Diagrams into Booch Style Diagrams. Ada Letters vol.XI(2).
Song, X. May 1992. Comparing Software Design Methodologies Through Process Modeling.
Irvine, California: University of California.
Stark, M. April 1986. Abstraction Analysis: From Structured Analysis to Object-oriented Design. Greenbelt, MD: NASA Goddard Space Flight Center.
Strom, R. October 1986. A Comparison of the Object-oriented and Process Paradigms. SIGPLAN Notices vol.2i(10).
Teledyne Brown Engineering. October 1987. Software Methodology, Catalog, Report MC87-COMM/ADP-0036. Tinton Falls, NJ.
The Fusion Object-Oriented Analysis and Design Method. May 1992. Bristol, England: Hewlett-Parckard Laboratories.
Trhomas, D. May/June 1989. In Search of an Object-oriented Development Process. Journal of Object-oriented Programming vol.2(1).
Wahl, S. 13 December 1988. Introduction to Object-oriented Software. C++ Tutorial Program of the USENIX Conference. Denver, CO: USENIX Association.
Walters, N. July/August 1991. An Ada Object-Based Analysis and Design Approach. Ada Letters vol.XI(5).
Wasserman, Т., Pircher, P., and Muller R. December 1988. An Object-Oriented Structure Design Method/or Code Generation. San Francisco, CA: Interactive Development Environments.
-- Summer 1989. Concepts of Object-Oriented Structured Design. American Programmer vol.2(7-8).
-- March 1990. The Object-Oriented Structured Design Notation for Software Design Representation. IEEE Computer vol.23(3).
Webster, D. December 1988. Mapping the Design Information Representation Terrain. IEEE Spectrum vol.21(12).
Williams, L. 1986. The Object Model in Software Engineering Boulder, CO: Software Engineering Research.
Wirfs-Brock, R., and Wilkerson, B. October 1989. Object-oriented Design: A Responsibility-Driven Approach. SIGPLAN Notices vol.24(10).
Wirfs-Brock, R., Wilkerson, В., and Wiener, L. 1990. Designing Object-oriented Software. Englewood Cliffs, New Jersey: Prentice Hall.
Xong, X. and Osterweil, L. June 1992. A Detailed Objective Comparison and Integration of Two Object-oriented Design Methodologies. Irvine, California: University of California.
Yau, S., and Tsai, J.
June 1986. Survey of Software Design Techniques. IEEE Transactions on Software Engineering vol.SE-12(6)
Zachman, J. 1987. A Framework for Information Systems Architecture. IBM System Journal vol.26(3).
Zimmerman, R. 1983. Phases, Methods, and Tools - A Triad of System Development, in Entity-Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
G. Объектно-ориентированное программирование
Ada and C++: Business Case Analysis. July 1991. Washington, D.C.: Deputy Assistant Secretary of the Air Force.
Adams, S. July 1986. MetaMethods: The MVC Paradigm. HOOPLA: Hooray for Object-oriented Programming Languages vol.1(4). Everette, WA: Object-oriented Programming for Smalltalk Applications Developers Association.
Agha, G. October 1986. An Overview of Actor Languages. SIGPLAN Notices vol.21(10).
-- 1988. Actors: A Model of Concurrent Computation in Distributed Systems. Cambridge, MA: The MIT Press.
Agha, G., and Hewitt, C. 1987. Actors: A Conceptual Foundation for Concurrent Object-oriented Programming, in Research Directions in Object-oriented Programming, ed. B. Schriver and P. Wegner Cambridge. MA: The MIT Press.
Aksit, M., and Tripathi, A. September 1988. Data Abstraction Mechanisms in Sina/st. SIGPLAN Notices vol.23(11).
Albano, A. June 1983. Type Hierarchies and Semantic Data Models. SIGPLAN Notices vol.18(6).
Almes, G., Black, A. Lazowska, E., and Noe, J. January 1985. The Eden System: A Technical Review. IEEE Transactions of Software Engineering vol. SE-11(1).
Alpert, S., Woyak, S., Shrobe, H. and Arowood, L. December 1990. Object-oriented Programming in Al. IEEE Expert vol.5(6).
Althoff, J. August 1981. Building Data Structures in the Smalltalk-80 System. Byte vol.6(8).
Ambler, A. 1980. Gypsy: A Language for Specification and Implementation of Verifiable Programs, in Programming Language Design, ed. A. Wasserman. New York, NY: Computer Society Press.
America, P. 1987. POOL-T: A Parallel Object-oriented Language, in Object-oriented Concurrent Programming, ed.
Yonezawa and M. Tokoro. Cambridge, MA: The MIT Press.
Apple Computer. 1989. MacApp: The Expandable Macintosh Application, version 2.0B9. Cupertino, CA.
-- Macintosh Programmers Workshop Pascal 3.0 Reference. Cupertino, CA.
-- AT&T Bell Laboratories. 1989. UNIX System VATTC++ Language System, Release 2.0 Library Manual. Murray Hill, NJ.
-- UNIX System VATTC++ Language System, Release 2.0 Product Reference Manual. Murray Hill, NJ.
-- UNIX System VATTC++ Language System. Release 2.0 Release Notes. Murray Hill, NJ.
-- UNIX System VATT C+ + Language System, Release 2.0 Selected Readings. Murray Hill, NJ.
Attardi, G. 1987. Concurrent Strategy Execution in Omega, in Object-oriented Concurrent Programming, ed. Yonezawa and M. Tokoro. Cambridge. MA: The MIT Press.
Bach, I. November/December 1982. On the Type Concept of Ada. Ada Letters vol.11(3).
Badrinath, В., and Ramamritham, K. May 1988. Synchronizing Transactions on Objects. IEEE Transactions on Computers vol.37(5).
Ballard, M., Maier, D., and Wirfs-Brock, A. November 1986. QUICKTALK: A Smalltalk-80 Dialect for Defining Primitive Methods. SIGPLAN Notices vol.21(11).
Beaudet, P., and Jenkins, M. June 1988. Simulating the Object-oriented Paradigm in Nial. SIGPLAN Notices vol.23(6).
Bennett, J. October 1987. The Design and Implementation of Distributed Smalltalk. SIGPLAN Notices vol.22(12).
Bergin, J., and Greenfield, S. March 1988. What Does Modula-2 Need to Fully Support Object-oriented Programming? SIGPLAN Notices vol.23(3).
Bhaskar, K. October 1983. How Object-oriented Is Your System? SIGPLAN Notices vol.18(10).
Birman, K., Joseph, Т., Raeuchle, Т., and Abbadi, A. June 1985. Implementing Fault-tolerant Distributed Objects. IEEE Transactions of Software Engineering vol.SE-11(6).
Birtwistle, G., Dahl, O-J., Myhrhaug, В., and Nygard, K. 1979. Simula begin. Lund, Sweden: Studentlitteratur.
Black, A., Hutchinson, N., Jul, E., and Levy, H. November 1986. Object Structure in the Emerald System. SIGPLAN Notices vol.21(11).
Black, A., Hutchinson, N., Jul, E., Levy, H., and Carter, L. July 1986. Distribution and Abstract Types in Emerald. Report 86-02-04. Seattle, WA: University of Washington.
Blaschek, G. 1989. Implementation of Objects in Modula-2. Structured Programming vol.10(3).
Blaschek, G., Pomberger, G., and Stritzinger, A. 1989. A Comparison of Object-oriented Programming Languages. Structured Programming vol.10 (4).
Block, F., and Chan, N. October 1989. An Extended Frame Language. SIGPLAN Notices vol.24(10).
Bobrow, D. November 1984. If Prolog is the Answer, What Is the Question? Palo Alto, California. Xerox Palo Alto Research Center.
-- 1985. An Overview of KRL, a Knowledge Representation Language, in Readings in Knowledge Representation, ed. R. Brachman and H. Levesque. Los Altos, CA: Morgan Kaufmann.
Bobrow, D., DeMichiel, L, Gabriel, R., Keene, S., Kiczales, G., and Moon, D. September 1988.
Common Lisp Object System Specification X3J13 Document 88-002R. SIGPLAN Notices vol.23.
Bobrow, D., Kahn, K., Kiczales, G., Masinter, L., Stefik, M., and Zdybel, F. August 1985. COMMONLOOPS: Merging Common Lisp and Object-Oriented Programming, Report ISL-85-8. Palo Alto, CA: Xerox Palo Alto Research Center, Intelligent Systems Laboratory.
Borgida, A. January 1985. Features of Languages for the Development of Information Systems at the Conceptual Level. IEEE Software vol.2(1).
-- October 1986. Exceptions in Object-Oriented Languages. SIGPLAN Notices vol.21(10).
Borning, A., and Ingalls, D. 1982a. A Type Declaration and Inference System for Smalltalk. Palo Alto, CA: Xerox Palo Alto Research Center.
-- 1982b. Multiple Inheritance in Smalltalk-80. Proceedings of the National Conference on Artificial Intelligence. Menio Park, CA: AAAI.
Bos, J. September 1987. PCOL - A Protocol-Constrained Object Language. SIGPLAN Notices vol.22(9).
Briot, J., and Cointe, P. October 1989. Programming with Explicit Metaclasses in Smalltalk. SIGPLAN Notices vol.24(10).
Buzzard, G., and Mudge, T. 1987.
Object- Based Computing and the Ada Programming Language, in Object-oriented Computing: Concepts vol.1. ed. G. Peterson. New York, NY: Computer Society Press of the IEEE.
Canning, P., Cook, W., Hill, W., and Olthoff, W. October 1989. Interfaces for Strongly-Typed Object-oriented Programming. SIGPLAN Notices vol.24 (10).
Caudill, P., and Wirfs-Brock, A. November 1986. A Third Generation Smalltalk-80 Implementation. SIGPLAN Notices vol.21(11).
Chambers, C., Ungar, D., and Lee, E. October 1989. An Efficient Implementation of Self, a Dinamically-Typed Object-oriented Language Based on Prototypes SIGPLAN Notices-vol.24(10).
Chang, S. 1990. Visual Languages and Visual Programming. New York, New York: Plenum Press.
Chin, R. and Chanson, S. March 1991. Distributed Object-based Programming Systems. ACM Computing Surveys vol.23(1).
Clark, K. December 1988. PARLOG and Its Application. IEEE Transactions on Software Engineering vol.14(12).
Cleaveland, С. 1980. Programming Languages Considered as abstract Data Types. Communications of the ACM.
Coad, P. and Nicola, J. 1993. Object-oriented Programming. Englewood Cliffs, New Jersey: Yourdon Press.
Cointe, P. October 1987 Metaclasses Are First Class: the ObjVlisp Model. SIGPLAN Notices vol.22(12).
Connor, R., Dearie, A., Morrison, R., and Brown, A. October 1989. An Object Addressing Mechanism for Statically Typed Languages with Multiple Inheritance. SIGPLAN Notices vol.24(10).
Conroy, Т., and Pelegri-Llopart, E. 1983. An Assessment of Method-lookup Caches for Smalltalk-80 Implementations, in Smalltalk-80: Bits of History, Words of Advice, ed. G. Krasner. Reading MA: Addison-Wesley.
Coplien, J. 1992. Advanced C++ Programming Styles and Idioms. Reading, Massachusetts: Addison-Wesley Publishing Company.
Corradi. A., and Leonardi. L. December 1988. The Role of Opaque Types in Building Abstractions. SIGPLAN Notices vol.'23(12).
Сох, В. 1986. Object-oriented Programming: An Evolutionary Approach. Reading, MA: Addison-Wesley.
Cox, B. January 1983. The Object-oriented Pre-compiler. SIGPLAN Notices vol.18(1).
-- January 1984. Message/ Object Programming: An Evolutionary Change in Programming Technology. IEEE Software vol.1(1).
-- February/March 1984. Object-oriented Programming: A Power Tool for Software Craftsmen. Unix Review.
-- October/November 1983. Object-oriented Programming in C. Unix Review. Сох, В., and Hunt, B. August 1986. Objects, Icons, and Software-lCs. Byte vol.11(8).
Cox, P. and Pietrzykowski, T. March 1989. Prograph: A Pictorial View of Object-oriented Programming. Nova Scotia, Canada: Technical University of Nova Scotia.
deJong, P. October 1986. Compilation into Actors. SIGPLAN Notices vol. 21(10). Deutsch, P. August 1981. Building Control Structures in the Smalltalk-80 System. Byte vol.6(8).
-- 1983. Efficient Implementation of the Smalltalk-80 System. Proceedings of the 11th Annual ACM Symposium on the Principles of Programming Languages. New York. NY: Association of Computing Machinery.
Dewhurst, S., and Stark, K. 1989. Programming in C++. Englewood Cliffs, NJ: Prentice Hall. Diederich, J., and Milton, J. May 1987. Experimental Prototyping in Smalltalk. IEEE Software vol.4(3).
Dixon, R., McKee, Т., Schweizer, P., and Vaughn, M. October 1989. A Fast Method Dispatcher for Compiled Languages with Multiple Inheritance. SIGPLAN Notices vol.24(10).
Dony, С. August 1988. An Object-oriented Exception Handling System for an Object-oriented Language Proceedings of ECOOP'88: European Conference on Object-Oriented Programming. New York, NY: Springer-Verlag.
Duff, C. August 1986. Designing an Efficient Language. Byte vol.11 (8).
Dussud, P. October 1989. TICLOS: An Implementation of CLOS for the Explorer Family. SIGPLAN Notices vol.24(10).
Eccles, J. 1988. Porting from Common Lisp with Flavors to C++. Proceedings of USENIX C++ Conference. Berkeley, CA: USENIX Association.
Edelson, D. September 1987. How Objective Mechanisms Facilitate the Development of Large Software Systems in Three Programming Languages.
SIGPLAN Notices vol.22(9).
Ellis, M. and Stroustrup, B. 1990. The Annotated C++ Reference Manual. Reading, Massachusetts: Addison-Wesley Publishing Company.
Endres, T. May 1985. Clascal - An Object-oriented Pascal. Computer Language vol.2(5). Entsminger, G. 1990. The Tao of Objects. Redwood City, California: M & T Books. Filman, R. October 1987. Retrofitting Objects. SIGPLAN Notices vol.22(12). Finzer, W., and Gould, L. June 1984. Programming by Rehearsal. Byte vol.9(6).
Foote, В., and Johnson, R. October 1989. Reflective Facilities in Smalltalk-80. SIGPLAN Notices vol.24(10).
Freeman-Benson, B. October 1989. A Module Mechanism for Constraints in Smalltalk. SIGPLAN Notices vol.24(10).
Fukunaga, K., and Jirose, S. November 1986. An Experience with a Prolog-Based Object-Oriented Language. SIGPLAN Notices vol.21(11).
Gabriel, R., White, J., and Bobrow, D. September 1991. CLOS Integrating Object-oriented and Functional Programming. Communications of the Л CM vol.34( 9).
Goldberg, A. August 1981. Introducing the Smalltalk-80 System. Byte vol.6(8). Goldberg, A. September 1988. Programmer as Reader. IEEE Software vol.4(5).
Goldberg, A., and Kay, A. March 1976. Smalltalk-72 Instructional Manual. Palo Alto, CA: Xerox Palo Alto Research Center.
-- 1977. Methods for Teaching Programming Language Smalltalk, Report SSL 77-2. Palo Alto, CA:
Xerox Palo Alto Research Center.
Goldberg, A., and Pope, S. Summer 1989. Object-oriented Programming Is Not Enough. American Programmer vol.2(7-8).
Goldberg, A., and Robson, D. 1983. Smalltalk-80: The Language and Its Implementation. Reading, MA: Addison-Wesley.
-- 1989. Smalltalk-80: The Language. Reading, MA: Addison-Wesley.
Goldberg, A., and Ross, J. August 1981. Is the Smalltalk-80 System for Children? Byte vol.6(8).
Goldstein, Т. May 1989. The Object-oriented Programmer. The C++ Report vol.1(5).
Gonsalves, G., and Silvestri, A. December 1986. Programming in Smalltalk-80: Observations and Remarks from the Newly Initiated.
SIGPLAN Notices vol. 21(12).
Gorlen, K. 1989. An Introduction to C++, in UNIX Systems VATTC++ Language System, Release 2. 0 Selected Readings. 1989. Murray Hill, NJ: ATT Bell Laboratories.
Golden, K., Orlow, S., and Plexico, P. 1990. Data Abstraction and Object-oriented Programming in C++. New York, New York: John Wiley and Sons.
Gougen, J., and Meseguer, J. 1987. Unifying Functional, Object-oriented, and Relational Programming with Logical Semantics, in Research Directions in Object-oriented Programming. ed. Schriver and P. Wegner Cambridge. MA: The MIT Press.
Graube, N. August 1988. Reflexive Architecture: From ObjVLisp to CLOS. Proceedings of ECOOP'88 European Conference of Object-oriented Programming New York, NY: Springer-Verlag.
Grogono, P. November 1989. Polymorphism and Type Checking in Object-oriented Languages. SIGPLAN Notices vol.24(11).
-- 1991. Issues in the Design of an Object-oriented Programming Language. Structured Programming vol.12(1).
Hagmann, R. 1983. Preferred Classes: A Proposal for Faster Smalltalk-80 Execution, in Smalltalk-80: Bits of History, Words of Advices, ed. G. Krasner. Reading, MA: Addison-Wesley.
Hailpern. В., and Nguyen, V. 1987. A Model for Object-Based Inheritance, in Research Directions in Object-oriented Programming, ed. B. Shriver and P. Wegner. Cambridge, MA: The MIT Press.
Halbert, D., and O'Brien, P. September 1988. Using Types and Inheritance in Object-oriented Programming IEEE Software vol.4(5).
Halstead, R. 1988. Object-management on Distributed Systems, in Object-oriented Computing:
Implementations vol.2. ed. G. Peterson. New York, NY: Computer Society Press of the IEEE.
Harland, D., Szyplewski, M., and Wainwright, J. October 1985. An Alternative View of Polymorphism. SIGPLAN Notices vol.20(10).
Hendler, J. October 1986. Enhancement for Multiple Inheritance. SIGPLAN Notices vol.21(10).
Hines, Т., and Unger, E. 1986. Conceptual Object-oriented Programming. Manhattan, Kansas: Kansas State University.
Ingalls, D.
The Smalltalk- 76 Programming System Design and Implementation. Proceedings of the Fifth Annual ACM Symposium on Principles of Programming Languages, New York, NY: Association of Computing Machinery.
-- August 1981a. Design Principles Behind Smalltalk. Byte vol.6(8).
-- August 1981. The Smalltalk Graphics Kernel. Byte vol.6(8).
-- 1983. The Evolution of the Smalltalk Virtual Machine, in Smalltalk-80 Bits of History, Words of Advice, ed. G. Krasner. Reading, MA: Addison-Wesley.
-- November 1986. A Simple Technique for Handling Multiple Polymorphism. SIGPLAN Notices vol.21(11).
Ishikawa, Y., and Tokoro, M. 1987. Orient84/K: An Object-oriented Concurrent Programming Language for Knowledge Representation, in Object-oriented Concurrent Programming, ed. Yonezawa and M. Tokoro. Cambridge, MA: The MIT Press.
Jackson, M. May 1988. Objects and Other Subjects. SIGPLAN Notices vol. 23(5).
Jacky, J., and Kalet, I. September 1987. An Object-oriented Programming Discipline for Standard Pascal. Communications of the ACM vol.30(9).
Jacobson, I. November 1986. Language Support for Changeable, Large, Real-Time Systems. SIGPLAN Notices vol.21(11).
Jeffery, D. February 1989. Object-oriented Programming in ANSI C. Computer Language. Jenkins, M., and Glasgow, J. January 1986. Programming Styles in Nial. IEEE Software vol.3(1). Johnson, R. November 1986. Type-Checking Smalltalk. SIGPLAN Notices vol.21(11).
Johnson, R., Graver, J., and Zurawski, L. September 1988. TS An Optimizing Compiler for Smalltalk. SIGPLAN Notices vol.23(11).
Kaehler, and Patterson, D. 1986. A Taste of Smalltalk. New York, NY: W. W. Norton.
-- August 1986. A Small Taste of Smalltalk. Byte vol.11(8).
Kaehler, Т. November 1986. Virtual Memory on a Narrow Machine for an Object-oriented Language. SIGPLAN Notices vol.21(11).
Kahn, K., Tribble, E., Miller, M., and Bobrow, D. 1987. Vulcan: Logical Concurrent Objects, in Research Directions Object-oriented Programming, ed. B. Schriver and P. Wegner. Cambridge, MA: The MIT Press.
-- November 1986. Objects in Concurrent Logic Programming Languages. SIGPLAN Notices vol.21(11).
Kaiser, G., and Garlan, D. October 1987. MELDing Data Flow and Object-oriented Programming. SIGPLAN Notices vol.22(12).
Kalrne, С. 27 March 1986. Object-oriented Programming: A Rule-Based Perspective. Los Angeles, CA: Inference Corporation.
Kay, A. New Directions for Novice Programming in the 1980s. Palo Alto, CA: Xerox Palo Alto Research Center.
Keene, S. 1989. Object-oriented Programming in Common Lisp. Reading, MA: Addison-Wesley.
Kelly, K., Rischer, R., Pleasant, M., Steiner, D., McGrew, C., Rowe. J., and Rubin, M. 30 March 1986. Textual Representations of Object-oriented Programs for Future Programmers. Palo Alto, CA: Xerox Al Systems.
Kempf, J., Harris, W., D'Souza, R., and Snyder, A. October 1987. Experience with CommonLoops. SIGPLAN Notices vol.22(12).
Kempf, R. October 1987. Teaching Object-Oriented Programming with the KEE System. SIGPLAN Notices vol.22(12).
Khoshafian, S., and Copeland, G.November 1986. Object Identity. SIGPLAN Notices vol.21(11).
Kiczales, G., Rivieres, J., and Bobrow, D. 1991. The Art of the Metaobject Protocol. Cambridge, Massachusetts: The MIT Press.
Kilian, M. April 1987. An Overview of the Trellis/Owl Compiler. Hudson, MA: Digital Equipment Corporation.
Kimminau, D., and Seagren, M. 1987. Comparison of two Prototype Development Using Object-Based Programming. Naperville, IL: AT&T Bell Laboratories.
Knowledge Systems Corporation. 1987. Pluggable Gauges Version 1.0 User Manual. Cary, NC.
Knudsen J. and Madsen, O. August 1988. Teaching Object-oriented Programming Is More than Teaching Object-oriented Programming Languages. Proceedings of ECOOP'88: European Conference on Object-oriented Programming. New York, NY: Springer-Verlag.
Knudsen, J. August 1988. Name Collison in Multiple Classification Hierarchies. Proceedings of ECOOP'88; European Conference on Object-oriented Programming. New York, NY: Springer-Verlag.
Korson, T.
and McGregor, J. September 1990. Understanding Object-oriented: A Unifying Paradigm. Communications of the ACM vol.33(9).
Koshmann, Т., and Evers, M. July 1988. Bridging the Gap Between Object-oriented and Logic Programming. IEEE Software vol.5(4).
Koskimies, K., and Paakki, J. July 1987. TOOLS: A Unifying Approach to Object-oriented Language Interpretation. SIGPLAN Notices vol.22(7).
Krasner, G. August 1981. The Smalltalk-80 Virtual Machine. Byte vol. 6(8).
-- ed. 1983. Smalltalk-80 Bits of History, Words of Advice. Reading, MA: Addison-Wesley.
Krasner, G, and Pope, S. August/September 1988. A Cookbook for Using the Model-View-Controller User Interface Paradigm in Smalhalk-8O.Joumal of Object-oriented Programming, vol.1(3).
Kristensen, В., Madsen, O., Moller-Pedersen, В., and Nygaard, K. 1987. The BETA Programming Language, in Research Directions Object-oriented Programming, ed. B. Schriverand P. Wegner. Cambridge. MA: The MIT Press.
LaLonde, W. April 1989. Designing Families of Data Types Using Exemplars. ACM Transactions on Programming Language and Systems vol.11(2).
LaLonde, W., Thomas, D., and Pugh, J. November 1986. An Examplar Based Smalltalk. SIGPLAN Notices vol.21(11).
LaLonde, W. and Pugh, J. 1990. Inside Smalltalk, Volumes 1 and 2. Englewood Cliffs, New Jersey: Prentice Hall.
Lang, K., and Peralmutter, B. November 1986. Oaklisp: an Object-oriented Scheme with First Class Types. SIGPLAN Notices vol.21(11).
Laursen, J., and Atkinson, R. October 1987. Opus: A Smalltalk Production System SIGPLAN Notices vol.22(12)
Lieberherr, K., and Holland, I. March 1989. Formulations and Benefits of the Law of Demeter. SIGPLAN Notices vol.24(3).
-- September 1989. Assuring Good Style for Object-oriented Programs. IEEE Software vol.6(5).
Lieberherr, K., Holland, I., Lee, G., and Riel, A. June 1988. An Objective Sense of Style. IEEE Computer vol.21(6).
Lieberman, H. November 1986. Using Prototypical Objects to Implement Shared Behavior in Object-oriented Systems.
SIGPLAN Notices vol.21(11).
-- 1987. Concurrent Object- oriented Programming in Act 1, in Object-oriented Concurrent Programming, ed. Yonezawa and M. Tokoro. Cambridge, MA: The MIT Press.
Lieberman, H., Stein, L., and Ungar, D. May 1988. Of Types and Prototypes: The Treaty of Orlando. SIGPLAN Notices vol.23(5).
Lim, J., and Johnson, R. April 1989. The Heart of Object-oriented Concurrent Programming. SIGPLAN Notices vol.24(4).
Linowes, J. August 1988. It's an Attitude. Byte vol.13(8).
Lippman, S. 1989. C++ Primer 1991 2nd Edition. Reading, Massachusetts: Addison-Wesley Publishing Company.
Liskov, В., Atkinson, R., Bloom, T., Moss, E., Schaffert, C., Scheifler, R., and Snyder. R. 1981. CLU Reference Manual. New York, NY: Springer-Verlag.
Liskov, В., Snyder, A., Atkinson, R., and Schaffert, C. 1980. Abstraction Mechanisms in CLU, in Programming Language Design, ed. A. Wasserman. New York, NY: Computer Society Press.
Liu, C. March 1991. On the Object-Orientedness of C++. SIGPLAN Notices vol.26(3).
Lujun, S., and Zhongxiu. August 1987. An Object-oriented Programming Language for Developing Distributed Software. SIGPLAN Notices vol.22(8).
MacLennan, B. 1987. Values and Objects in Programming Languages, in Object-oriented Computing: Concepts vol.1. ed. G. Peterson. New York, NY: Computer Society Press of the IEEE.
Madsen, 0.1987. Block Structure and Object-oriented Languages, in Research Directions in Object-oriented Programming. ed. B. Schriver and P. Wegner. Cambridge, MA: The MIT Press.
Madsen, 0., and Moller-Pedersen, B. August 1988. What Object-oriented Programming May Be -And What It Does Not Have To Be. Proceedings of ECOOP'88: European Conference on Object-oriented Programming. New York, NY: Springer-Verlag.
Madsen, 0., and Moller-Pedersen, B. October 1989. Virtual Classes: A Powerful Mechanism in Object-oriented Programming. SIGPLAN Notices vol. 24(10).
Manci, D. 1990. Use of Metrics to Evaluate C++. Liberty Corner, New Jersey: AT&T Bell Laboratories.
Mannino, M., Choi, I., and Batory, D. November 1990. The Object-oriented Functional Data Language. IEEE Transactions on Software Engineering vol. 16(11).
Marcus, R.November 1985. Generalized Inheritance. SIGPLAN Notices vol.20(11).
Markowitz, V., and Raz, Y. 1983. Eroll: An Entity-Relationship, Role-Oriented Query Language, in Entity-Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Masini, G., Napoli, A., Colnet, D., and Tompre, K. 1991. Object-oriented Languages. London, England: Academic Press.
Mellender, F. October 1988. An Integration of Logic and Object-oriented Programming. SIGPLAN Notices vol.23(1O).
Methfessel, R. April 1987. Implementing an Access and Object-oriented Paradigm in a Language That Supports Neither. SIGPLAN Notices vol.22(4).
Meyer, B.November 1986. Genericity versus Inheritance. SIGPLAN Notices vol.21(11).
-- February 1987. Eiffel: Programming for Reusability and Extensibility. SIGPLAN Notices vol.22(2).
-- November/December 1988. Harnessing Multiple Inheritance. Journal of Object-Oriented Programming vol.1(4).
Micallef, J. April/May 1988. Encapsulation, Reusability, and Extensibility in Object-Oriented Programming Languages-./ounia/ of Object- Oriented Programming vol.1(1).
Microsoft C++ Tutorial. 1992. Redmond, Washington: Microsoft Corporation. Microsoft Windows Guide to Programming. 1992. Redmond, Washington: Microsoft Corporation.
Minsky, N., and Rozenshtein, D. October 1987. A Law-Based Approach to Object-oriented Programming. SIGPLAN Notices vol.22(12).
-- October 1989. Controllable Delegation: An Exercise in Law-Governed Systems. SIGPLAN Notices vol.24(10).
Miranda. E. October 1987. BrouHaHa - A Portable Smalltalk Interpreter. SIGPLAN Notices vol.22(12).
Mittal, S., Bobrow, D., and Kahn, K. November 1986. Virtual Copies: At the Boundary Between Classes and Instances. SIGPLAN Notices vol.21 (11).
Moon, D. November 1986. Object-oriented Programming with Flavors.
SIGPLAN Notices vol.21(11).
Morrison, R., Dearie, A., Connor, R., and Brown, A. July 1991. An Ad Hoc Approach to the Implementation of Polymorphism. ACM Transactions on Programming Languages and Systems vol.13(3).
Mossenbock, H., and Tempi, J. 1989. Object Oberon - A Modest Object-oriented Language. Structured Programming vol.10(4).
Mudge, Т. March 1985. Object-Based Computing and the Ada Language. IEEE Computer vol.18(3). Murray, R. 1990. C++ Tactics. Liberty Corner, New Jersey: AT&T Bell Laboratories.
Nelson, M. October 1991. Concurrency and Object-oriented Programming. SIGPLAN Notices vol.26(10).
Nierstrasz, 0. October 1987. Active Objects in Hybrid. SIGPLAN Notices vol.22(12). Novak, G. June 1983. Data Abstraction in GLISP. SIGPLAN Notices vol.18(6).
-- Fall 1983. GLISP: A Lisp-Based Programming System with Data Abstraction. AI Magazine vol.4(3).
Nygaard, K. October 1986. Basic Concepts in Object-oriented Programming. SIGPLAN Notices vol.21(10).
Nygaard, K., and Dahl, O-J. 1981. The Development of the Simula Languages, in History of Programming Languages, ed. R. Wexelbalt. New York, NY: Academic Press.
O'Brien, P. 15 November 1985. Trellis Object-Based Environment: Language Tutorial. Hudson, MA: Digital Equipment Corporation.
O'Grady, F. July/August 1990. Is There Life After COBOL? American Programmer. 3(7-8). Object-oriented Programming Workshop. October 1986. SIGPLAN Notices vol.21(10).
Olthoff, W. 1986. Augmentation of Object-Oriented Programming by Concepts of Abstract Data Type Theory: The ModPascal Experience. Kaiserslautern, West Germany: University of Kaiserslautern.
Osterbye, K. June/July 1988. Active Objects: An Access-Oriented Framework for Object-oriented Languages. Journal of Object-oriented Programming vol.1(2).
Paepcke, A. October 1989. PCLOS: A Critical Review. SIGPLAN Notices vol.24(10).
Parc Place Systems. 1988. The Smalltalk-80 Programming System Version VI 2.3. Palo Alto, CA.
Pascoe, G. August 1986. Elements of Object-oriented Programming.
Byte vol.11(8).
-- November 1986. Encapsulators: A New Software Paradigm in Smalltalk-80. SIGPLAN Notices vol.21(11).
Perez, E. Sertember/October 1988. Simulating Inheritance with Ada. Ada Letters vol.8(7).
Peterson, G. ed. 1987. Object-oriented Computing Concepts. New York, NY: Computer Society Press of the IEEE.
Pinson, L., and Wiener, R. 1988. An Introduction to Object-oriented Programming and Smalltalk. Reading, MA Addison-Wesley.
Pohl, I. 1989. C++ for С Programmers. Redwood City, CA: Benjamin/Cummings. Pokkunuri, B. November 1989. Object-oriented Programming. SIGPLAN Notices vol.24(11). Ponder, С. and Bush, B. June 1992. Polymorphism Considered Harmful. SIGPLAN Notices vol.27(6). Fountain, D. August 1986. Object-oriented FORTH. Byte vol.11(8).
Proceedings of ECOOP'88: European Conference on Object-Oriented Programming. August 1988. New York, NY: Springer-Verlag.
Proceedings of OOPSLA '86: Object-oriented Programming Systems, Languages, and Applications. November 1986. SIGPLAN Notices vol.21(11).
Proceedings of OOPSLA 87: Object-oriented Programming Systems, Languages, and Applications. October 1987. SIGPLAN Notices vol.22(12).
Proceedings of OOPSLA Object-oriented Programming Systems, Languages, and Applications. September 1988. SIGPLAN Notices vol.23(11).
Proceedings of OOPSLA'89: Object-oriented Programming Systems, Languages, and Applications. October 1989. SIGPLAN Notices vol.24(10).
Proceedings of OOPSLA'90. Object-Oriented Programming Systems, Languages, and Applications. October 1990. SIGPLAN Notices vol.25(10).
Proceedings of OOPSLA'91. Object-oriented Programming Systems. Languages, and Applications. November 1991. SIGPLAN Notices vol.26(11).
Proceedings of OOPSLA '92. Object-Oriented Programming Systems, Languages, and Applications. October 1992. SIGPLAN Notices vol.27(10).
Proceedings of the ACM SIGPLAN Workshop on Object-Based Concurrent Programming. April 1989. SIGPLAN Notices vol.24(4).
Proceedings of the USENIX Association C++ Workshop.
November 1987. Berkeley, CA: USENIX Association.
Proceedings of the Workshop on Data Abstraction, Databases and Conceptual Modelling. 1980. SIGPLAN Notices vol.16(1).
Pugh, J. March 1984. Actors - The Stage is Set. SIGPLAN Notices vol. 19(3).
Rathke, С. 1986. ObjTalk: Representation von Wissen in einer objektorientierten Sprache Stuttgart, West Germany: Institut fur Informatik der Universitat Stuttgart.
Rentsch, T. September 1982. Object-oriented Programming. SIGPLAN Notices vol.17(12).
Rettig, M., Morgan, Т., Jacobs, J., and Wimberly, D. January 1989. Object-oriented Programming in AI. AIExpert.
Robson, D. August 1981. Object-Oriented Software Systems. Byte vol. 6(8).
Rumbaugh, J. October 1987. Relations as Semantic Constructs in an Object-oriented Language. SIGPLAN Notices vol.22(12).
Russo, V., and Kaplan, S. 1988. A C++ Interpreter for Scheme. Proceedings of USENIX C++ Conference. Berkeley, CA: USENIX Association.
Sakkinen, M. August 1988. On the Darker Side of C++. Proceedings of ECOOP'88: European Conference on Object-oriented Programming. New York, NY: Springer-Verlag.
-- December 1988. Comments on "the Law of Demeter" and C++. SIGPLAN Notices vol.23(12).
Saltzer, J. 1979. Naming and Binding of Objects, in Operating Systems, ed. R. Bayer et. al. New York, NY: Springer-Verlag.
Sandberg, D. November 1986. An Alternative To Subclassing. SIGPLAN Notices vol.21(11).
-- October 1988. Smalltalk and Exploratory Programming. SIGPLAN Notices vol.23(10).
Saunders, J. March/April 1989. A Survey of Object-oriented Programming Languages./ournal of Object-oriented Programming vol.1(6).
Schaffert, С., Cooper, T., and Wilpolt, C. November 25, 1985. Trellis Object-Based Environment: Language Reference Manual. Hudson, MA: Digital Equipment Corporation.
Schaffert, C., Cooper, Т., Bullis, В., Kilian, M., and Wilpolt, C. November 1986. An Introduction to Trellis/Owl. SIGPLAN Notices vol.21(11).
Schmucker, K. 1986a. MacApp: An Application Framework. Byte vol.11 (8).
-- 1986b. Object- oriented Languages for the Macintosh. .Byte vol.11 (8).
-- 1986с. Object-Oriented Programming for the Macintosh. Hasbrouk Heights, NJ: Hayden.
Schriver, В., and Wegner, P. eds. 1987. Research Directions in Object-oriented Programming. Cambridge, MA: The MIT Press.
Seidewitz, E. March/April 1992. Object-oriented Programming with Mixins in Ada. Ada Letters vol.XII(2).
-- October 1987. Object-oriented Programming in Smalltalk and Ada. SIGPLAN Notices vol.22(12). Shafer, D. 1988. Hyper Talk Programming. Indianapolis, IN: Hayden Book.
Shah, A., Rumbaugh, J., Hamel, J., and Borsari, R. October 1989. DSM: An Object-Relationship Modeling Language. SIGPLAN Notices vol.24(10).
Shammas, N. October 1988. Smalltalk a la C. Byte vol.13(10).
Shan, Y. October 1989. An Event-Driven Model-View-Controller Framework for Smalltalk. SIGPLAN Notices vol.24(10).
Shapiro, J. 1991. A C++ Toolkit. Englewood Cliffs, New Jersey Prentice-Hall. Shaw, M. 1981. ALPHARD: Form and Content. New York, NY: Springer-Verlag.
Shibayama, E. September 1988. How to Invent Distributed Implementation Schemes of an Object-Based Concurrent Language - A Transformational Approach. SIGPLAN Notices vol.23(11).
Shibayama, E., and Yonezawa, A. 1987. Distributed Computing in ABCL/1, in Object-oriented Concurrent Programming, ed. Yonezawa and M. Tokoro. Cambridge MA: The MIT Press.
Shopiro, J. 13 December 1988. Programming Techniques with C++. C++ Tutorial Program of the USENIX Conference. Denver, CO: USENIX Association.
-- December 1989. An Example of Multiple Inheritance in C++: A Model of the lostream Library. SIGPLAN Notices vol.24(12).
Simonian, R., and Crone., M. November/December 1988. InnovAda: True Object-oriented Programming in Ada Journal of Object-oriented Programming vol.1(4).
Snyder, A. February 1985 Object-oriented Programming for Common Lisp. Report ATC-85-1. Palo Alto CA: Hewlett-Packard.
-- November 1986. Encapsulation and Inheritance in Object-oriented Programming Languages.
SIGPLAN Notices vol.21(11).
-- 1987. Inheritance and the Development of Encapsulated Software Components, in Research Directions in Object-oriented Programming, ed. B. Schriver and P. Wegner. Cambridge, MA: The MIT Press.
-- January 1993. The Essence of Objects: Concepts and Terms. IEEE Software vol.10(1). Software Productivity Solution 1988. Classical-Ada User Manual. Melbourne. FL.
Stankovic, J. April 1982. Software Communication Mechanisms: Procedure Calls Versus Messages. IEEE Computer vol.15(4).
Stefik, M. and Bobrow D. Winter 1986. Object-oriented Programing: Themes and Variations, AI Magazine, vol.6(4).
Stefik, M. Bobrow, D. Mittal, S., and Conway, L. Fall 1983, Knowledge Programing in Loops. AI Magazine vol.4(3).
Stein, L. October 1987. Delegation Is Inheritance. SIGPLAN Notices vol. 22(12).
Stroustrup, B. January 1982. Classes: An Abstract Data Type Facility for the C Language. SIGPLAN Notices vol.17(1).
-- October 1986. An Overview of C++. SIGPLAN Notices vol.21(10).
-- 1987. The Evolution of C++. Proceedings of the USENIX C++ Workshop. Santa Fe. NM: USENIX Association.
-- November 1987. Possible Directions for C++. Proceedings of the USENIX C++ Workshop. Santa Fe., NM: USENIX Association.
-- 1988. Parameterized Types for C++. Proceedings of USENIX C++ Conference. Berkeley, CA: USENIX Association.
-- May 1988 What is Object-oriented Programming? IEEE Software vol. 5(3).
-- August 1988. A Better C? Byte vol.13(8).
-- 1991. The C++ Programming Language. Second Edition. Reading, Massachusetts: Addison-Wesley Publishing Company.
Suzuki.N. 1981. Inferring Types in Smalltalk, Proceedings of the 8th Annual Symposium of ACM Principles of Programming Languages. New York, NY: Association of Computing Machinery.
Suzuki, N., and Terada, M. 1983. Creating Efficient Systems for Object-oriented Languages. Proceedings of the 11th Annual ACM Symposium on the Principles of Programming Languages. New York, NY: Association of Computing Machinery.
Symposium on Actor Languages.
October 1980. Creative Computing.
Tektronix. 1988. Modular Smalltalk.
Tesler, L. August 1986. Programming Experiences. Byte vol.11(8).
The Smalltalk-80 System. August 1981. Byte vol.6(8).
Thomas, D. March 1989. What's in an Object? Byte vol.14(3).
Tieman, M. 1 May 1988. User's Guide to GNU C++. Cambridge, MA: Free Software Foundation.
Tokoro, M., and Ishikawa, Y. October 1986. Concurrent Programming in Orient84/K: An Object-Oriented Knowledge Representation Language. SIGPLAN Notices vol.21(10).
Touati, H. May 1987. Is Ada an Object-Oriented Programming Language? SIGPLAN Notices vol.22(5).
Touretzky, D. 1986. The Mathematics of Inheritance Systems. Los Altos, California: Morgan Kaufman Publishers.
Tripathi, A., and Berge, E. An Implementation of the Object-oriented Concurrent Programming Language SINA. Software - Practice and Experience vol.19(3).
U. S. Department of Defense. February 1983. Reference Manual for the Ada Programming Language. Washington, D.C.: Ada Joint Program Office.
Ungar, D. September 1988. Are Classes Obsolete? SIGPLAN Notices vol. 23(11). Ungar, D., and Smith, R. October 1987. Self: The Power of Simplicity. SIGPLAN Notices vol.22(12).
van den Bos, J., and Laffra, C. October 1989. PROCOL: A Parallel Object Language with Protocols. SIGPLAN Notices vol.24(10).
Vaucher, J., Lapalrne, G., and Malenfant, J. August 1988. SCOOP: Structured Concurrent Object-oriented Prolog. Proceedings of ECOOP'88: European Conference on Object-oriented Programming. New York, NY: Springer-Verlag.
Warren. S., and Abbe, D. May 1980. Presenting Rosetta Smalltalk. Datamation.
Watanabe, Т., and Yonezawa, A. September 1988. Reflection in an Object-oriented Concurrent Language. SIGPLAN Notices vol.23(11).
Wegner, P. October 1987. Dimensions of Object-Based Language Design. SIGPLAN Notices vol.22(12).
-- January 1988. Workshop on Object-oriented Programming at ECOOP 1987. SIGPLAN Notices vol.23(1).
-- August 1990. Concepts and Paradigms of Object-oriented Programming.
OOPS Messenger vol.1(1).
-- October 1992. Dimensions of Object-oriented Modeling. IEEE Computer vol.25(10).
Wiener, R. June 1987. Object-oriented Programming in C++ - A Case Study. SIGPLAN Notices vol.22(6).
Williams, G. Summer 1989. Designing the Future: The Power of Object-oriented Programming. American Programmer vol.2(7-8).
Wilson, R. 1 November 1987. Object-oriented Languages Reorient Programming Techniques. Computer Design vol.26(20).
Winblad, A., Edwards. S., and King, D. 1990. Object-oriented Software. Reading, Massachusetts: Addison-Wesley Publishing Company.
Winston, P., and Horn, B. 1989. Lisp. 3rd ed. Reading, MA: Addison-Wesley.
Wirfs-Brock, R. and Wilkerson, B. September 1988. An Overview of Modula Smalltalk. SIGPLAN Notices vol.23(11).
Wirth. N. June 1987. Extensions of Record Types. SIGCSE Bulletin vol. 19(2).
-- July 1988a. From Modula to Oberon. Software - Practice and Experience vol.18(7).
-- July 1988b. The Programming Language Oberon. Software - Practice and Experience vol.18(7).
Wolf, W. September 1989. Practical Comparison of Two Object-oriented Languages. IEEE Software vol.6(5).
Yokote, Y., and Tokoro, M. November 1986. The Design and Implementation of Concurrent Smalltalk. SIGPLAN Notices vol.21(11).
-- October 1987. Experience and Evolution of Concurrent Smalltalk. SIGPLAN Notices vol.22(12).
Yonezawa, A., and Tokoro. M. eds. 1987. Object-oriented Concurrent Programming. Cambridge, MA: The MIT Press.
Yonezawa, A., Briot, J., and Shibayama, E. November 1986. Object-oriented Concurrent Programming in ABCL/1. SIGPLAN Notices vol.21(11).
Yonezawa, A., Shibayama, E., Takada, Т., and Honda, Y. Modelling and Programming in an Object-oriented Concurrent Language ABCL/1, in Object-oriented Concurrent Programming, ed. Yonezawa and M. Tokoro. Cambridge, MA: The MIT Press.
Yourdon, E. February 1990. Object-oriented COBOL. American Programmer vol.3(2).
-- January 1992. Modeling Magic. American Programmer vol.5(1).
Zave, P. September 1989.
A Compositional Approach to Multiparadigm Programming. IEEE Software vol.6(5).
H. Прикладное программирование
Abdel-Hamid, Т. and Madnick, S. 1991. Software Project Dynamics. Englewood Cliffs, New Jersey Prentice-Hall.
Abelson, H., and Sussman, G. 1985. Structure and Interpretation of Computer Programs. Cambridge, MA The MIT Press.
Andrews, D. and Leventhal, N. 1993. FUSION: Integration IE, CASE, and JAD:A Handbook for Reengineering the Systems Organization. Englewood Cliffs, New Jersey: Yourdon Press.
Appleton, D. 15 January 1986. Large Projects. Datamation.
Aron, J. 1974a. The Program Development Process: The Individual Programmer. Vol.1. Reading, MA:
Addison-Wesley.
-- 1974b. The Program Development Process: The Programming Team. Vol. 2. Reading, MA: Addison-Wesley.
Babich, W. 1986. Software Configuration Management. Reading, Massachusetts: Addison-Wesley Publishing Company.
Ben-Ari, M. 1982. Principles of Concurrent Programming. Englewood Cliffs, NJ: Prentice Hall.
Berard, E. 1993. Essays on Object-oriented Software Engineering. Englewood Cliffs, New Jersey: Prentice-Hall.
Berson, A. 1992. Client/Server Architecture. New York, New York: McGraw-Hill.
Berzins, V. and Luqi. 1991. Software Engineering with Abstractions. Reading, Massachusetts:
Addison-Wesley Publishing Company.
Biggerstaff, T. and Perils, A. 1989. Software Reusability. New York, New York: ACM Press.
Bisant, D. and Lyle, J. October 1989. A Two-Person Inspection Method to Improve Programming Productivity. IEEE Transactions on Software Engineering vol.15(10).
Bischofberger, W. and Keller, R. 1989. Enhancing the Software Life Cycle by Prototyping. Structured Programming.
Bloom, P. April 1993. Trends in Client-Server/Cooperative Processing Application Development Tools. American Programmer, Arlington MA: Cutter Information Corporation.
Boar, B. 1984. Application Prototyping. New York, New York: John Wiley and Sons.
Boehm, B. August 1986. A Spiral Model of Software Development and Enhancement.
Software Engineering Notes, vol.11(4).
-- September 1992. Risk Control. American Programmer vol.5(7).
Boehm, В. and Papaccio, P. 1988. Understanding and Controlling Software Costs. IEEE Transactions on Software Engineering vol.4(10).
Boehm-Davis, D., and Ross., L. October 1984. Approaches to Structuring the Software Development Process. Report GEC/DIS/TR-84-B1V-1. Arlington, VA: General Electric.
Booch, G. 1986. Software Engineering with Ada. Menlo Park, CA: Benjamin/Cummings. Brooks, F. 1975. The Mythical Man-Month, Reading, MA: Addison-Wesley.
-- April 1987. No Silver Bullet: Essence and Accidents of Software Engineering. IEEE Computer vol.20(4).
Charette, R. 1989. Software Engineering Risk Analysis and Management. New York, New York: McGraw-Hill Book Company.
Chidamber, S. and Kemerer, C. Towards a Metrics Suite for Object-Oriented Design. Phoenix, Arizona: OOPSLA'91.
-- 1993. A Metrics Suite for Object-oriented Design. Cambridge, Massachusetts: MIT Sloan School of Management.
Chmura, I., Norcio, A., and Wicinski, T. July 1990. Evaluating Software Design Processes by Analyzing Change Date Over Time. IEEE Transactions on Software Engineering vol.16(7).
Сох, В. November 1990. Planning the Software Industrial Revolution. IEEE Software vol.7(6).
Curtis, В. 17 May. 1989. ...But You Have To Understand, This Isn't the Way We Develop Software At Our Company. MCC Technical Report Number STP-203-89. Austin, TX: Microelectronics and Computer Technology Corporation.
Curtis, В., Kellner, M., and Over, J. September 1992. Process Modeling, Communications of the ACM vol.35(9).
Dahl, 0., Dijkstra, E., and Hoare, C. A. 1972. Structured Programming. London, England: Academic Press.
Davis, A. 1990. Software Requirements: Analysis and Specification. Englewood Cliffs, New Jrsey: Prentice-Hall.
Davis, A., Bersoff, E., and Comer, E. October 1988. A Strategy for Comparing Alternative Software Development Life Cycle Models. IEEE Transactions on Software Engineering vol.14(10).
Davis, C., Jajodia, S., Ng, P., and Yeh, R. eds. 1983. Entity-Relationship Approach to Software Engineering. Amsterdam, The Netherlands: Elsevier Science.
DeMarco, Т., and Lister, T. 1987. Peopleware. New York, NY: Dorset House.
DeRemer, F., and Kron, H. 1980. Programming-in-the-Large versus Programming-in-the-Small
Tutorial on Software Design Techniques, 3rd ed. ed. P. Freeman and A. Wasserman. New York, NY: Computer Society Press of the IEEE.
Dewire, D. 1992. Client/Server Computing. New York, NY: McGraw-Hill.
Dijkstra, E. 1979. Programming Considered as a Human Activity, in Classics in Software Engineering, ed. E. Yourdon. New York, NY: Yourdon Press.
-- 1982. Selected Writings on Computing: A Personal Perspective. New York, NY: Springer-Verlag.
Dowson, M. August 1986. The Structure of the Software Process. Software Engineering Notes, vol.11(4).
Dowson, M., Nejmeh, В., and Riddle, W. February 1990. Software Engineering Practices in Europe, Japan, and the U.S. Boulder, Colorado Software Design and Analysis.
Dreger, B. 1989. Function Point Analysis. Englewood Cliffs, NJ: Prentice-Hall.
Eastman, N. 1984. Software Engineering and Technology. Technical Directions vol.10(1). Bethesda, MD: IBM Federal Systems Division.
Fagan, M. June 1976. Design and Code Inspections and Process in the Development of Programs. IBM-TR-00.73.
Foster, C. 1981. Real-Time Programming. Reading, MA: Addison-Wesley.
Freedman, D. February 1992. The Devil Is in the Details Everything Important Must be Reviewed. American Programmer vol.5(2).
Freeman, P. 1975. Software Systems Principles. Chicago, IL: Science Research Associates.
Freeman, P., and Wasserman, A. eds. 1983. Tutorial on Software Design Techniques. Fourth Edition. New York, NY: Computer Society Press of the IEEE.
Gehani, N. and McGettrick, A. 1986. Software Specification Techniques. Reading, Massachusetts:
Addison-Wesley Publishing Company.
Gilb, T. 1988. Principles of Software Engineering Management. Reading, Massachusetts: Addison-Wesley Publishing Company.
Glass, R. 1982. Modem Programming Practices: A Report from Industry. Englewood Cliffs, NJ: Prentice-Hall.
-- 1983. Real-Time Software. Englewood Cliffs, NJ: Prentice-Hall.
-- 1991. Software Conflict. Englewood Cliffs, NJ: Yourdon Press.
Goldberg, A. and Rubin, K. 1992. Tutorial on Object-oriented Project Management. Vancouver, Canada: OOPSLA'92.
Guengerich, S. 1992. Downsizing In formation Systems. Carmel, Indiana: Sams.
Guindon, R., Krasner, H., and Curtis, B. 1987. Breakdowns and Processes During the Early Activities of Software Design by Professionals. Empirical Studies of Programmers, Second Workshop. Norwood, New Jersey: Ablex Publishing Company.
Guttman, M. and Matthews, J. November/December 1992. Managing a Large Project. Object Magazine vol.2(4).
Hansen, P. 1977. The Architecture of Concurrent Programs. Englewood Cliffs, NJ: Prentice-Hall.
Henderson-Sellers, B. and Edwards, J. September 1990. The Object-oriented Systems Lifecycle. Communications of the ACM vol.33(9).
Hoare, C. April 1984. Programming: Sorcery or Science? IEEE Software vol.1(2).
Holt, R., Lazowska, E., Graham, G., and Scott, M. 1978. Structured Concurrent Programming. Reading, MA: Addison-Wesley.
Humphrey, W. 1988. Characterizing the Software Development Process: A Maturity Framework. IEEE Software vol.5(2).
-- 1989. Managing the Software Process. Reading, MA: Addison-Wesley. Jackson, M. 1975. Principles of Program Design. Orlando, FL: Academic Press.
-- 1983. System Development. Englewood Cliffs, NJ: Prentice-Hall.
Jensen, R., and Tonies, C. 1979. Software Engineering. Englewood Cliffs, NJ: Prentice-Hall.
Jones, C. September 1984. Reusability in Programming: A Survey of the State of the Art. IEEE Transactions on Software Engineering vol.SF-10 (5).
-- September 1992. Risky Business: The most Common Software Risks. American Programmer vol.5(7).
Karam, G. and Casselman, R. February 1993. A Cataloging Framework for Software Development Methods. IEEE Computer.
Kishida, K., Teramoto, M., Torri, K., and Urano, Y.
September 1988. Quality Assurance Technology in Japan. IEEE Software vol.4(5).
Lammers, S. 1986. Programmers at Work. Redmond, WA: Microsoft Press.
Laranjeira, L. May 1990. Software Size Estimation of Object-Oriented Systems. IEEE Transactions on Software Engineering vol.16(5).
Ledgard, H. Summer 1985. Programmers: The Amateur vs. the Professional. Abacus vol.2(4).
Lejter, M., Myers, S., and Reiss, S. December 1992. Support for Maintaining Object-Oriented Programs. IEEE Transactions on Software Engineering vol. 18(12).
Linger, R., and Mills, H. 1977. On the Development of Large Reliable Programs, in Current Trends in Programming Methodology: Software Specification and Design vol.1. ed. R. Yeh. Englewood Cliffs, NJ: Prentice-Hall.
Linger, R., Mills, H., and Witt, B. 1979. Structured Programming. Theory and Practice. Reading, MA: Addison-Wesley.
Liskov, B. and Guttag, J. 1986. Absraction and Specification in Program Development. Cambridge, MA: The MIT Press.
Lorin, H. 1972. Parallelism in Hardware and Software. Englewool Cliffs, NJ: Prentice-Hall.
Luqi, August 1990. A Graph Model for Software Evolution. IEEE Transactions on Software Engineering vol.16(8).
-- May 1990. Software Evolution Through Rapid Prototyping. IEEE Computer vol.22(5).
Martin, J., and McClure, C. 1988. Structured Techniques: The Basis for CASE. Englewood Cliffs, NJ: Prentice-Hall.
Mascot, Version 3.1, The Official Handbook of. June 1987. London, England: Crown Copyright. Matsubara, T. July/August 1990. Bringing up Software Designers. American Programmer vol.3(7-8).
McCabe, Т. and Butler, C. December 1989. Design Complexity Measurement and Testing. Communications of the ACM vol.32(12).
Mellichamp, D. 1983. Real-Time Computing. New York, NY: Van Nostrand Reinhold.
Mills, H. November 1986. Structured Programming: Retrospect and Prospect. IEEE Software vol.3(6).
Mills, J. July 1985. A Pragmatic View of the System Architect. Communications of the ACM vol.28(7).
Mimno, P. April 1993. Client-Server Computing.
American Programmer, Arlington MA: Cutter Information Corporation.
Mullin, M. 1990. Rapid Prototyping for Object-oriented Systems. Reading, Massachusetts: Addison-Wesley Publishing Company.
Munck, R. 1985. Toward Large Software Systems That Work. Proceedings of The AlAA/ACM/ NASA/IEEE Computers in Aerospace V Conference. Menlo Park, CA: AIAA.
Myers, G. 1978. Composite/Structured Design. New York, NY: Van Nostrand Reinhold. Newport, J. 28 April 1986. A Growing Gap in Software. Fortune.
Ng, P. and Yeh, R. 1990. Modem Software Engineering. New York, New York: Van Nostrand Reinhold.
Office of the Under Secretary of Defense for Acquistion. September 1987. Report of the Defense Science Board Task on Military Software. Washington, D. C.
Oman, P. and Lewis, T. 1990. Milestones in Software Evolution. Los Alamitos, California: Computer Society Press of the IEEE.
Orr, K. 1971. Structured Systems Development. New York, NY: Yourdon Press.
Page-Jones, M. 1988. The Practical Guide to Structured Systems Design. Englewood Cliffs, NY: Yourdon Press.
Parnas, D. December 1985. Software Aspects of Strategic Defense Systems. Communications of the ACM vol.28(12).
-- July 1985a. Why Conventional Software Development Does Not Produce Reliable Programs. Software Aspects of Strategic Defense Systems, Report DCS-47-IR. Victoria, Canada: University of Victoria.
-- July 1985b. Why Software is Unreliable. Software Aspects of Strategic Defense Systems, Report DCS-47-IR. Victoria, Canada: University of Victoria.
Parnas, D. and Clements, P. 1986. A Rational Design Process: How and Why to Fake It. IEEE Transactions on Software Engineering vol.SE-12(2).
Peters, L. 1981. Software Design. New York, NY: Yourdon Press. Pressman, R. 1988. Making Software Happen. Englewood Cliffs, New Jersey: Prentice-Hall.
-- 1992. Software Engineering: A Practitioner's Approach, Third Edition. New York, NY: McGraw-Hill Book Company.
Rakos, J. 1990. Software Project Management for Small to Medium Sized Projects.
Englewood Cliffs, New Jersey: Prentice-Hall.
Ramamoorthy, C., Garg, V., and Prakask, A. July 1986. Programming in the Large. IEEE Transactions on Software Engineering vol.SE-12(7).
Rechtin, E. October 1992. The Art of Systems Architecting. IEEE Spectrum vol.29(10). Rettig, M. October 1990. Software Teams. Communications of the ACM vol.33(10).
Ross, D., Goodenough, J., and Irvine, C. 1980. Software Engineering: Process, Principles, and Goals. Tutorial on Software Design Techniques, 3rd Ed. ed. P. Freeman and A. Wasserman. New York, NY: Computer Society Press of the IEEE.
Rubinstein, R. and Hersh, H. 1984. The Human Factor. Burlington, Massachusetts Digital Press.
Schulmeyer, G. and McManus, J. 1992. Handbook of Software Quality Assurance, Second Edition. New York, New York: Van Nostrand Reinhold.
Shaw, M. November 1990. Prospects for an Engineering Discipline of Software. IEEE Software vol.7(6).
Smith, M. and Robson, D. June 1992. A Framework for Testing Object-oriented Programs. Journal of Object-oriented Programming vol.5(3).
Software Process Workshop. May 1988. SIGSOFT Software Engineering Notes vol.14(4). Sommerville, I. 1989. Software Engineering, 3rd ed. Wokingham, England: Addison-Wesley.
Song, X., and Osterweil, L. 1993. Executing an Iterative Design Process. Irvine, California: University of California.
Spector, A., and Gifford, D. April 1986. Computer Science Perspective of Bridge Design. Communications of the ACM vol.29(4).
Stevens, W., Myers., G., and Constantine, L. 1979. Structured Design, in Classics in Software Engineering, ed. E. Yourdon. New York, NY: Yourdon Press.
Symons, C. 1988. Function Point Analysis: Difficulties and Improvements. IEEE Transactions on Software Engineering vol.14(1).
Taylor, D. 1990. Object-Oriented Technology A Manager's Guide. Alameda, California: Servio Corporation.
The Software Trap: Automate - Or Else. 9 May. 1988. Business Week. Thomsett, R. July/August 1990. Effective Project Teams. American Programmer vol. 3(7-8).
-- June 1991. Managing Superlarge Projects: A Contingency Approach. American Programmer vol.4(6).
U. S. Department of Defense. 30 July 1982. Report ofthe DoD Joint Service Task Force on Software Problems. Washington, D.C.
van Genuchten, M. June 1991. Why is Software Late? An Empirical Study of Reasons for Delay in Software Development. IEEE Transactions on Software Engineering vol.17(6).
Vick, С., and Ramamoorthy, C. 1984. Software Engineering. New York, NY: Van Nostrand Reinhold. Vonk, R. 1990. Prototyping. Englewood Cliffs, NJ: Prentice-Hall.
Walsh, J. Preliminary Defect Data from the Iterative Development of a Large C+ + Program. Vancouver, Canada: OOPSLA'92.
-- January 1993. Software Quality in an Iterative Object-Oriented Development Paradigm. Santa Clara, California: Rational.
Ward, M. 1990. Software that Works. San Diego, California: Academic Press.
Ward, P., and Mellor, S. 1985. Structured Development for Real-Time Systems: Introduction and Tools. Englewood Cliffs, NJ: Yourdon Press.
Wegner, P. 1980. Research Directions in Software Technology. Cambridge, MA: The MIT Press.
-- July 1984. Capital-intensive Software Technology. IEEE Software vol.1(3).
Weinberg, G. 1988. Understanding the Professional Programmer. New York, New York: Dorset House Publishing.
Weinberg, G. and Freedman, D. 1990. Handbook of Walkthroughs, Inspections, and Technical Reviews. New York, New York: Dorset House.
Whitten, N. 1990. Managing Software Development Projects. New York, New York: John Wiley and Sons.
Wilde, N. and Huitt, R. December 1992. Maintenance Support for Object-Oriented Programs. IEEE Transactions on Software Engineering vol.18(12).
Wilde, N., Matthews, P. and Huitt, R. January 1993. Maintaining Object-oriented Software. IEEE Software vol.10(1).
Wirth, N. 1986. Algorithms and Data Structures. Englewood Cliffs, NJ: Prentice-Hall.
Workshop on Software Configuration Management. November 1989. SIGSOFT Software Engineering Notes vol.17(7).
Yamaura, T. January 1992.
Standing Naked in the Snow. American Programmer vol.5(1).
Yeh, R. ed. 1977. Current Trends in Programming Methodology: Software Specification and Design. Englewood Cliffs, NJ: Prentice-Hall.
Yourdon, E. 1975. Techniques of Program Structure and Design. Englewood Cliffs, NJ: Prentice-Hall.
-- 1979. ed. Classics in Software Engineering. New York, NY: Yourdon Press.
-- 1989a. Modem Structured Analysis. Englewood Cliffs, NJ: Prentice-Hall.
-- 1989b. Structured Walkthroughs. Englewood Cliffs, NJ: Prentice-Hall.
-- August 1989с. The Year of the Object. Computer Language vol.6(8).
-- Summer 1989d. Object-oriented Observations. American Programmer vol.2(7-8).
Yourdon, E., and Constantine, L. 1979. Structured Design. Englewood Cliffs, NJ: Prentice-Hall.
Zahniseer, R. July/August 1990. Building Software in Groups. American Programmer vol.3(7-8).
Zave, P. February 1984. The Operational versus the Conventional Approach to Software Development. Communications of the ACM vol.27(2).
Zeikowitz, M. June 1978. Perspectives on Software Engineering. ACM Computing Surveys vol.10(2).
I. Специальная литература
Alexander, С. 1979. The Timeless Way of Building. New York, New York: Oxford University Press.
DeGrace, P. and Stahl, L. 1990. Wicked Problems, Righteous Solutions. Englewood Cliffs, New Jersey: Yourdon Press.
Fukuyama, F. 1992. The End of the Last Man. New York, New York: The Free Press.
Gall., J. 1986. Systemantics: How Systems Really Work and How They Fail. 2nd ed. Ann Arbor, MI: The General Systemantics Press.
Gleick, J. 1987. Chaos. New York, NY: Penguin Books.
Heckbert, P. 1988. Ray Tracing Jell-O Brand Gelatin. Communications of the ACM vol.31(2).
Heinlein, R. 1966. The Moon Is a Harsh Mistrres. New York, NY: The Berkeley Publishing Group.
Hofstadter, D. 1979. Godel, Escher, Bach: An Eternal Golden Braid. New York, NY: Vintage Books.
Inside Macintosh Volumes 1-5. 1988. Reading, MA: Addison-Wesley.
Kawasaki, G. 1990. The Macintosh Way. Glenview, Illinois Scott, Foresman and Company.
Lakoff, G. and Johnson, M. 1980. Metaphors We Live By. Chicago, Illinois: The University of Chicago Press.
Lammers, S. 1986. Programmers at Work. Bellevue, Washington, Microsoft Press.
Meyer, C., and Matyas. 1982. Cryptography. New York, NY:John Wiley and Sons.
Parker, T. 1983. Rules of Thumb. Boston, Massachusetts: Houghton Mifflin Company.
Peter, L. 1986. The Peter Pyramid. New York, NY: William Morrow.
Petroski, H. 1985. To Engineer Is Human. New York, NY: St. Martin's Press.
Rand, Ayn. 1979. Introduction to Objectivist Epistemology. New York, NY: New American Library.
Reti. L. 1988. The Unknown Leonard. New York, New York: Abradale Press.
Sears, F., Zemansky, M., and Young., H. 1987. University Physics. Seventh ed. Reading, MA: Addison-Wesley.
vonOech, R. 1990. A Whack on the Side of the Head. New York, New York: Warner Books, Incorporated.
Wagner, J. 1986. The Search for Signs of Intelligent Life in the Universe. New York, NY: Harper and Row.
Whitehead, A. 1958. An Introduction to Mathematics. New York, NY: Oxford University Press.
J. Теория
Aho, A., Hopcroft, J., and Ullman, J. 1974. The Design and Analysis of Computer Programs. Reading, MA: Addison-Wesley.
Almarode, J. October 1989. Rule-Based Delegation for Prototypes. SIGPLAN Notices vol.24(10).
Appelbe, W. and Ravn, A. April 1984. Encapsulation Constructs in Systems Programming Languages. ACM Transactions on Programming Languages and Systems vol.6(2).
Averill, E. April 1982. Theory of Design and Its Relationship to Capacity Measurement. Proceedings of the Fourth Annual International Conference on Computer Capacity Management. San Francisco, CA: Association of Computing Machinery.
Barr, A., and Feigenbaum, E. 1981. The Handbook of Artificial Intelligence. Los Altos, CA: William Kaufmann.
Bastani, F., and Iyengar, S. March 1987. The Effect of Data Structures on the Logical Complexity of Programs. Communications of the ACM vol.30 (3)
Bastani, F., Hilal, W., and Sitharama, S. October 1987.
Efficient Abstract Data Type Components for Distributed and Parallel Systems. IEEE Computer vol.20(10).
Belkhouche, В., and Urban, J. May 1986. Direct Implementation of Abstract Data Types from Abstract Specifications. IEEE Transactions on Software Engineering vol.SE-12(5).
Bensley, E., Brando, Т., and Prelle, M. September 1988. An Execution Model for Distributed Object-Oriented Computation. SIGPLAN Notices vol. 23(11).
Berztiss, A. 1980. Data Abstraction, Controlled Iteration and Communicating Processes. Communications of the ACM.
Bishop, J. 1986. Data Abstraction in Programming Languages. Wokingham, England: Addison-Wesley.
Boehm, H., Demers, A., and Donahue, J. October 1980. An Informal Description of Russell. Technical Report TR 80-430. Ithaca, NY: Cornell University.
Borning, A., Duisberg, R., Freeman-Benson, В., Kramer. A., and Woolf, M. October 1987. Constraint Hierarchies. SIGPLAN Notices vol.22(12).
Boute, R. January 1988. Systems Semantics: Principles, Applications, and Implementation. ACM Transactions on Programming Languages and Systems vol.10(1).
Brachman, R. October 1983. What Is-a Is and Isn't: An Analysis of Taxonomic Links in Semantic Networks. IEEE Computer vol.16(10).
Brachman, R., and Levesque, H. eds. 1985. Readings in Knowledge Representation. Los Altos, CA: Morgan Kaufmann.
Brooks, R. April 1987. Intelligence without Representation. Cambridge, Massachusetts: MIT Artificial Intelligence Laboratory.
Bruce, K., and Wegner, P. October 1986. An Algebraic Model of Subtypes in Object-Oriented Languages. SIGPLAN Notices vol.21(10).
Card, S., Moran, Т., nad Newell, A. 1983. The Psychology of Human-Computer Interaction. Hillsdale, New Jersey: Lawrence Erlbaum Associates.
Cardelli, L, and Wegner, P. December 1985. On Understanding Types, Data Abstraction, and Polymorphism. ACM Computing Surveys vol.17(4).
Claybrook, В., and Wyckof, M. 1980. Module: an Encapsulation Mechanism for Specifying and Implementing Abstract Data Types. Communications of the ACM.
Cline, A., and Rich, E. December 1983. Building and Evaluating Abstract Data Types, Report TR-83-26. Austin, TX: University of Texas, Department of Computer Sciences.
Cohen, A. January 1984. Data Abstraction, Data Encapsulation, and Object-oriented Programming. SIGPLAN Notices vol.19(1).
Cohen, N. November/December 1985. Tasks as Abstraction Mechanisms. Ada Letters vol.5(3-6).
Cohen, P., and Loiselle, C. August 1988. Beyond ISA: Structures for Plausible Inherence in
Semantic Nets. Proceedings of the Seventh National Conference on Artificial Intelligence. Saint Paul, MN: American Association for Artificial Intelligence.
Collins, W. 1992. Data Structures: An Object-oriented Approach. Reading, Massachusetts: Addison-Wesley Publishing Company.
Cook, W., and Palsberg, J. October 1989. A Denotational Semantics of Inheritance and Its Correctness. SIGPLAN Notices vol.24(10).
Courtois, P., Heymans, F., and Parnas, D. October 1971, Concurrent Control with "Readers" and "Writers." Communications of the ACM vol.14(10).
Danforth, S., and Tomlinson, C. March 1988. Type Theories and Object-oriented Programming. ACM Computing Surveys vol.20(1).
Demers, A., Donahue, J., and Skinner, G. Data Types as Values: Polymorphism, Type-Checking, Encapsulation. Proceedings of the Fifth Annual ACM Symposium on Principles of Programming Languages. New York, NY: Association of Computing Machinery.
Dennis, J., and Van Horm, E. March 1966. Programming Semantics for Multiprogrammed Computations. Communications of the ACM vol.9(3).
Donahue, J., and Demers, A. July 1985. Data Types Are Values. ACM Transactions on Programming Languages and Systems vol.7(3).
Eckart, J. April 1987. Iteration and Abstract Data Types. SIGPLAN Notices vol.22(4).
Embley, D., and Woodfield, S. 1988. Assessing the Quality of Abstract Data Types Written in Ada. Proceedings of the 10th International Conference on Software Engineering. New York, NY: Computer Society Press of the IEEE.
Ferber, J.
October 1989. Computational Reflection in Class-Based Object-oriented Languages. SIGPLAN Notices vol.24(10).
Fisher, J. and Gipson, D. November 1992. In Search of Elegance. Computer Language vol.9(11).
Gannon, J. Hamlet, R., and Mills, H. July 1987. Theory of Modules. IEEE Transactions on Software Engineering vol.SE-13(7).
Gannon, J., McMullin, P., and Hamlet, R. July 1981. Data Abstraction Implementation, Specification, and Testing. ACM Transactions on Programming Languages and System vol.3(3).
Gardner, M. May/June 1984. When to Use Private Types. Ada Letters vol.3(6).
Goguen, J. Thatcher, J., and Wagner, E. 1977. An Initial Algebra Approach to the Specification, Correctness, and Implementation of Abstract Data Types, in Current Trends in Programming Methodology: Data Structuring vol. ed. R. Yeh. Englewood Cliffs, NJ: Prentice-Hall.
Goldberg, D. 1989. Genetic Algorithms. Reading, Massachusetts: Addison-Wesley Publishing Company.
Graube, N. October 1989. Metaclass Compatibility. SIGPLAN Notices vol.24(10).
Gries, D., and Prins, J. July 1985. A New Notion of Encapsulation. SIGPLAN Notices vol.20(7).
Grogono, P., and Bennett, A. November 1989. Polymorphism and Type Checking in Object-oriented Language. SIGPLAN Notices vol.24(11).
Guttag, J. 1980. Abstract Data Types and the Development of Data Sructures, in Programming Language Design, ed. A. Wasserman. New York, NY: Computer Society Press of the IEEE.
Hammons, C., and Dobbs, P. May/June 1985. Coupling, Cohesion, and Package Unity in Ada. Ada Letters vol.4(6). I
Harel, D. and Kahana, C. October 1992. On Statecharts with Overlapping. ACM Transactions on Software Engineering and Methodology vol.1(4).
Harel, D., Lachover, H., Naamad, A., Pnueli, A., Politi, M., Sherman, R. Shtull-Trauring, S., and Trakhtenbrot, M. April 1990. STATEMATE: A Working Environment for the Development of Complex Reactive Systems. IEEE Transactions on Software Engineering vol.16(4).
Harrison G., and Liu, D. July/August 1986. Generic Implementations Via Analogies in the Ada Programming Language.
Ada Letters vol.6(4).
Hayes, P. 1981. The Logic of Frames, in Readings in Artificial Intelligence, ed. B. Webber and N. Nilsson. Palo Alto, CA: Tioga.
Hayes-Roth, F., July 1985. A Backboard Architecture for Control. Artificial Intelligence vol.26(3).
Hayes-Roth, F., Waterman, D., and Lenat, D 1983. Building Expert Systems. Reading, MA: Addison-Wesley.
Haynes, C., and Friedman, D. October 1987. Embedding Continuations in Procedural Objects. ACM Transactions on Programming Languages and Systems vol.9(4).
Henderson, P. February 1986. Functional Programming, Formal Specification, and Rapid Prototyping. IEEE Transactions on Software Engineering vol.SE-12(2).
Herlihy, M., and Liskov, B. October 1982. A Value Transmission Method for Abstract Data Types. ACM Transactions on Programming Languages and Systems vol.4(4).
Hesselink, W. January 1988. A Mathematical Approach to Nondeterminism in Data Types. ACM Transactions on Programming Languages and Systems vol.10(1).
Hibbard, P., Hisgen, A., Rosenberg, J., Shaw, M., and Sherman, M. 1981. Studies in Ada Style. New York, NY: Springer-Verlag.
Hilfinger, P. 1982. Abstraction Mechanisms and Language Design. Cambridge, MA: The MIT Press.
Hoare, C. October 1974. Monitors: An Operating System Structuring Concept. Communications of the ACM vol.17(10).
Hoare, C. 1985. Communicating Sequential. Processes Englewood Cliffs, NJ: Prentice-Hall International. Hogg, J., and Weiser, S. October 1987. OTM: Applying Objects to Tasks. SIGPLANNotices vol.22(12).
Jajodia, S., and Ng. P. 1983. On Representation of Relational Structures by Entity-Relationship Diagrams, in Entity-Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Johnson, C., 1986. Some Design Constraints Required for the Assembly of Software Components: The Incorporation of Atomic Abstract Types into Generically Structured Abstract Types. Proceedings of the First International Conference on Ada Programming. Language Applications for the NASA Space Station.
Houston, TX: NASA Lyndon B. Johnson Space Center.
Kernighan, B. and Plauger, P. 1981. Software Tools in Pascal. Reading, MA: Addison-Wesley.
Knight, B. 1983. A Mathematical Basis for Entity Analysis, in Entity-Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Knuth, D. 1973. The Art of Computer Programming, Vol.1-3. Reading, MA: Addison-Wesley.
Kosko, B. 1992. Neural Networks and Fuzzy Systems. Englewood Cliffs, New Jersey: Prentice-Hall Incorporated.
LaLonde, W., and Pugh, J. August 1985. Specialization, Generalization, and Inheritance: Teaching Objectives Beyond Data Stmctures and Data Types. SIGPLAN Notices vol.20(8).
Leeson, J., and Spear, M. March 1987. Type-Independent Modules: The Preferred Approach to Generic ADTs in Modula-2. SIGPLAN Notices vol.22(3).
Lenzerini, M., and Santucci, G. 1983. Cardinality Constraints in the Entity-Relationship Model, in Entity-Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Levesque, H. July 1984. Foundations of a Functional Approach to Knowledge Representation. Artificial Intelligence vol.23(2).
Lindgreen, P. 1983. Entity Sets and Their Description, in Entity-Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Lins, C. 1989. A First Look at Literate Programming. Structured Programming. Liskov, B. May 1988. Data Abstraction and Hierarchy. SIGPLAN Notices vol.23(5).
-- 1980. Programming with Abstract Data Types, in Programming Language Design, ed. A. Wasserman. New York, NY: Computer Society Press of the IEEE.
Liskov, В., and Scheifler, R. July 1983. Guardians and Actions: Linguistic Support for Robust, Disttibuted Programs. ACM Transactions on Programming Languages and Systems vol.5(3).
Liskov, В., and Zilles, S. 1977. An Introduction to Formal Specifications of Data Abstractions, in Current Trends in Programming Methodology: Software Specification and Design vol.1.
ed. R. Yeh. Englewood Cliffs, NJ: Prentice-Hall.
Lowry, M. and McCartney. 1991. Automating Software Design. Cambridge, Massachusetts: The MIT Press.
Lucco, S. October 1987. Parallel Programming in a Virtual Object Space. SIGPLANNotices vol.22(12).
Maes, P. October 1987. Concepts and Experiments in Computational Reflection. SIGPLAN Notices vol.22(12).
Mark, L. 1983. What is the Binary Relationship Approach?, in Entity-Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Markowitz, V., and Raz, Y. 1983. A Modified Relational Algebra and Its Use in an Entity-Relationship Environment, in Entity-Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Matsuoka, S., and Kawai, S. September 1988. Using Tuple Space Communication in Distributed Object-Oriented Languages. SIGPLAN Notices vol.23(11).
McAllester, D., and Zabih, F. November 1986. Boolean Classes. SIGPLAN Notices vol.21(11). McCullough, P. October 1987. Transparent Forwarding: First Steps. SIGPLAN Notices vol.22(12).
Merlin, P., and Bochmanm, G. January 1983. On the Construction of Submodule Specifications and Communication Protocols. ACM Transactions on Programming Languages and Systems vol.5(1).
Meyer, B. 1987. Programming as Contracting, Report TR-EI-12/CO. Goleta, CA: Interactive Software Engineering.
-- October 1992. Applying "Design by Contract." IEEE Computer vol.25(10).
Minoura, Т., and Lyengar, S. January 1989. Data and Time Abstraction Techniques for Multilevel Concurrent Systems. IEEE Transactions on Software Engineering vol.15(1).
Murata, T. 1984 Modeling and Analysis of Concurrent Systems, in Software Engineering, ed. C. Vick and C. Ramamoorthy. New York, NY: Van Nostrand Reinhold.
Mylopoulos, J., and Levesque, H. 1984. An Overview of Knowledge Representation. On Conceptual Modeling: Perspectives from Artificial Intelligence, Databases and Programming Languages, ed. M.
Brodie. J. Mylopoulos, and J. Schmidt. New York, NY: Springer-Verlag.
Nakano, R. 1983. Integrity Checking in a Logic-Oriented ER Model, in Entity-Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Newton, M., and Watkins, J. November/December 1988. The Combination of Logic and Objects for Knowledge Representation. Journal of Object-Oriented Programming vol.1(4).
Nii, P. Summer 1986. Blackboard Systems: The Blackboard Model of Problem Solving and the Evolution of Blackboard Architectures. AI Magazine vol.7(2).
Ohori, A., and Buneman., P. October 1989. Static Type Inference for Parametric Classes. SIGPLAN Notices vol.24(1O).
Pagan, F. 1981. Formal Specification of Programming Language. Englewood Cliffs, NJ: Prentice-Hall.
Parent, C., and Spaccapieta, S. July 1985. An Algebra for a General Entity-Relationship Model. IEEE Transactions on Software Engineering vol.SE-II(7).
Parnas, D. 1977. The Influence of Software Structure on Reliability, in Current Trends in Programming Methodology: Software Specification and Design vol.1. ed. R. Yeh. Englewood Cliffs, NJ: Prentice-Hall.
-- 1980. Designing Software for Ease of Extension and Contraction, in Tutorial on Software Design Techniques, 3rd ed. ed. P. Freeman and A. Wasserman. New York, NY: Computer Society Press of the IEEE.
Parnas, D., Clements, P., and Weiss, D. 1983. Enhancing Reusability with Information Hiding. Proceedings of the Workshop on Reusability in Programming, Stratford, CT: ITT Programming.
Pattee, H. 1973 Hierarchy Theory. New York, NY: George Braziller.
Peckham, J., and Maryanski, F. September 1988. Semantic Data Models. ACM Computing Surveys vol.20(3).
Pedersen, С. October 1989. Extending Ordinary Inheritance Schemes to Include Generalization. SIGPLAN Notices vol.24(10).
Peterson., J. September 1977. Petri Nets. Computing Surveys vol.9(3). Reed, D. September 1978. Naming and Synchronization in a System. Cambridge, MA: The MIT Press.
Rich, C.
and Wills, L. January 1990. Recognizing a Program's Design: A Graph-Parsing Approach. IEEE Software vol.7(1).
Robinson, L., and Levitt, K. 1977. Proof Techniques for Hierarchically Structured Programs, in Current Trends in Programming Methodology: Program Validation vol.2. ed. R. Yeh. Englewood Cliffs, NJ: Prentice-Hall.
Ross, D. July/August 1986. Classifying Ada Packages. Ada Letters vol.6(4).
Ruane, L. January 1984. Abstract Data Types in Assembly Language Programming. SIGPLAN Notices vol.19(1).
Rumbaugh, J. September 1988. Controlling Propagation of Operations Using Attributes on Relations. SIGPLAN Notices vol.23(11).
Sedgewick, R. 1983. Algorithms. Reading, MA: Addison-Wesley.
Shankar, K. 1984. Data Design: Types, Structures, and Abstractions, in Software Engineering, ed. C. Vick and C. Ramamoorthy. New York, NY: Van Nostrand Reinhold.
Shaw, M. 1984. The Impact of Modeling and Abstraction Concerns on Modern Programming Languag0.85troduction to Data Types, in Programming Language Design, ed. A. Wasserman. New York, NY: Computer Society Press of the IEEE.
Sherman, M., Hisgen, A., and Rosenberg, J. 1982. A Methodology for Programming Abstract Data Types in Ada. Proceedings of The AdaTec Conference on Ada. New York. NY: Association of Computing Machinery.
Siegel, J. April 1988. Twisty Little Passages. HOOPLA: Hooray for Object-Oriented Programming Languages vol.1(3). Everette, WA: Object-Oriented Programming for Smalltalk Application Developers Association.
Stefik, M., Bobrow, D., and Kahn, K. January 1986. Integrating Access-Oriented Programming into a Multiparadigm Environment. IEEE Software vol.3(1).
Storm, R., and Yemini, S. January 1986. Typestate: A Programming Language Concept for Enhancing Software Reliability. IEEE Transaction on Software Engineering vol.SE-12(1).
Stubbs, D., and Webre, N. 1985. Data Structures with Abstract Data Types and Pascal. Monterey, CA: Broocs/Cole.
Swaine, M. June 1988. Programming Paradigms. Dr. Dobb's Journal of Software Tools, no. 140.
Tabourier, Y. 1983. Further Development of the Occurrences Structure Concept: The EROS Approach, in Entity-Relationship Approach to Software Engineering, ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Tanenbaum, A. 1981. Computer Networks. Englewood Cliffs, NJ: Prentice-Hall. Throelli, L. October 1987. Modules and Type Checking in PL/LL. SIGPLAN Notices vol.22(12).
Tomlinson, C. and Singh, V. October 1989. Inheritance and Synchronization with Enabled-sets. SIGPLAN Notices vol.24(10).
Toy, W. 1984. Hardware/Software Tradeoffs in Software Engineering. Ed. C. Vick and C. Ramamoorthy. New York, NY: Van Nostrand Reinhold.
Vegdahl, S. November 1986. Moving Structures between Smalltalk Images. SIGPLAN Notices vol.21(11).
Walters, N. October 1992. Using Harel Statecharts to Model Object-oriented Behavior. SIGSOFT Notices vol.17(4).
Wasserman, A. 1980. Introduction to Data Types, in Programming Language Design, ed. A. Wasserman. New York, NY: Computer Society Press of the IEEE.
Weber, H., and Ehrig, H. July 1986. Specification of Modular Systems. IEEE Transactions on Software Engineering vol.SE-12(7).
Wegner, P. June 1981. The Ada Programming Language and Environment. Unpublished draft.
Wegner, P. 1987. On the Unification of Data and Program Abstraction in Ada, in Object-oriented Computing: Concepts vol.1. ed. G. Peterson. New York. NY: Computer Society Press of the IEEE.
Wegner, P. 1987. The Object-oriented Classification Paradigm, in Research Directions in Object-oriented Programming. ed. B. Schriver and P. Wegner. Cambridge, MA: The MIT Press.
Wegner, P., and Zdonik, S. August 1988. Inheritance as an Incremental Modification Mechanism or What Like Is and Isn't Like. Proceedings of ECOOP'88: European Conference on Object-oriented Programming. New York, NY: Springer-Verlag.
Weihl, W., and Liskov, B. April 1985. Implementation of Resilient, Atomic Data Types. ACM Transactions on Programming Languages and Systems vol. 7(2).
Weinberg, G. 1971.
The Psychology of Computer Programming. New York: Van Nostrand / Reinhold Company.
Weller, D., and York, B. May 1984. A Relational Representation of an Abstract Type System. IEEE Transactions on Software Engineering vol.SE-10(3).
White, J. July 1983. On the Multiple Implementation of Abstract Data Types within a Computation. IEEE Transactions on Software Engineering vol. SE-9(4).
Wirth, N. December 1974. On the Composition of Well-structured Programs. Computing Surveys vol.6(4).
-- January 1983. Program Development by Stepwise Refinement. Communications of the ACM vol.26(1).
-- 1986. Algorithms and Data Structures, Second Edition. Englewood Cliffs, NJ: Prentice-Hall.
-- April 1988. Type Extensions. ACM Transactions on Programming Languages and Systems vol.10(2).
Wolf, A., Clarke, L., and Wileden, J. April 1988. A Model of Visibility Control. IEEE Transactions on Software Engineering vol.14(4).
Woods, W. October 1983. What's Important About Knowledge Representation? IEEE Computer vol.16(10).
Zilles, S. 1984. Types, Algebras, and Modelling, in On Conceptual Modeling: Perspectives from Artificial Intelligence, Databases, and Programming Languages, ed. M. Brodie, J. Mylopoulos, and J. Schmidt. New York, NY: Springer-Verlag.
Zippel, R. June 1983. Capsules. SIGPLAN Notices vol.18(6).
K. Инструменты и среды разработки
Andrews, Т., and Harris, С. 1987. Combining Language and Database Advances in an Object- Oriented Development Environment. Billerica, MA: Ontologic.
Corradi, A., and Leonardi, L. 1986. An Environment Based on Parallel Objects. Bologna, Italy: Universita' di Bologna.
Deutsch, P., and Taft, E. June 1980. Requirements for an Experimental Programming Environment. Report CSL-80-10. Palo Alto, CA: Xerox Palo Alto Research Center.
Diederich, J., and Milton, J. October 1987. An Object-Oriented Design System Shell. SIGPLAN Notices vol.22(12).
Durant, D., Carlson, G., and Yao, P. 1987. Programmers Guide to Windows. Berkeley, CA: Sybex.
Ertman, L, Lark, J., and Hayes-Roth, F.
December 1988. ABE: An Environment for Engineering Intelligent Systems. IEEE Transactions on Software Engineering vol.14(12).
Ferrel, P., and Meyer, R. October 1989. Vamp: The Aldus Application Framework. SIGPLAN Notices vol.24(10).
Fischer, H., and Martin, D. 1987. Integrating Ada Design Graphics into the Ada Software Development Process. Encino, CA: Mark V Business Systems.
Goldberg, A. 1984a. Smalltalk-80: The Interactive Programming Environment. Reading, MA: Addison-Wesley.
-- 1984b. The Influence of an Object-oriented Language on the Programming Environment, in Interactive Programming Environments, ed. B. Barstow. New York, NY: McGraw-Hill.
Goldstein, I., and Bobrow, D. March 1981. An Experimental Description-Based Programming Environment, Report CSL-81-3. Palo Alto, CA: Xerox Palo Alto Research Center.
Gorlen, K. May 1986.Object-oriented Program Support. Bethesda, MD: National Institute of Health.
Hecht, A., and Simmons, A. 1986. Integrating Automated Structured Analysis and Design with Ada Programming Support Environments. Proceedings of the First International Conference on Ada Programming Language Applications for the NASA Space Station. Houston, TX: NASA Lyndon B.Johnson Space Center.
Hedin, G., and Magnusson B. August 1988. The Mjolner Environment: Direct Interaction with Abstractions. Proceedings of ECOOP'88: European Conference on Object-oriented Programming. New York, NY: Springer-Verlag.
Hudson, S., and King, R. June 1988. The Cactic Project: Database Support for Software Environments. IEEE Transactions on Engineering vol.14(6).
International Business Machines. April 1988. Operating System/2 Seminar Proceedings, IBM OS/2 Standard Edition Version 1.1, IBM Operating System/2 Update, Presentation Manager. Boca Ration, FL.
Kant, E. 26 March 1987. Interactive Problem Solving with a Task Configuration and Control System. Ridgefield, CT: Schlumberger-Doll Research.
Kleyn, M., and Ginrich, P. September 1988. GraphTrace - Understanding Object-oriented Systems Using Concurrently Animated Views.
SIGPLAN Notices vol.23(11).
Laff, M., and Hailpern, B. July 1985. SW-2 - An Object-Based Programming Environment SIGPLAN Notices vol.20(7).
MacLenna, B. July 1985. A Simple Software Environment Based on Objects and Relations. SIGPLAN Notices vol.20(7).
Marques, J., and Guedes, P. October 1989. Extending the Operating System to Support an Object-oriented Environment. SIGPLAN Notices vol.24(10).
Minsky, N., and Rozenshtein, D. February 1988. A Software Development Environment for Law-Governed Systems. SIGPLAN Notices vol.24(2).
Moreau, D., and Dominick, W. 1987. Object-oriented Graphical Information Systems: Research Plan and Evaluation Metrics. Lafayette, LA: University of Southwestern Louisiana, Center for Advanced Computer Studies.
Nakata, S., and Yamazak, G. 1983. ISMOS: A System Based on the E-R Model and its Application to Database-Oriented Tool Generation, in Entity-Relationship Approach to Software Engineering. ed. C. Davis et al. Amsterdam, The Netherlands: Elsevier Science.
Nye, A. 1989. Xlib Programming Manual for Version 11. Newton, MA: O'Reilly and Associates.
O'Brien, P., Halbert, D., and Kilian, M. October 1987. The Trellis Programming Environment. SIGPLAN Notices vol.22(12).
Open Look Graphical User Interface Functional Specification. 1990. Reading, MA: Addison-Wesley. OSF/Motif Style Guide, Version 1.0. 1989. Cambridge, MA: Open Software Foundation.
Penedo, M., Ploedereder, E., and Thomas, I. February 1988. Object Management Issues for Software Engineering Environments. SIGPLAN Notices vol.24(2).
Reenskaug, Т., and Skaar, A. October 1989. An Environment for Literate Smalltalk Programming. SIGPLAN Notices vol.24(10).
Rosenplantt, W., Wileden, J., and Wolf, A. October 1989. OROS: Toward a Type Model for Software Development Environments. SIGPLAN Notices vol. 24(10).
Russo, V., and Campbell, R. October 1989. Virtual Memory and Backing Storage Management in Multiprocessor Operating Systems Using Object-Oriented Design Techniques. SIGPLAN Notices vol.24(10).
Scheifler, R., and Gettys, J. 1986. The X Window System. ACM Transactions on Graphics vol.63.
Schwan, K., and Matthews, J. July 1986. Graphical Views of Parallel Programs. Software Engineering Notes, vol.11(3).
Shear, D. 8 December 1988. CASE Shows Promise but Confusion Still Exists. EDN vol.33(25). Sun Microsystems. 29 March 1987. NeWS Technical Overview Mountain View, CA.
Tarumi, H., Agusa, K., and Ohno, Y. 1988. A Programming Environment Supporting Reuse of Object-oriented Software. Proceedings of the 10th International Conference on Software Engineering, New York, NY: Computer Society Press of the IEEE.
Taylor, R., Belz, F., Clarke, L, Osterweil, L, Selby, R., Wielden, J., Wolf, A., and Young, M. February 1988. Foundations for the Arcadia Environment. SIGPLAN Notices vol.24(2).
Tesler, L. August 1981. The Smalltalk Environment. Byte vol.6(8).
Vines, D., and King, T. 1988. Gaia: An Object-oriented Framework for an Ada Environment. Minneapolis, MN: Honeywell.
Weinand, A., Gamma, E., and Marty, R. 1989. Design and Implementation of ET++, a Seamless Object-oriented Application Framework. Structured Programming vol.10(2).
Wiorkowski, G., and Kull, D. 1988. DB2 Design and Development Guide. Reading, MA: Addison-Wesley.
Что является и что не является объектом?
Способностью к распознанию объектов физического мира человек обладает с самого раннего возраста. Ярко окрашенный мяч привлекает внимание младенца, но, если спрятать мяч, младенец, как правило, не пытается его искать: как только предмет покидает поле зрения, он перестает существовать для младенца. Только в возрасте около года у ребенка появляется представление о предмете: навык, который незаменим для распознавания. Покажите мяч годовалому ребенку и спрячьте его: скорее всего, ребенок начнет искать спрятанный предмет. Ребенок связывает понятие предмета с постоянством и индивидуальностью формы независимо от действий, выполняемых над этим предметом [1].
В предыдущей главе объект был неформально определен как осязаемая реальность, проявляющая четко выделяемое поведение. С точки зрения восприятия человеком объектом может быть:
осязаемый и (или) видимый предмет;
нечто, воспринимаемое мышлением;
нечто, на что направлена мысль или действие.
Таким образом, мы расширили неформальное определение объекта новой идеей: объект моделирует часть окружающей действительности и таким образом существует во времени и пространстве. Термин объект в программном обеспечении впервые был введен в языке Simula и применялся для моделирования реальности [2].
Объектами реального мира не исчерпываются типы объектов, интересные при проектировании программных систем. Другие важные типы объектов вводятся на этапе проектирования, и их взаимодействие друг с другом служит механизмом отображения поведения более высокого уровня [3]. Это приводит нас к более четкому определению, данному Смитом и Токи: "Объект представляет собой конкретный опознаваемый предмет, единицу или сущность (реальную или абстрактную), имеющую четко определенное функциональное назначение в данной предметной области" [4]. В еще более общем плане объект может быть определен как нечто, имеющее четко очерченные границы [5].
Представим себе завод, на котором создаются композитные материалы для таких различных изделий как, скажем, велосипедные рамы и крылья самолетов.
Заводы часто разделяются на цеха: механический, химический, электрический и т.д. Цеха подразделяются на участки, на каждом из которых установлено несколько единиц оборудования: штампы, прессы, станки. На производственных линиях можно увидеть множество емкостей с исходными материалами, из которых с помощью химических процессов создаются блоки композитных материалов. Затем из них делается конечный продукт - рамы или крылья. Каждый осязаемый предмет может рассматриваться как объект. Токарный станок имеет четко очерченные границы, которые отделяют его от обрабатываемого на этом станке композитного блока; рама велосипеда в свою очередь имеет четкие границы по отношению к участку с оборудованием.
Существуют такие объекты, для которых определены явные концептуальные границы, но сами объекты представляют собой неосязаемые события или процессы. Например, химический процесс на заводе можно трактовать как объект, так как он имеет четкую концептуальную границу, взаимодействует с другими объектами посредством упорядоченного и распределенного во времени набора операций и проявляет хорошо определенное поведение. Рассмотрим систему пространственного проектирования CAD/CAM. Два тела, например, сфера и куб, имеют как правило нерегулярное пересечение. Хотя эта линия пересечения не существует отдельно от сферы и куба, она все же является самостоятельным объектом с четко определенными концептуальными границами.
Объекты могут быть осязаемыми, но иметь размытые физические границы: реки, туман или толпы людей [Это верно только на достаточно высоком уровне абстракции. Для человека, идущего через полосу тумана, бессмысленно отличать "мой туман" от "твоего тумана". Однако, рассмотрим карту погоды: полосы тумана в Сан-Франциско и в Лондоне представляют собой совершенно разные объекты]. Подобно тому, как взявший в руки молоток начинает видеть во всем окружающем только гвозди, проектировщик с объектно-ориентированным мышлением начинает воспринимать весь мир в виде объектов.
Разумеется, такой взгляд несколько упрощен, так как существуют понятия, явно не являющиеся объектами. К их числу относятся атрибуты, такие, как время, красота, цвет, эмоции (например, любовь или гнев). Однако, потенциально все перечисленное - это свойства, присущие объектам. Можно, например, утверждать, что некоторый человек (объект) любит свою жену (другой объект), или что конкретный кот (еще один объект) - серый.
Объект имеет состояние, обладает некоторым хорошо определенным поведением и уникальной идентичностью.
Полезно понимать, что объект - это нечто, имеющее четко определенные границы, но этого недостаточно, чтобы отделить один объект от другого или дать оценку качества абстракции. На основе имеющегося опыта можно дать следующее определение:
Объект обладает состоянием, поведением и идентичностью; структура и поведение схожих объектов определяет общий для них класс; термины "экземпляр класса" и "объект" взаимозаменяемы.
Что такое класс?
Понятия класса и объекта настолько тесно связаны, что невозможно говорить об объекте безотносительно к его классу. Однако существует важное различие этих двух понятий. В то время как объект обозначает конкретную сущность, определенную во времени и в пространстве, класс определяет лишь абстракцию существенного в объекте. Таким образом, можно говорить о классе "Млекопитающие", который включает характеристики, общие для всех млекопитающих. Для указания на конкретного представителя млекопитающих необходимо сказать "это - млекопитающее" или "то - млекопитающее".
Класс представляет набор объектов, которые обладают общей структурой и одинаковым поведением.
В общепонятных терминах можно дать следующее определение класса: "группа, множество или вид с общими свойствами или общим свойством, разновидностями, отличиями по качеству, возможностями или условиями" [17]. В контексте объектно-ориентированного анализа дадим следующее определение класса:
Класс - это некое множество объектов, имеющих общую структуру и общее поведение.
Любой конкретный объект является просто экземпляром класса. Что же не является классом? Объект не является классом, хотя в дальнейшем мы увидим, что класс может быть объектом. Объекты, не связанные общностью структуры и поведения, нельзя объединить в класс, так как по определению они не связаны между собой ничем, кроме того, что все они объекты.
Важно отметить, что классы, как их понимают в большинстве существующих языков программирования, необходимы, но не достаточны для декомпозиции сложных систем. Некоторые абстракции так сложны, что не могут быть выражены в терминах простого описания класса. Например, на достаточно высоком уровне абстракции графический интерфейс пользователя, база данных или система учета как целое, это явные объекты, но не классы [Можно попытаться выразить такие абстракции одним классом, но повторной используемости и возможности наследования не получится. Иметь громоздкий интерфейс - плохая практика, так как большинство клиентов использует только малую его часть. Более того, изменение одной части этого гигантского интерфейса требует обновления каждого из клиентов, независимо от того, затронуло ли его это изменение по сути. Вложенность классов не устраняет этих проблем, а только откладывает их]. Лучше считать их некими совокупностями (кластерами) сотрудничающих классов. Страуструп называет такие кластеры компонентами [18]. Мы же, по причинам, которые будут объяснены в главе 5, называем такие кластеры категориями классов.
Добавление источников знаний
Теперь, когда определены ключевые абстракции информационной доски и механизмы выдвижения и проверки предположений, необходимо реализовать механизм вывода (класс InferenceEngine), связывающий все источники знаний в единое целое. Ранее уже упоминалось, что механизм вывода должен реализовать одну основную операцию, а именно выполнение правила, evaluateRules. Мы не будем на этом подробно останавливаться, поскольку реализация не влияет на проектные решения.
Убедившись в правильной работе механизма вывода, можно последовательно вводить в систему источники знаний. Целесообразность именно такого процесса объясняется двумя причинами:
Трудно заранее выяснить, какие правила существенны для каждого из источников знаний, не испытав систему на конкретной задаче.
Отладка базы знаний существенно упрощается при последовательном добавлении правил.
Реализация источников знаний является предметом инженерии знаний. Для построения конкретного источника знаний требуется консультация с экспертами (например, криптографами). При анализе источников знаний может выявиться, что одни правила бесполезны, другие слишком специализированы или излишне обобщены, а некоторых явно недостает. После анализа правила источника могут модифицироваться. Иногда требуется создание нового источника знаний.
В процессе реализации источников знании могут выявиться общие для нескольких источников правила и/или поведение. Например, источник знаний о структуре слов и источник знаний о структуре предложений могут иметь в своем составе общие правила относительно возможного порядка следования некоторых языковых структур. В обоих случаях суть правила одна и та же, поэтому целесообразно ввести новый класс-примесь StructureKnowledgeSource, отражающий знания о структуре, в который и помещается это общее поведение.
Такое изменение структуры классов подчеркивает тот факт. что процесс обработки правил определяется не только источниками знаний, но и характером объектов доски. Например, один из источников знаний может реализовывать прямую последовательность рассуждений в отношении одних объектов и обратную последовательность - в отношении других. Кроме того, различные источники знаний могут по-разному оперировать с одним и тем же объектом.
11.4. Сопровождение
Добавление новых функций
Программное обеспечение сопровождается и постоянно дорабатывается, что особенно справедливо для таких больших систем, как наша. Действительно, до сих пор можно встретить программы, разработанные лет двадцать назад (просто патриархальные по компьютерным меркам). Чем больше пользователей применяет систему управления движением и чем лучше мы адаптируем проект к новым требованиям, тем чаще клиенты будут находить новые неожиданные применения для существующих механизмов, создавая потребность во включении в систему новых функций.
Рассмотрим единственное добавление к нашим требованиям: обработку платежной ведомости. Предположим, анализ показал, что работа с платежными ведомостями железнодорожной компании осуществляется с использованием аппаратуры, выпуск которой прекращен, поэтому возник серьезный риск безвозвратной потери всей системы платежей в результате нескольких критических поломок. В этом случае можно объединить обработку платежной ведомости с системой управления движением. Для начала надо понять, как эти две несвязанные задачи будут сосуществовать; можно рассматривать их как разные приложения, причем обработка платежной ведомости будет происходить в фоновом режиме.
Дальнейший анализ показывает, что от интеграции обработки платежной ведомости может быть получена огромная польза. Вспомним, что планы поездов содержат информацию о распределении бригад. Следовательно, мы можем проанализировать запланированное и действительное распределение бригад, вычислить рабочее время, сверхурочные часы и т. п. Получая эту информацию непосредственно, мы можем обрабатывать платежную ведомость дешевле и быстрее.
Что добавление этой функции затрагивает в нашем проекте? Очень немногое. Новую подсистему можно добавить в подсистему UserApplications. Оттуда новой подсистеме будут видны все важные механизмы, которые нужны для ее функционирования. Признак хорошо спроектированной объектно-ориентированной системы: значительные дополнения к требованиям могут быть учтены довольно просто путем надстройки новых функций над существующими механизмами.
Предположим, мы хотим ввести более существенное изменение: добавить экспертную систему, помогающую диспетчеру при определении маршрутов и реагирующую на чрезвычайные ситуации. Как это требование отразится на нашем проекте? Незначительно. Мы можем разместить новую подсистему между подсистемами TrainPlanDatabase и DispatcherApplications, так как база знаний, созданная для экспертной системы, подобна по содержанию TrainPlanDatabase; кроме того, подсистема DispatcherApplications является единственным клиентом экспертной системы. Нам предстоит разработать некоторый новый механизм, чтобы доводить рекомендации до конечного пользователя. Например, мы можем использовать метафору информационной доски, как это делалось в главе 11.
Дополнительная литература
Бигерстафф и Перлис (Biggerstaffand Perlis) [H 1989] провели исчерпывающий анализ повторного использования программного обеспечения. Вирфс-Брок (Wirfs-Brock) [С 1988] предложил хорошее введение в объектно-ориентированные среды разработки. Джонсон (Johnson) [G 1992] изучал вопросы документирования архитектуры сред разработки и выявил ряд общих моментов.
Библиотека МасАрр [G 1989] для Macintosh является хорошим примером правильно сконструированной объектно-ориентированной прикладной среды разработки. Введение в более раннюю версию этой библиотеки классов может быть найдено у Шмукера (Schmucker) [G 1986]. В недавней работе Голдстейн и Алджер (Goldstein and Alger) [С 1992] обсуждают развитие объектно-ориентированного программного обеспечения для Macintosh.
Другие примеры сред разработки: гипермедиа (Мейровиц (Meirowitz) [С 1986]), распознавание образов (Йошида (Yoshida) [С 1988]), интерактивная графика (Янг (Young) [С 1987]), настольные издательские системы (Феррел (Ferrel) [K 1989]). Среды разработки общего назначения: ЕТ++ (Вейнанд (Weinand) [K 1989]) и управляемые событиями MVC-архитектуры (Шэн (Shan) [G 1989]). Коггинс (Coggins) [С 1990] изучил, в частности, развитие библиотек для C++.
Эмпирическое изучение объектно-ориентированных архитектур и их влияния на повторное использование можно найти в работе Льюиса (Lewis) [С 1992].
Дополнительные обозначения
До сих пор мы занимались существенной частью нашей системы обозначений [Все существенные элементы в совокупности как раз и образуют нотацию Booch Lite]. Однако, чтобы передать некоторые часто встречающиеся стратегические и тактические решения, нам потребуется расширить ее. Общее правило: держаться существенных понятий и обозначений, а дополнительные применять только тогда, когда они действительно необходимы.
Параметризованные классы. В некоторых объектно-ориентированных языках программирования, в частности, C++, Eiffel и Ada можно создавать параметризованные классы. Как было сказано в главе 3, параметризованным классом называется семейство классов с общей структурой и поведением. Чтобы создать конкретный класс этого семейства, нужно подставить вместо формальных параметров фактические (процесс инстанцирования). Конкретный класс может порождать экземпляры.
Параметризованные классы достаточно сильно отличаются от обычных, что отмечается специальным украшением на их значках. Как показывает пример на рис. 5-8, параметризованный класс изображается значком обычного класса с пунктирным прямоугольником в правом верхнем углу, в котором указаны параметры. Инстанцированный класс изображается обычным значком класса с украшением в виде прямоугольника (со сплошной границей) с перечисленными в нем фактическими параметрами.
Связь между параметризованным классом и его инстанцированием изображается пунктирной линией, указывающей на параметризованный класс. Для получения инстанцированного класса необходим другой конкретный класс как фактический параметр (GardeningPlan в этом примере).
Параметризованный класс не может порождать экземпляры и не может использоваться сам в качестве параметра. Каждый инстанцированный класс является новым классом, отличающимся от других конкретных классов того же семейства.
Метаклассы. В некоторых языках, таких как Smalltalk и CLOS, есть метаклассы. Метакласс (см. главу 3) - это класс класса. В Smalltalk, например, метаклассы - это механизм поддержки переменных и операций класса (подобных статическим членам класса в C++), особенно фабрик класса (производящих операций), создающих экземпляры объектов данного класса.
В CLOS метаклассы играют важную роль в возможности уточнения семантики языка [9].
Рис. 5-9. Значок метакласса.
Метаклассы принципиально отличаются от обычных классов, и, чтобы подчеркнуть это, их значок закрашивается серым цветом, как это сделано на рис. 5-9. Связь между классом и его метаклассом (метасвязь) имеет вид жирной стрелки, направленной от класса к его метаклассу. Метакласс GardeningPlan обеспечивает методы-фабрики new() и default(), которые создают новые экземпляры класса GardeningPlan.
Метакласс не имеет экземпляров, но может любым образом быть ассоциирован с другими классами.
Метасвязь имеет еще одно применение. На некоторых диаграммах классов бывает полезно указать объект, который является статическим членом некоторого класса. Чтобы показать класс этого объекта, мы можем провести метасвязь "объект/ класс". Это согласуется с предыдущим употреблением: связь между некоторой сущностью (объектом или классом) и ее классом.
Утилиты классов. Благодаря своему происхождению, гибридные языки, такие как C++, Object Pascal и CLOS, позволяют разработчику применять как процедурный, так и объектно-ориентированный стиль программирования. Это контрастирует со Smalltalk, который целиком организован вокруг классов. В гибридном языке есть возможность описать функцию-не-член, называемую также свободной подпрограммой. Свободные подпрограммы часто возникают во время анализа и проектирования на границе объектно-ориентированной системы и ее процедурного интерфейса с внешним миром.
Утилиты классов употребляются одним из двух способов. Во-первых, утилиты класса могут содержать одну или несколько свободных подпрограмм, и тогда следует просто перечислить логические группы таких функций-не-членов. Во-вторых, утилиты класса могут обозначать класс, имеющий только переменные (и операции) класса (в C++ это означало бы класс только со статическими элементами [Программирующие на Smalltalk часто используют идиому утилит, чтобы достичь того же эффекта]). Таким классам нет смысла иметь экземпляры, потому что все экземпляры будут находиться в одном и том же состоянии.
Такой класс сам выступает в роли своего единственного экземпляра.
Рис. 5-10. Значок утилиты классов.
Как показано на рис. 5-10, утилита классов обозначается обычным значком класса с украшением в виде тени. В этом примере утилита классов PlanMetrics (параметры плана) предоставляет две важные операции: expectedYield (ожидаемый урожай) и timeToHarvest (время сбора урожая). Утилита обеспечивает эти две операции на основе услуг, предоставляемых классами нижнего уровня - GardeningPlan (план) и CropDatabase (база данных об урожае). Как показывает диаграмма, PlanMetrics зависит от CropDatabase: получает от нее информацию об истории посевов. В свою очередь, класс PlanAnalyst использует услуги PlanHetrics.
Рис. 5-10 иллюстрирует обычное использование утилит классов: здесь утилита предоставляет услуги, основанные на двух независимых абстракциях нижнего уровня. Вместо того, чтобы ассоциировать эти операции с классами высшего уровня, таких как PlanAnalyst, мы решили собрать их в утилиту классов и добились четкого разделения обязанностей между этими простыми процедурными средствами и более изощренной абстракцией класса-анализатора PlanAnalyst. Кроме того, включение свободных подпрограмм в одну логическую структуру повышает шансы на их повторное использование, обеспечивая более точное разбиение абстракции.
Связь классов с утилитой может быть отношением использования, но не наследования или агрегирования. В свою очередь, утилита класса может вступать в отношение использования с другими классами и содержать их статические экземпляры, но не может от них наследовать.
Подобно классам, утилиты могут быть параметризованы и инстанцированы. Для обозначения параметризованных утилит используются такие же украшения, как и для параметризованных классов (см. рис. 5-8). Аналогично, для обозначения связи между параметризованной утилитой класса и ее конкретизацией мы используем то же обозначение, что и для инстанцирования параметризованных классов.
Вложенность. Классы могут быть физически вложены в другие классы, а категории классов - в другие категории и т.д.
Обычно это нужно для того, чтобы ограничить видимость имен. Вложение соответствует объявлению вложенной сущности в окружающем ее контексте. Мы изображаем вложенность физически вложенным значком; на рис. 5-11 полное имя вложенного класса - Nutritionist::NutrientProfile.
Рис. 5-11. Значок вложенности.
В соответствии с правилами выбранного языка реализации, классы могут содержать экземпляры вложенного класса или использовать его. Языки обычно не допускают наследования от вложенного класса.
Обычно вложение классов является тактическим решением проектировщика, а вложение категорий классов - типично стратегическое архитектурное решение. В обоих случаях необходимость в использовании вложения на глубину более одного-двух уровней встречается крайне редко.
Управление экспортом. Все основные языки объектно-ориентированного программирования позволяют четко разделить интерфейс класса и его реализацию. Кроме того, как описано в главе 3, большинство из них позволяет разработчику определить более детально доступ к интерфейсу класса.
Например, в C++ элементы класса бывают открытыми (доступны всем клиентам), защищенными (доступны только подклассам, друзьям и самому классу) и закрытыми (доступны только самому классу и его друзьям). Кроме того, некоторые элементы могут быть частью реализации класса и тем самым быть недоступными даже друзьям этого класса [Например, объект или класс, описанный в .срр-файле, доступен только функциям-членам, реализованным в том же файле]. В Ada элементы класса могут быть открытыми или закрытыми. В Smalltalk все переменные экземпляров по умолчанию закрытые, а все операции - открытые. Доступ предоставляется самим классом и только явно: клиент ничего не может получить насильно.
Мы изображаем способ доступа следующими украшениями связи:
<нет украшения> - открытый (по умолчанию)
| - защищенный
|| - закрытый
||| - реализация
Мы ставим их как "засечки" на линии связи у источника. Например, на рис. 5-12 показано, что класс GrainCrop множественно наследует от классов Crop (посев) (открытый суперкласс) и FoodItem (пища) (защищенный суперкласс).
Рис. 5-12. Значок управления доступом.
FoodItem в свою очередь содержит от одного до двадцати трех закрытых экземпляров класса VitaminContent (содержание витаминов) и один открытый экземпляр класса CaloricEquivalent (калорийность). Заметим, что CaloricEquivalent мог бы быть записан как атрибут класса FoodItem, так как атрибуты эквивалентны агрегации, мощность которой равна 1:1. Кроме того, мы видим, что класс GrainCrop (посев зерновых) использует класс GrainYieldPredictor (предсказатель урожая зерновых) как часть своей реализации. Это обычно означает, что некоторый метод класса GrainCrop использует услуги, предоставляемые классом GrainYieldPredictor.
Кроме уже рассмотренных в этом примере случаев, обычная ассоциация так же может быть украшена символами доступа. Метасвязь (связь между инстанцированным классом и его метаклассом) не может получить таких украшений.
Символы ограничения доступа можно применять к вложенности во всех ее формах. На обозначении класса мы можем указать доступ к атрибутам, операциям или вложенным классам, добавив символ ограничения доступа в качестве префикса к имени. Например, на рис. 5-12 показано, что класс Crop имеет один открытый атрибут scientificName (ботаническое название), один защищенный - yield (урожай), и один закрытый - nutrientValue (количество удобрения). Такие же обозначения используются для вложенных классов или категорий классов. По умолчанию все вложенные классы и категории являются открытыми, но мы можем указать ограниченный доступ соответствующей меткой.
Типы отношении. В некоторых языках встречаются настолько всепроникающие типы отношений, с настолько фундаментальной семантикой, что было бы оправдано введение новых символов. В C++, например, имеется три таких конструкции:
static - переменная (или функция) класса;
virtual - совместно используемый базовый класс в ромбовидной структуре наследования;
friend - класс, которому даны права доступа к закрытым и защищенным элементам другого класса.
Рис. 5-13.
Значки отношений.
Логично использовать для них такое же украшение в виде треугольного значка, как и для абстрактного класса, но с символами S, V или F соответственно.
Рассмотрим пример на рис. 5-13, который представляет другой ракурс классов, показанных на предыдущем рисунке. Мы видим, что базовый класс OrganicItem (органический компонент) содержит один экземпляр класса ItemDictionary (словарь компонентов) и что этот экземпляр содержится самим классом, а не его экземплярами (то есть он является общим для всех экземпляров). В общем случае мы указываем обозначение static на одном из концов ассоциации или на конце связи агрегации.
Рассматривая класс GrainCrop, мы видим, что структура наследования приобретает ромбовидную форму (связи наследования, разветвившись, сходятся). По умолчанию, в C++ ромбовидная форма структуры наследования ведет к тому, что в классах-листьях дублируются структуры базового, дважды унаследованного класса. Чтобы класс GrainCrop получил единственную копию дважды унаследованных структур класса OrganicItem, мы должны применить виртуальное наследование, как показано на рисунке. Мы можем добавлять украшение виртуальной связи только к наследованию.
Значок дружественности можно присоединить к любому типу связи, расположив значок ближе к серверу, подразумевая, что сервер считает клиента своим другом. Например, на рис. 5-13 класс PlanAnalyst дружит с классом Crop, а, следовательно, имеет доступ к его закрытыми и защищенным элементам, включая оба атрибута yield и scientificName.
Физическое содержание. Как показано в главе 3, отношение агрегации является специальным случаем ассоциации. Агрегация обозначает иерархию "целое/часть" и предполагает, что по агрегату можно найти его части. Иерархия "целое/часть" не означает обязательного физического содержания: профсоюз имеет членов, но это не означает, что он владеет ими. С другой стороны, отдельная запись о посеве именно физически содержит в себе соответствующую информацию, такую, как имя посева, урожай и график подкормки.
Рис. 5-14. Физическое содержание.
Агрегация обычно выявляется при анализе и проектировании; уточнение ее как физического содержания является детализирующим, тактическим решением. Однако, распознать этот случай важно, во-первых, для правильного определения конструкторов и деструкторов классов, входящих в агрегацию, и, во-вторых, для генерации и последовательного исправления кода.
Физическое содержание отмечается на диаграмме украшением на конце линии, обозначающей агрегацию; отсутствие этого украшения означает, что решение о физическом содержании не определено. В гибридных языках мы различаем два типа содержания:
по значению целое физически содержит часть
по ссылке целое физически содержит указатель или ссылку на часть.
В чисто объектно-ориентированных языках, в особенности в Smalltalk, физическое содержание бывает только по ссылке.
Чтобы отличить физическое присутствие объекта от ссылки на него, мы используем закрашенный квадратик для обозначения агрегации по значению и пустой квадратик - для агрегации по ссылке. Как будет обсуждаться позже, этот стиль украшений согласуется с соответствующей семантикой на диаграммах объектов.
Рассмотрим пример, приведенный на рис. 5-14. Мы видим, что экземпляры класса CropHistory (история посева) физически содержат несколько экземпляров классов NutrientSchedule (график внесения удобрений) и ClimateEvent (климатическое событие). Физическое содержание частей агрегации по значению означает, что их создание или уничтожение происходит при создании или уничтожении самого агрегата. Таким образом, агрегация по значению гарантирует, что время жизни агрегата совпадает с временем жизни его частей. В противоположность этому, каждый экземпляр класса CropHistory обладает только ссылкой или указателем на один экземпляр класса Crop. Это означает, что времена жизни этих двух объектов независимы, хотя и здесь один является физической частью другого. Еще один случай - отношение агрегации между классами CropEncyclopedia (энциклопедия посевов) и CropHistory.
В данном случае мы вообще не упоминаем физическое содержание. Диаграмма говорит о том, что эти два класса состоят в отношении "целое/часть", и что по экземпляру CropEncyclopedia можно найти соответствующий экземпляр CropHistory, но физическое содержание тут ни при чем. Вместо этого может быть разработан другой механизм, реализующий эту ассоциацию. Например, объект класса CropEncyclopedia запрашивает базу данных, и получает ссылку на подходящий экземпляр CropHistory.
Роли и ключи. В предыдущей главе мы указали на важность описания различных ролей, играемых объектами в их взаимодействии друг с другом; в следующей главе мы изучим, как идентификация ролей помогает провести процесс анализа.
Коротко говоря, роль абстракции - это то, чем она является для внешнего мира в данный момент. Роль обозначает потребность или способность, в силу которых один класс ассоциируется с другим. Текстовое украшение, описывающее роль класса, ставится рядом с любой ассоциацией, ближе к выполняющему роль классу, как это видно на рис. 5-15. На этом рисунке классы PlanAnalyst (анализатор планов) и Nutritionist (агрохимик) оба являются поставщиками информации для объекта класса CropEncyclopedia (они оба добавляют информацию в энциклопедию), а объекты класса PlanAnalyst являются также и пользователями (они просматривают материал из энциклопедии). В любом случае, роль клиента определяет индивидуальное поведение и протокол, который он использует. Обратим внимание также на рефлексивную ассоциацию класса PlanAnalyst: мы видим, что несколько экземпляров этого класса могут сотрудничать друг с другом и при этом они используют особый протокол, отличающийся от их поведения в ассоциации, например, с классом CropEncyclopedia.
Рис. 5-15. Роли и ключи.
На этом примере показана также ассоциация между классами CropEncyclopedia и Crop, но с другим типом украшения, которое представляет ключ (изображается как идентификатор в квадратных скобках). Ключ - это атрибут, значение которого уникально идентифицирует объект.
В этом примере класс CropEncyclopedia использует атрибут scientificName, как ключ для поиска требуемой записи. Вообще говоря, ключ должен быть атрибутом объекта, который является частью агрегата, и ставится на дальнем конце связи-ассоциации. Возможно использование нескольких ключей, но значения ключей должны быть уникальны.
Рис. 5-16. Значок ограничения.
Ограничения. Как говорилось в главе 3, ограничение - это выражение некоторого семантического условия, которое должно сохраняться. Иначе говоря, ограничение - инвариант класса или связи, который должен сохраняться, если система находится в стабильном состоянии. Подчеркнем - в стабильном состоянии, потому что возможны такие переходные явления, при которых меняется состояние системы в целом и система находится во внутренне рассогласованном состоянии, так что невозможно соблюсти все наложенные ограничения. Соблюдение ограничений гарантируется только в стабильном состоянии системы.
Мы используем для ограничений украшения, похожие на те, что использовались нами для обозначения ролей и ключей: помещаем заключенное в фигурные скобки выражение ограничения рядом с классом или связью, к которым оно прилагается. Ограничение присоединяется к отдельным классам, к ассоциации в целом или к ее участникам.
На рис. 5-16 мы видим, что для класса EnviromentalController наложено ограничение на мощность, постулирующее, что в системе имеется не более 7 экземпляров этого класса. При отсутствии ограничения на мощность класс может иметь сколько угодно экземпляров. Обозначение для абстрактного класса, введенное ранее, является специальным случаем ограничения (нуль экземпляров), но так как это явление очень часто встречается в иерархиях классов, оно получило собственный тип украшения (треугольник с буквой А).
Класс Heater (нагреватель) имеет ограничение другого типа. В рисунок включено требование гистерезиса в работе нагревателя: он не может быть включен, если с момента его последнего выключения прошло меньше пяти минут. Мы прилагаем это ограничение к классу Heater, считая, что контроль за его соблюдением возложен на экземпляры класса.
На этой диаграмме изображены еще два типа ограничений: ограничение на ассоциации. В ассоциации между классами EnvironmentalController и Light требуется, чтобы отдельные источники света были уникально индексированы относительно друг друга в контексте данной ассоциации. Имеется еще ограничение, наложенное на ассоциации EnvironmentalController с классами Heater и Cooler, состоящее в том, что диспетчер не может включить нагреватель и охладитель одновременно. Это ограничение прикладывается к ассоциации, а не к классам Heater и Cooler, потому что его соблюдение не может быть поручено самим нагревателям и охладителям.
При необходимости можно включить в выражение ограничения имена других ассоциаций с помощью квалифицированных имен, использованных в проекте. Например, Cooler:: запускает однозначно именует одну из ассоциаций класса-диспетчера. В нашей системе обозначений такие выражения часто используются в ситуации, когда один класс имеет ассоциацию (например, агрегацию) с двумя (или более) другими классами, но в любой момент времени каждый его экземпляр может быть ассоциирован только с одним из объектов.
Ограничения бывают также полезны для выражения вторичных классов, атрибутов и ассоциаций [В терминологии Румбаха это называется производные сущности: для них он использует специальный значок. Нашего общего подхода к ограничениям достаточно, чтобы выразить семантику производных классов, атрибутов и ассоциации; этот подход облегчает повторное использование существующих значков и однозначное определение сущностей, от которых взяты производные]. Например, рассмотрим классы Adult (взрослые) и Child (дети), являющиеся подклассами абстрактного класса Person (Люди). Мы можем снабдить класс Person атрибутом dateofbirth (дата рождения) и добавить атрибут, называемый age (возраст), например, потому что возраст играет особую роль в нашей модели реального мира. Однако, age - атрибут вторичный: он может быть определен через dateofbirth. Таким образом, в нашей модели мы можем иметь оба атрибута, но должны указать ограничение, определяющее вывод одного из другого.
Вопрос о том, какие атрибуты из каких выводятся, относится к тактике, но ограничение пригодится независимо от принятого нами решения.
Аналогично, мы могли бы иметь ассоциацию между классами Adult и Child, которая называлась бы Parent (родитель), а могли бы включить и ассоциацию, именуемую Caretaker (попечитель), если это нужно в модели (например, если моделируются официальные отношения родительства в системе социального обеспечения). Ассоциация Caretaker вторична: ее можно получить как следствие ассоциации Parent; мы можем указать этот инвариант как ограничение, наложенное на ассоциацию Caretaker.
Ассоциации с атрибутами и примечания. Последнее дополнительное понятие связано с задачей моделирования свойств ассоциаций; в системе обозначений задача решается введением элемента, который может быть приложен к любой диаграмме.
Рассмотрим пример на рис. 5-17. На нем показана ассоциация многие-ко-многим между классами Crop и Nutrient. Эта ассоциация означает, что к каждому посеву применяется N (любое число) удобрений, а каждое удобрение применяется к N (любому числу) посевов. Класс NutrientSchedule является как бы свойством этого отношения многие-ко-многим: каждый его экземпляр соответствует паре из посева и удобрения. Чтобы выразить этот семантический факт, мы рисуем на диаграмме пунктирную линию от ассоциации Crop/Nutrient (ассоциация с атрибутом) к ее свойству - классу NutrientSchedule (атрибут ассоциации). Каждая уникальная ассоциация может иметь не больше одного такого атрибута и ее имя должно соответствовать имени класса-атрибута.
Идея атрибутирования ассоциаций имеет обобщение: при анализе и проектировании появляется множество временных предположений и решений; их смысл и назначение часто теряются, потому что нет подходящего места для их хранения, а хранить все в голове - дело немыслимое. Поэтому полезно ввести обозначение, позволяющее добавлять произвольные текстовые примечания к любому элементу диаграммы. На рис. 5-17 имеется два таких примечания. Одно из них, приложенное к классу NutrientSchedule, сообщает нечто об ожидаемой уникальности его экземпляров (Выбирает из общего набора расписаний); другое (Получаем из базы данных удобрений) приложено к конкретной операции класса Nutrient и выражает наши пожелания к ее реализации.
Рис. 5-17. Ассоциация с атрибутом и примечание.
Для таких примечаний мы используем значки, похожие на бумажки, и соединяем их с элементом, к которому они относятся, пунктирной линией. Примечания могут содержать любую информацию: обычный текст, фрагменты программ или ссылки на другую документацию (все это может пригодиться при разработке инструментов проектирования). Примечания могут быть не связаны ни с каким элементом, это значит, что они относятся к самой диаграмме [Значок, который мы используем, похож на обозначение примечаний во многих windows-системах, особенно следующих традициям Macintosh. Непосредственными вдохновителями нашего обозначения были предложения Гамма, Хелпа, Джонсона и Влиссидеса [10]].
Дополнительные понятия
Элементы диаграмм состояний и переходов, которые мы только что описали, недостаточны для многих случаев сложных систем. По этой причине мы расширим наши обозначения, включив семантику карт состояний, предложенную Харелом.
Рис. 5-21. Действия, условные переходы и вложенные состояния.
Действия, ассоциированные с состояниями и условные переходы. Как показано на рис. 5-18, с состояниями могут быть ассоциированы действия. В частности, можно назначить выполнение некоторого действия на входе или выходе из состояния, при этом используется синтаксис следующих примеров:
entry start Alarm - запуск процедуры при входе в состояние
exit shutDown() - вызов операции при выходе из состояния.
Как и для переходов, можно назначить любое действие после ключевых слов entry и exit(вход и выход).
Деятельность можно ассоциировать с состоянием, используя синтаксис следующего примера:
do Cooling - в данном состоянии заниматься этой деятельностью.
Этот синтаксис служит сокращенной записью явных указаний: "Начать деятельность при входе в состояние и окончить при выходе из него".
На рис. 5-21 мы видим пример использования этих обозначений. При входе в состояние Heating (нагревание) вызывается операция Heater::startUp(), а при выходе - операция Heater::shutDown(), то есть происходит запуск и остановка нагревания. При входе и выходе из состояния Failure (сбой), соответственно вызывается и прекращается сигнал тревоги (Alarm).
Рассмотрим также переход из состояния Idle в состояние Heating. Он совершается, если температура понизилась, но только в случае, если прошло больше пяти минут после того, как последний раз был выключен нагреватель. Это пример условного (или защищенного) перехода; условие представляется логическим выражением в скобках.
Вообще, каждый переход может быть ассоциирован либо с событием, либо с событием и условием. Допускаются и "переходы без события". В этом случае переход совершается сразу после завершения действия, связанного с состоянием, причем выполняется и действие, связанное с выходом из этого состояния.
Если переход условный, он состоится только в случае, если условие выполнено.
Имеет значение порядок выполнения условного перехода. Пусть имеется состояние S, из которого при событии E совершается переход T с условием C и действием A. Переход T осуществляется в такой последовательности:
Происходит событие E.
Проверяется условие C.
Если C удовлетворено, то выполняется переход T и действие A.
Это означает, что если условие C не выполнено, то переход не может быть осуществлен до тех пор, пока событие E не произойдет еще раз и условие C не будет проверено еще раз. Побочные эффекты при вычислении условия или выполнении действия, назначенного на выход, не могут отменить переход. Например, предположим, что произошло событие E, условие C выполнилось, но действие A, выполняемое при выходе из состояния S, изменило ситуацию так, что условие C перестало выполняться: переход T все равно состоялся.
Мы можем использовать еще и следующий синтаксис:
in Cooling - выражение для текущего состояния.
Здесь используется имя состояния (которое может быть квалифицированным). Выражение истинно тогда и только тогда, когда система находится в указанном состоянии. Такие условия особенно полезны, когда некоторому внешнему состоянию нужно запустить переход по условию, связанному с некоторым вложенным состоянием.
Можно использовать в условии и выражение, налагающее ограничения по времени:
timeout (Heating, 30) - выражение ограничения по времени.
Это условие выполняется, если система более 30 секунд находилась в состоянии Heating и остается в нем в момент проверки. Этот тип условия употребляется в системах реального времени для "переходов без события", так как защищает систему от зависания на долгое время в одном состоянии. Это выражение можно использовать для указания нижней границы времени нахождения в данном состоянии. Если приложить временное ограничение к каждому переходу с событием, выводящим из данного состояния, это будет равнозначно требованию, что система находится в каждом состоянии как минимум время, указанное в ограничении [Харел предложил "обобщенную завитушку" для обозначения двухсторонних границ по времени, но мы не будем обсуждать здесь его обобщения, так как условия исчерпания времени достаточно выразительны].
Что случится, если некое событие произойдет, а перейти в другое состояние нельзя либо потому, что не существует перехода для данного события, либо не выполняется условие перехода? По умолчанию это надо считать ошибкой: игнорирование событий обычно является признаком неполного анализа задачи. Вообще, для каждого состояния нужно документировать события, которые оно намеренно игнорирует.
Вложенные состояния. Возможность вложения состояний друг в друга придает глубину диаграммам переходов; эта ключевая особенность карт состояний Харела предотвращает комбинаторный взрыв в структуре состояний и переходов, который часто случается в сложных системах.
На рис. 5-21 показаны внутренние детали состояния Cooling, то есть вложенные в него состояния; для простоты мы опустили все его действия, включая действия при входе и выходе.
Объемлющие состояния, такие, как Cooling, называются суперсостояниями, а вложенные, такие, как Running, - подсостояниями. Вложенность может достигать любой глубины, то есть подсостояние может быть суперсостоянием для вложенных состояний более низкого уровня. Данное суперсостояние Cooling содержит три подсостояния. Семантика вложенности подразумевает отношение xor (исключающее или) для вложенных состояний: если система находится в состоянии Cooling (охлаждение), то она находится ровно в одном из подсостояний Startup (начальное), Ready (готовность) или Running (выполнение).
Чтобы проще ориентироваться в диаграмме переходов с вложенными состоя-ниями мы можем увеличить или уменьшить ее масштаб относительно выбранного состояния. При уменьшении вложенные состояния исчезают, а при увеличении проявляются. Переходы в скрытые на диаграмме подсостояния и выходы из них показываются стрелкой с черточкой, как переход в состояние Ready на рисунке [Если быть точными, то переходы Too hot и Ok относительно состояния Cooling также должны быть показаны на рис. 5-21 с черточкой, так как это переходы между подсостояниями].
Переходам между состояниями разрешено начинаться и кончаться на любом уровне.
Рассмотрим различные формы переходов:
Переход между одноуровневыми состояниями (такой, как из Failure в Idle или из Ready в Running) - простейшая форма перехода; его семантика описана в предыдущем разделе.
Можно совершить переход непосредственно в подсостояние (как из Idle
в Startup), или непосредственно из подсостояния (как из Running
в Idle), или одновременно и то, и другое.
Указание перехода из суперсостояния (как из Cooling в Failure через событие Failure) означает, что он осуществляется из каждого подсостояния этого суперсостояния. Такой переход пронизывает все уровни до переопределения. Это упрощает диаграмму за счет удаления банальных переходов, общих для всех подсостояний.
Указание перехода в состояние с вложенными подсостояниями (например, предыдущий переход в состояние Failure) подразумевает переход к его начальному подсостоянию (по умолчанию).
История. Иногда, возвращаясь к суперсостоянию, мы хотели бы попасть в то его подсостояние, где мы были последний раз. Эту семантику мы будем изображать значком истории (буква H (History) внутри кружка, размещенного где-нибудь внутри значка суперсостояния). Например, на рис. 5-22 мы видим развернутое изображение состояния Failure. В самый первый раз, когда наша система переходит в него, она принимает начальное состояние по умолчанию Create log (создать журнал); что обозначено непомеченным переходом из закрашенного кружка внутри объемлющего состояния; когда журнал (log) создан, система переходит в состояние Log ready. После того, как сообщение о сбое занесено в журнал, мы возвращаемся обратно. Когда мы попадем в состояние Failure в следующий раз, нам не нужно будет опять создавать журнал, и мы перейдем прямо к Log ready, так как когда мы в последний раз выходили из состояния Failure, система находилась именно в этом подсостоянии.
Рис. 5-22. История событий.
Действие "истории" распространяется только на тот уровень, на котором она указана. Если мы хотим распространить ее действие на все нижние подуровни, то мы обозначим это, пририсовав к ее значку звездочку.Можно получить промежуточный результат, пририсовав значок истории только к отдельным подсостояниям.
Дополнительный материал
В текст книги вплетен значительный дополнительный материал. В большинстве глав имеются специальные вставки (врезки), в которых содержится информация по отдельным важным темам, например, о механизмах вызова методов в различных объектно-ориентированных языках программирования. В книгу включено также приложение, посвященное объектно-ориентированным языкам, в котором рассматривается различие между объектными и объектно-ориентированными языками, их эволюция и свойства. Для тех читателей, которые незнакомы с конкретными языками программирования, мы подготовили сводку свойств нескольких основных языков с примерами кода. В книге имеется глоссарий (словарь основных терминов) и обширная тематическая библиография. Наконец, на последних страницах содержится сводка по объектно-ориентированному методу разработки и системе обозначений.
Помимо этой книги, можно порекомендовать "Сборник задач", содержащий упражнения, вопросы и проекты, которые должны оказаться полезными для семинарских занятий. "Сборник задач" ("Instructor's Guide with Exercises", ISBN 0-8053-5341-0) написан Мэри Бет Россон (Mary Beth Rosson) из лаборатории Томаса Дж. Ватсона (Thomas J. Watson) корпорации IBM. Преподаватели, желающие получить эту книгу, могут обращаться за бесплатным экземпляром непосредственно в издательство Addison-Wesley Longman (aw.cse@aw.com) или к местному представителю этого издательства. Вопросы и предложения для сборника задач можно направлять по адресу: rosson@watson.ibm.com.
Приобрести инструментальные средства и пройти обучение методу Буча (Booch) можно в разных местах. За дополнительной информацией обращайтесь в компанию Rational: booch-card@rational.com. Кроме того, Addison-Wesley Longman может предоставить учебным заведениям программные средства, поддерживающие нашу нотацию.
Как пользоваться этой книгой?
Книгу можно читать от корки до корки, но можно и по-другому. Если вы нуждаетесь в глубоком понимании объектной концепции и принципов объектно-ориентированного проектирования, начните с главы 1 и следуйте далее по порядку.
Если вам интересна в основном система обозначений и процесс объектно-ориентированного анализа и проектирования, начните с глав 5 и 6; менеджерам проектов, использующим этот метод, будет особенно интересна глава 7. Если вы интересуетесь практическим приложением объектно-ориентированной технологии к конкретной области, обратитесь к главам 8-12.
Благодарности
Книга посвящается моей жене в благодарность за ее любовь и поддержку.
На протяжении всей работы над первым и вторым изданиями много людей формировали мои взгляды на объектно-ориентированную разработку. Среди них были: Сэм Адаме (Sam Adams), Майк Акроид (Mike Akroid), Гленн Андерт (Glenn Andert), Сид Байлин (Sid Bailin), Кент Бек (Kent Beck), Даниел Бобров (Daniel Bobrow), Дик Больц (Dick Bolz), Дэйв Балман (Dave Bulman), Дэйв Бернстейн (Dave Bernstein), Кэйван Кэран (Kayvan Carun), Дэйв Коллинз (Dave Collins), Стив Кук (Steve Cook), Дамиан Конвэй (Damian Conway), Джим Коплиен (Jim Coplien), Брэд Кокс (Brad Сох), Ворд Канингэм (Ward Cunningham), Том ДеМар-ко (Torn DeMarco), МайкДелвин (Mike Delvin), Ричард Габриел (Richard Gabriel), Вильям Ценемерас (William Cenemeras), Адель Голдберг (Adele Goldberg), Ян Грэ-хем (lan Graham), Тони Хоар (Топу Ноаге), Джон Хопкинс (Jon Hopkins), Майкл Джэксон (Michael Jackson), Ральф Джонсон (Ralph Johnson), Джеймс Кемпф (James Kempf). Норм Керт (Norm Kerth), Иордан Крейндлер (Jordan Kreindler), Дуг Ли ( Doug Lea), Фил Леви (Phil Levy), Барбара Лисков ( Barbara Liskov), Клифф Лонгмэн (Cliff Longman), Джеймс МакФарлэйн (James MacFarlane), Масауд Милани (Masoud Milani), Арлан Миллс (Harlan Mills), Роберт Мюррей (Robert Murray), Стив Нейс (Steve Neis), Джин Уйе (Gene Ouye), Дэйв Парнас (Dave Parnas), Билл Риддел (Bill Riddel), Мэри Бет Россон (Mary Beth Rosson), Кенни Рубин (Кеппу Rubin), Джим Румбах (Jim Rumbaugh), Курт Шмукер (Kurt Schmucker), Эд Сейде-витц (Ed Seidewitz), Дэн Шифман (Dan Shiftman), Дэйв Стивенсон (Dave Stevenson), Бьерн Страуструп (Bjarne Stroustrup), Дэйв Томсон (Dave Thomson), Майк Вило (Mike Vilot), Тони Вассерман (Tony Wasserman), Питер Вегнер (Peter Wegner), Айсеал Байт (Iseult White), Джон Вильяме (John Williams), Ллойд Вильяме (Lloyd Williams), Марио Волчко (Mario Wolczko), Никлаус Вирт (Niklaus Wirth) и Эд Иордан (Ed Yourdon).
Практические главы этой книги формировались по мере моего участия в разработке сложных программных систем по всему миру для таких компаний как: Apple, Alcatel, Andersen Consulting, AT&T, Autotrol, Bell Northern Research, Boeing, Borland, Computer Sciences Corporation, Contel, Ericsson, Ferranti, General Electric, GTE, Holland Signaal, Hughes Aircraft Company, IBM, Lockheed, Martin Marietta, Motorola, NTT, Philips, Rockwell International, Shell Oil, Symantec, Taligent и TRW. Я общался с сотнями профессиональных программистов и менеджеров и благодарю их всех за то, что они помогли сделать эту книгу отвечающей проблемам реальной жизни.
Особая благодарность - компании Rational за поддержку моего труда. Спасибо также моему редактору Дэну Йоранстаду (Dan Joraanstad) за его постоянную поддержку и Тони Холлу (Tony Hall), рисунки которого внесли жизнь в то, что без них осталось бы еще одной скучной технической книгой. Наконец, спасибо трем моим кошкам, Кэми (Сату), Энни (Annie) и Тени (Shadow), составлявшим мне компанию в долгие часы ночной работы.
Генераторы приложений
При создании приложений типа системы складского учета необходимо произвести множество экранных форм и отчетов. Для больших систем эта работа не столько сложна, сколько велика по объему и однообразна. По этой причине сегодня весьма популярны генераторы приложений на основе языков четвертого поколения (4GL). Использование этих языков не противоречит идеям объектно-ориентированного проектирования. Напротив, 4GL-языки позволяют при правильном применении существенно упростить написание кода.
Языки четвертого поколения используются для генерации экранных форм и отчетов. На основании спецификаций они создают исполняемый код форм и отчетов. Мы интегрируем этот код в нашу систему, "оборачивая" его вручную тонким объектно-ориентированным слоем. Таким образом код, сгенерированный 4GL, становится частью структуры классов, которую остальные части приложения могут использовать, не обращая внимание на то, как она была создана.
Такой подход позволяет нам воспользоваться преимуществами 4GL, сохраняя иллюзию полностью объектно-ориентированной архитектуры. Кроме того, языки четвертого поколения сами подвергаются сильному влиянию технологии объект-но-ориентированного программирования и включают в себя прикладные интер-фейсы (API) для объектно-ориентированных языков типа C++.
Такую же стратегию можно использовать и при реализации диалога пользователя с системой. Написание программ для модального и немодального диалога скучно, поскольку мы должны охватить массу мелких деталей. Лучше не писать такой код вручную [Можно получать удовольствие и от самого процесса написания объектно-ориентированных программ, но гораздо важнее сосредоточиться на требованиях поставленной задачи. Это означает, что нужно избегать написания нового кода, где только возможно. Генераторы приложений и GUI-конструкторы очень способствуют этому. Среды разработки, которые мы описывали в главе 9, предоставляют еще один важный пример такого рода], а использовать GUI-конструкторы, позволяющие "рисовать окна диалога.
После получения готового кода мы заворачиваем его в объектную оболочку, включаем в наше приложение и получаем систему с четким разделением обязанностей.
10.4. Сопровождение
Системы клиент/сервер редко бывают окончательно завершенными. Не то чтоб мы никогда не могли сказать про систему, что она уже стабильна. Просто систем должна развиваться вместе с бизнесом, чтобы оставаться полезной.
Можно указать некоторые направления модернизации, которые вероятны для системы складского учета:
Предоставить возможность клиентам работать с системой по каналам связи.
Автоматически генерировать индивидуальные каталоги товаров для потребительских групп или даже отдельных клиентов.
Полностью автоматизировать все функции, устранив кладовщиков и большую часть работающих на приеме и отгрузке.
Анализ показывает, что все перечисленные модификации связаны скорее с со циалъным и политическим риском, чем с техническим. Гибкая объектно-ориентированная архитектура системы позволяет заказчику использовать все степени свободы, чтобы адаптироваться к постоянно меняющемуся рынку.
Дополнительная литература
Об архитектуре клиент/сервер написано больше, чем большинство смертных способно прочесть за всю жизнь. Две наиболее полезные ссылки - это Девайр (Dewire) [H 1992] и Берсон (Berson) [H 1992], которые предложили исчерпывающие и хорошо читаемые обзоры по всему спектру проблем технологии клиент/сервер. Блум (Bloom) [H 1993] дал короткое, но интересное перечисление базовых понятий и проблем архитектуры клиент/сервер.
Децентрализация - это не то же самое, что вычисления в архитектуре клиент/сервер, хотя она и предусматривает вычисления в архитектуре клиент/сервер в корпоративных информационно-управляющих системах. Все мотивировки за и против децентрализации можно найти в работе Гвенджерича (Guengerich) [H 1992].
Исчерпывающее обсуждение технологии реляционных баз данных можно найти у Дэйта (Date) [Е 1981,1983,1986]. Вдобавок к этому, Дэйт (Date) [E 1987] предложил описание стандарта SQL.
Разные подходы к анализу данных могут быть найдены у Вериярда (Veryard) [В 1984], Хавришкевича (Hawryszkiewycz) [Е 1984) и Росса (Ross) [F 1987).
Объектно-ориентированные базы данных представляют собой сплав обычной технологии баз данных и объектной модели. Отчеты о работе в этой области можно найти у Кэттла (Cattle) (Е 1991], Атвуда (Atwood) [Е 1991], Дэвиса и др. (Davis et al.) [H 1983], Кима и Лочовского (Kim and Lochovsky) [H 1989], Здоника и Майера (Zdonik and Maier) [E 1990].
В библиографии приведены несколько ссылок на различные оконные системы и объектно-ориентированные интерфейсы пользователя. Подробности о Microsoft Windows API можно найти в Windows [G 1992], а относительно Apple МасАрр - в Масарр [G 1992].
Характерные черты удачных проектов
Удачным проектом мы назовем тот, который удовлетворил (по возможности, превзошел) ожидания заказчика, уложился во временные и финансовые рамки, легко поддается изменению и адаптации. Пользуясь этим критерием, рассмотрим следующие две черты, которые оказались общими для всех встречавшихся нам удачных проектов, и, что замечательно, отсутствовали у тех, которые кажутся нам неудачными:
Ясное представление об архитектуре создаваемой системы;
Хорошо организованный итеративно развивающийся процесс работы над проектом.
Архитектура. Признак добротности архитектуры - ее концептуальное единство и целостность. По утверждению Брукса, "концептуальная целостность в проектировании важнее всего" [1]. Как показано в главах 1 и 5, архитектура объектно-ориентированной программной системы содержит структуры классов и объектов, имеющие горизонтальное и вертикальное слоение. Обычно конечному пользователю нет дела до архитектуры системы. Однако, как указывает Страуструп, "ясная внутренняя структура" играет важную роль в построении системы, которая будет понятна, тестируема, устойчива и сможет развиваться и перестраиваться [2]. Более того, именно ясность архитектуры дает возможность выявить общие абстракции и механизмы, которые можно свести воедино, тем самым делая систему проще, меньше и надежнее.
Не существует единственно верного способа классифицировать абстракции и разрабатывать архитектуру. В любой предметной области всегда достаточно глупейших путей проектирования, но, если поискать, можно найти и весьма элегантные. Как же отличить хорошую архитектуру от плохой?
Как правило, хорошая архитектура тяготеет к объектной ориентированности. Это не означает, что любая объектно-ориентированная архитектура оказывается хорошей, или что хороша только объектно-ориентированная архитектура. Однако, как было показано в главах 1 и 2, применение принципов объектно-ориентированной декомпозиции приводит к архитектуре, обладающей требуемыми свойствами организованной сложности.
Хорошей архитектуре присущи следующие свойства:
Она представляет собой многоуровневую систему абстракций. На каждом уровне абстракции сотрудничают друг с другом, имеют четкий интерфейс с внешним миром и основываются на столь же хорошо продуманных средствах нижнего уровня.
На каждом уровне интерфейс абстракции строго отграничен от реализации. Реализацию можно изменять, не затрагивая при этом интерфейс. Изменяясь внутренне, абстракции продолжают соответствовать ожиданиям внешних клиентов.
Архитектура проста, то есть не содержит ничего лишнего: общее поведение достигается общими абстракциями и механизмами.
Мы различаем стратегические и тактические решения. Стратегическое решение
имеет важное архитектурное значение и связано с высоким уровнем системы. Механизмы обнаружения и обработки ошибок, парадигмы интерфейса пользователя, политика управления памятью, устойчивость объектов, синхронизация процессов, работающих в реальном масштабе времени, - все это стратегические архитектурные решения. В противоположность этому, тактическое решение имеет только локальное архитектурное значение и поэтому обычно связано с деталями интерфейса и реализации абстракций. Протокол класса, сигнатура метода, выбор алгоритма - все это тактические архитектурные решения.
Хорошая архитектура всегда демонстрирует баланс между стратегическими и тактическими решениями. При слабой стратегии даже очень изящно задуманный класс не сможет вполне соответствовать своей роли. Самые прозорливые стратегические решения будут разрушены, если не уделить должного внимания разработке отдельных классов. В обоих случаях пренебрежение архитектурой рождает программные эквиваленты анархии и неразберихи.
Цикл итеративного развития. Рассмотрим две крайности - полное отсутствие формализованного жизненного цикла разработки и очень жесткие, строго соблюдаемые правила разработки. В первом случае мы имеем анархию; тяжким трудом (преимущественно нескольких своих членов) команда разработчиков в конце концов может родить что-то стоящее, но состояние проекта всегда будет неизмеримо и непредсказуемо.
Следует ожидать, что команда отработает весьма неэффективно, а, может быть, и вообще не создаст ничего пригодного для передачи заказчику. Это - пример проекта в свободном падении [Есть шанс, что проект в свободном падении приземлится благополучно, но вам не нужно ставить в связи с этим на кон будущее своей компании]. Во втором случае мы имеем диктатуру, в которой инициативы наказуемы, экспериментирование, которое могло бы привнести больше элегантности в архитектуру, не поощряется, и действительные требования заказчика никогда корректно не доходят до разработчиков нижнего уровня, скрытых за настоящей бумажной стеной, воздвигнутой бюрократией.
Встречавшиеся нам удачные объектно-ориентированные проекты не следовали ни анархическому, ни драконовскому жизненному циклу. Зато мы заметили, что удачная объектно-ориентированная архитектура создается в итеративно развивающемся процессе. Проектирование является итеративным, повторяющимся, в том смысле, что уже созданная архитектура вновь и вновь подвергается анализу и проектированию. При этом в каждом цикле анализ-проектирование-эволюция стратегические и тактические решения развиваются, приближаясь к требованиям конечного пользователя (часто даже не высказанным), оставаясь при этом простыми, надежными и открытыми для дальнейшего изменения.
Итеративно развивающийся процесс является антитезой традиционного "водопада" и не сводится к одностороннему движению сверху-вниз или снизу-вверх. Обнадеживающие прецеденты этого стиля есть в опыте создания как аппаратуры, так и программ [3, 4]. Например, пусть надо сформировать штат фирмы, занимающейся проектированием и изготовлением сложной уникальной аппаратуры. Можно использовать горизонтальный подход, когда проект катится водопадом, так, что архитекторы передают его конструкторам, а те электронщикам. Это - пример проектирования сверху-вниз, когда мы приглашаем узких (хотя и глубоких) специалистов в своей области [5]. Можно пойти по другому пути, наняв мастеров на все руки, каждому из которых можно поручить вертикальный сегмент проекта от начала до конца.
Это уже гораздо больше похоже на итеративно развивающийся процесс.
По нашему мнению, процесс объектно-ориентированного проектирования не сводится к одностороннему движению сверху-вниз или снизу-вверх. Друк считает, что хорошо структурированные сложные системы можно создать методом "возвратного проектирования" (round-trip gestalt design). В этом методе основное внимание уделяется процессу поступательного итеративного развития путем совершенствования различных, но, тем не менее, совместимых между собой логических и физических моделей системы. Мы считаем, что возвратное проектирование составляет необходимую основу процесса объектно-ориентированного проектирования.
В отдельных случаях решаемая задача может быть уже хорошо изучена и много раз запрограммирована. Процесс разработки можно привести в идеальный порядок: проектировщики новой системы уже понимают, какие абстракции являются главными; они уже знают, какие механизмы нужно использовать и каким, в общих чертах, будет поведение системы. Творчество все еще важно в таком процессе, но здесь проблема достаточно сужена и большинство стратегических решений предопределены. Тогда, поскольку риск исключен, можно достичь очень высоких показателей производительности [6]. Чем больше мы знаем о задаче, тем легче ее решить.
Большинство промышленных задач не таковы: они связаны с балансированием уникальных требований к функциональности и эффективности и требуют полной творческой отдачи всего коллектива разработчиков. Более того, любая человеческая деятельность, которая требует творчества и инноваций, идет путем проб и ошибок, итеративно развивающегося процесса, который опирается на опыт, компетентность и талант каждого члена коллектива [Эксперименты Кертиса и его коллег подкрепляют эти наблюдения. Они изучали работу профессиональных разработчиков программного обеспечения, записывая видеокамерой их действия и затем анализируя их содержание (анализ, проектирование, реализация и т.п.) и время на выполнение. В результате исследований был сделан вывод, что "создание программ представляется набором итеративных, плохо упорядоченных и взаимно перекрывающихся процессов под приспосабливающимся управлением...Развитие по сбалансированной схеме сверху-вниз проявляется как особый случай, когда схема проектирования оказалась вполне подходящей или задача мала по размеру... Хорошие проектировщики работают одновременно на нескольких уровнях абстракции и детализации" [8]]. Так что нет и не будет стандартных рецептов для проектирования программных систем.
Идентичность
Семантика. Хошафян и Коуплэнд предложили следующее определение:
"Идентичность - это такое свойство объекта, которое отличает его от всех других объектов" [12].
Они отмечают, что "в большинстве языков программирования и управления базами данных для различения временных объектов их именуют, тем самым путая адресуемость и идентичность. Большинство баз данных различают постоянные объекты по ключевому атрибуту, тем самым смешивая идентичность и значение данных". Источником множества ошибок в объектно-ориентированном программировании является неумение отличать имя объекта от самого объекта.
Примеры. Начнем с определения точки на плоскости.
struct Point { int x;
int y;
Point() : x(0), y(0) {}
Point(int xValue, int yValue) : x(xValue), y(yValue) {)
};
Мы определили point как структуру, а не как полноценный класс. Правило, на основании которого мы так поступили, очень просто. Если абстракция представляет собой собрание других объектов без какого-либо собственного поведения, мы делаем ее структурой. Однако, когда наша абстракция подразумевает более сложное поведение, чем простой доступ к полям структуры, то нужно определять класс. В данном случае абстракция point - это просто пара координат (x, y). Для удобства предусмотрено два конструктора: один инициализирует точку нулевыми значениями координат, а другой - некоторыми заданными значениями.
Теперь определим экранный объект (DisplayItem). Это абстракция довольно обычна для систем с графическим интерфейсом (GUI) - она является базовым классом для всех объектов, которые можно отображать в окне. Мы хотим сделать его чем-то большим, чем просто совокупностью точек. Надо, чтобы клиенты могли рисовать, выбирать объекты и перемещать их по экрану, а также запрашивать их положение и состояние. Мы записываем нашу абстракцию в виде следующего объявления на C++:
class DisplayItem {
public: DisplayItem();
DisplayItem(const Point& location);
virtual ~DisplayItem();
virtual void draw();
virtual void erase();
virtual void select();
virtual void unselect();
virtual void move(const Point& location);
int isSelected() const;
Point location() const;
int isUnder(const Point& location) const;
protected:
...
};
В этом объявлении мы намеренно опустили конструкторы, а также операторы для копирования, присваивания и проверки на равенство. Их мы оставим до следующего раздела.
Мы ожидаем, что у этого класса будет много наследников, поэтому деструктор и все модификаторы объявлены виртуальными. В особенности это относится к draw. Напротив, селекторы скорее всего не будут переопределяться в подклассах. Заметьте, что один из них, isUnder, должен вычислять, накрывает ли объект данную точку, а не просто возвращать значение какого-то свойства.
Объявим экземпляры указанных классов:
DisplayItem item1;
DisplayItem* item2 = new DisplayItem(Point(75, 75));
DisplayItem* item3 = new DisplayItem(Point(100, 100));
DisplayItem* item4 = 0;
Рис. 3-1а показывает, что при выполнении этих операторов возникают четыре имени и три разных объекта. Конкретно, в памяти будут отведены четыре места под имена item1, item2, item3, item4. При этом item1 будет именем объекта класса DisplayItem, а три других будут указателями. Кроме того, лишь item2 и item3 будут на самом деле указывать на объекты класса DisplayItem. У объектов, на которые указывают item2 и item3, к тому же нет имен, хотя на них можно ссылаться "разыменовывая" соответствующие указатели: например, *item2. Поэтому мы можем сказать, что item2 указывает на отдельный объект класса DisplayItem, на имя которого мы можем косвенно ссылаться через *item2. Уникальная идентичность (но не обязательно имя) каждого объекта сохраняется на все время его существования, даже если его внутреннее состояние изменилось. Эта ситуация напоминает парадокс Зенона о реке: может ли река быть той же самый, если в ней каждый день течет разная вода?
Рис. 3-1. Идентичность объектов.
Рассмотрим результат выполнения следующих операторов (рис. 3-1б):
item1.move(item2->location());
item4 = item3;
item4->move(Point(38, 100));
Объект item1 и объект, на который указывает item2, теперь относятся к одной и той же точке экрана. Указатель item4 стал указывать на тот же объект, что и item3. Кстати, заметьте разницу между выражениями "объект item2" и "объект, на который указывает item2". Второе выражение более точно, хотя для краткости мы часто будем использовать их как синонимы.
Хотя объект item1 и объект, на который указывает item2, имеют одинаковое состояние, они остаются разными объектами. Кроме того, мы изменили состояние объекта *item3, использовав его новое косвенное имя item4. Эта ситуация, которую мы называем структурной зависимостью, подразумевая под этим ситуацию, когда объект именуется более чем одним способом несколькими синонимичными именами. Структурная зависимость порождает в объектно-ориентированном программировании много проблем. Трудность распознания побочных эффектов при действиях с синонимичными объектами часто приводит к "утечкам памяти", неправильному доступу к памяти, и, хуже того, непрогнозируемому изменению состояния. Например, если мы уничтожим объект через указатель item3, то значение указателя item4 окажется бессмысленным; эта ситуация называется повисшей ссылкой. На рис. 3-1в иллюстрируется результат выполнения следующих действий:
item2 = &item1;
item4->move(item2->location());
В первой строке создается синоним: item2 указывает на тот же объект, что и item1. Во второй доступ к состоянию item1 получен через этот новый синоним. К сожалению, при этом произошла утечка памяти, - объект, на который первоначально указывала ссылка item2, никак не именуется ни прямо, ни косвенно, и его идентичность потеряна. В Smalltalk и CLOS память, отведенная под объекты, будет вновь возвращена системе сборщиком мусора. В языках типа C++ такая память не освобождается, пока не завершится программа, создавшая объект. Такие утечки памяти могут вызвать и просто неудобство, и крупные сбои, особенно, если программа должна непрерывно работать длительное время [Представьте себе утечку памяти в программе управления спутником или сердечным стимулятором.
Перезапуск компьютера на спутнике в нескольких миллионах километров от Земли очень неудобен. Аналогично, непредсказуемая сборка мусора в программе, управляющей стимулятором, может оказаться смертельным для пациента. В таких случаях разработчики систем реального времени предпочитают воздерживаться от динамического распределения памяти].
Копирование, присваивание и равенство. Структурная зависимость имеет место, когда объект имеет несколько имен. В наиболее интересных приложениях объектно-ориентированного подхода использование синонимов просто неизбежно. Например, рассмотрим следующие две функции:
void highLight(DisplayItem& i);
void drag(DisplayItem i); // Опасно
Если вызвать первую функцию с параметром item1, будет создан псевдоним: формальный параметр i означает указатель на фактический параметр, и следовательно item1 и i именуют один и тот же объект во время выполнения функции. При вызове второй функции с аргументом item1 ей передается новый объект, являющийся копией item1: i обозначает совершенно другой объект, хотя и с тем же состоянием, что и item1. В C++ различается передача параметров по ссылке и по значению. Надо следить за этим, иначе можно нечаянно изменить копию объекта, желая изменить сам объект [В Smalltalk семантика передачи объектов методам в качестве аргументов является по своему духу эквивалентом передачи параметра по ссылке в C++]. Как мы увидим в следующем разделе, передача объектов по ссылке в C++ необходима для программирования полиморфного поведения. В общем случае, передача объектов по ссылке крайне желательна для достаточно сложных объектов, поскольку при этом копируется ссылка, а не состояние, и следовательно, достигается большая эффективность (за исключением тех случаев, когда передаваемое значение очень простое).
В некоторых обстоятельствах, однако, подразумевается именно копирование. В языках типа C++ семантику копирования можно контролировать. В частности, мы можем ввести копирующий конструктор в определение класса, как в следующем фрагменте кода, который можно было бы включить в описание класса DisplayItem:
DisplayItem(const DisplayItem&);
В C++ копирующий конструктор может быть вызван явно (как часть описания объекта) или неявно (с передачей объекта по значению). Отсутствие этого специального конструктора вызывает копирующий конструктор, действующий по умолчанию, который копирует объект поэлементно. Однако, когда объект содержит ссылки или указатели на другие объекты, такая операция приводит к созданию синонимов указателей на объекты, что делает поэлементное копирование опасным. Мы предлагаем эмпирическое правило: разрешать неявное размножение путем копирования только для объектов, содержащих исключительно примитивные значения, и делать его явным для более сложных объектов.
Это правило поясняет то, что некоторые языки называют "поверхностным" и "глубоким" копированием. Чтобы копировать объект, в языке Smalltalk введены методы shallowCopy (метод копирует только объект, а состояние является разделяемым) и deepCopy (метод копирует объект и состояние, если нужно - рекурсивно). Переопределяя эти методы для классов с агрегацией, можно добиваться эффекта "глубокого" копирования для одних частей объекта, и "поверхностного" копирования остальных частей.
Присваивание - это, вообще говоря, копирование. В C++ его смысл тоже можно изменять. Например, мы могли бы добавить в определение класса DisplayItem следующую строку:
virtual DisplayItem& operator=(const DisplayItem&);
Этот оператор намеренно сделан виртуальным, так как ожидается, что подклассы будут его переопределять. Как и в случае копирующего конструктора, копирование можно сделать "глубоким" и "поверхностным". Если оператор присваивания не переопределен явно, то по умолчанию объект копируется поэлементно.
С вопросом присваивания тесно связан вопрос равенства. Хотя вопрос кажется простым, равенство можно понимать двумя способами. Во-первых, два имени могут обозначать один и тот же объект. Во-вторых, это может быть равенство состояний у двух разных объектов.
В примере на рис. 3- 1в оба варианта тождественности будут справедливы для item1 и item2. Однако для item2 и item3 истинным будет только второй вариант.
В C++ нет предопределенного оператора равенства, поэтому мы должны определить равенство и неравенство, объявив эти операторы при описании:
virtual int operator=(const DisplayItem&) const;
int operator!=(const DisplayItem&) const;
Мы предлагаем описывать оператор равенства как виртуальный (так как ожидаем, что подклассы могут переопределять его поведение), и описывать оператор неравенства как невиртуальный (так как хотим, чтобы он всегда был логическим отрицанием равенства: подклассам не следует переопределять это).
Аналогичным образом мы можем создавать операторы сравнения объектов типа >= и <=.
Время жизни объектов. Началом времени существования любого объекта является момент его создания (отведение участка памяти), а окончанием - возвращение отведенного участка памяти системе.
Объекты создаются явно или неявно. Есть два способа создать их явно. Во-первых, это можно сделать при объявлении (как это было с item1): тогда объект размещается в стеке. Во-вторых, как в случае item3, можно разместить объект, то есть выделить ему память из "кучи". В C++ в любом случае при этом вызывается конструктор, который выделяет известное ему количество правильно инициализированной памяти под объект. В Smalltalk этим занимаются метаклассы, о семантике которых мы поговорим позже.
Часто объекты создаются неявно. Так, передача параметра по значению в C++ создает в стеке временную копию объекта. Более того, создание объектов транзитивно: создание объекта тянет за собой создание других объектов, входящих в него. Переопределение семантики копирующего конструктора и оператора присваивания в C++ разрешает явное управление тем, когда части объекта создаются и уничтожаются. К тому же в C++ можно переопределять и оператор new, тем самым изменяя политику управления памятью в "куче" для отдельных классов.
В Smalltalk и некоторых других языках при потере последней ссылки на объект его забирает сборщик мусора. В языках без сборки мусора, типа C++, объекты, созданные в стеке, уничтожаются при выходе из блока, в котором они были определены, но объекты, созданные в "куче" оператором new, продолжают существовать и занимать место в памяти: их необходимо явно уничтожать оператором delete. Если объект "забыть", не уничтожить, это вызовет, как уже было сказано выше, утечку памяти. Если же объект попробуют уничтожить повторно (например, через другой указатель), последствием будет сообщение о нарушении памяти или полный крах системы.
При явном или неявном уничтожении объекта в C++ вызывается соответствующий деструктор. Его задача не только освободить память, но и решить, что делать с другими ресурсами, например, с открытыми файлами [Деструкторы не освобождают автоматически память, размещенную оператором new, программисты должны явно освободить ее].
Уничтожение долгоживущих объектов имеет несколько другую семантику. Как говорилось в предыдущей главе, некоторые объекты могут быть долгоживущими; под этим понимается, что их время жизни может выходить за время жизни породивших их программ. Обычно такие объекты являются частью некой долговременной объектной структуры, поэтому вопросы их жизни и смерти относятся скорее к политике соответствующей объектно-ориентированной базы данных. В таких системах для обеспечения долгой жизни наиболее принят подход на основе постоянных "подмешиваемых классов". Все объекты, которым мы хотим обеспечить долгую жизнь, должны наследовать от этих классов.
3.2. Отношения между объектами
Иерархия
Что такое иерархия? Абстракция - вещь полезная, но всегда, кроме самых простых ситуаций, число абстракций в системе намного превышает наши умственные возможности. Инкапсуляция позволяет в какой-то степени устранить это препятствие, убрав из поля зрения внутреннее содержание абстракций. Модульность также упрощает задачу, объединяя логически связанные абстракции в группы. Но этого оказывается недостаточно.
Значительное упрощение в понимании сложных задач достигается за счет образования из абстракций иерархической структуры. Определим иерархию следующим образом:
Иерархия - это упорядочение абстракций, расположение их по уровням.
Основными видами иерархических структур применительно к сложным системам являются структура классов (иерархия "is-a") и структура объектов (иерархия "part of").
Примеры иерархии: одиночное наследование. Важным элементом объектно-ориентированных систем и основным видом иерархии "is-a" является упоминавшаяся выше концепция наследования. Наследование означает такое отношение между классами (отношение родитель/потомок), когда один класс заимствует структурную или функциональную часть одного или нескольких других классов (соответственно, одиночное и множественное наследование). Иными словами, наследование создает такую иерархию абстракций, в которой подклассы наследуют строение от одного или нескольких суперклассов. Часто подкласс достраивает или переписывает компоненты вышестоящего класса.
Семантически, наследование описывает отношение типа "is-a". Например, медведь есть млекопитающее, дом есть недвижимость и "быстрая сортировка" есть сортирующий алгоритм. Таким образом, наследование порождает иерархию "обобщение-специализация", в которой подкласс представляет собой специализированный частный случай своего суперкласса. "Лакмусовая бумажка" наследования - обратная проверка; так, если B не есть A, то B не стоит производить от A.
Рассмотрим теперь различные виды растений, выращиваемых в нашей огородной системе.
Мы уже ввели обобщенное представление абстрактного плана выращивания растений. Однако разные культуры требуют разных планов. При этом планы для фруктов похожи друг на друга, но отличаются от планов для овощей или цветов. Имеет смысл ввести на новом уровне абстракции обобщенный "фруктовый" план, включающий указания по опылению и сборке урожая. Вот как будет выглядеть на C++ определение плана для фруктов, как наследника общего плана выращивания.
// Тип Урожай
typedef unsigned int Yield;
class FruitGrowingPlan : public GrowingPlan {
public: FruitGrowingPlan(char* name);
virtual ~FruitGrowingPlan();
virtual void establish(Day, Hour, Condition&);
void scheduleHarvest(Day, Hour);
Boolean isHarvested() const;
unsigned daysUntilHarvest() const;
Yield estimatedYield() const;
protected: Boolean repHarvested;
Yield repYield;
Абстракции образуют иерархию.
Это означает, что план выращивания фруктов FruitGrowingPlan является разновидностью плана выращивания GrowingPlan. В него добавлены параметры repHarvested и repYield, определены четыре новые функции и переопределена функция establish. Теперь мы могли бы продолжить специализацию - например, определить на базе "фруктового" плана "яблочный" класс AppleGrowingPlan.
В наследственной иерархии общая часть структуры и поведения сосредоточена в наиболее общем суперклассе. По этой причине говорят о наследовании, как об иерархии обобщение-специализация. Суперклассы при этом отражают наиболее общие, а подклассы - более специализированные абстракции, в которых члены суперкласса могут быть дополнены, модифицированы и даже скрыты. Принцип наследования позволяет упростить выражение абстракций, делает проект менее громоздким и более выразительным. Кокс пишет: "В отсутствие наследования каждый класс становится самостоятельным блоком и должен разрабатываться "с нуля". Классы лишаются общности, поскольку каждый программист реализует их по-своему. Стройность системы достигается тогда только за счет дисциплинированности программистов.
Наследование позволяет вводить в обращение новые программы, как мы обучаем новичков новым понятиям - сравнивая новое с чем-то уже известным" [64].
Принципы абстрагирования, инкапсуляции и иерархии находятся между собой в некоем здоровом конфликте. Данфорт и Томлинсон утверждают: "Абстрагирование данных создает непрозрачный барьер, скрывающий состояние и функции объекта; принцип наследования требует открыть доступ и к состоянию, и к функциям объекта для производных объектов" [65]. Для любого класса обычно существуют два вида клиентов: объекты, которые манипулируют с экземплярами данного класса, и подклассы-наследники. Лисков поэтому отмечает, что существуют три способа нарушения инкапсуляции через наследование: "подкласс может получить доступ к переменным экземпляра своего суперкласса, вызвать закрытую функцию и, наконец, обратиться напрямую к суперклассу своего суперкласса" [66]. Различные языки программирования по-разному находят компромисс между наследованием и инкапсуляцией; наиболее гибким в этом отношении является C++. В нем интерфейс класса может быть разделен на три части: закрытую (private), видимую только для самого класса; защищенную (protected), видимую также и для подклассов; и открытую (public), видимую для всех.
Примеры иерархии: множественное наследование. В предыдущем примере рассматривалось одиночное наследование, когда подкласс FruitGrowingPlan был создан только из одного суперкласса GrowingPlan. В ряде случаев полезно реализовать наследование от нескольких суперклассов. Предположим, что нужно определить класс, представляющий разновидности растений.
class Plant {
public: Plant(char* name, char* species);
virtual ~Plant();
void setDatePlanted(Day);
virtual establishGrowingConditions(const Condition&);
const char* name() const;
const char* species() const;
Day datePlantedt) const;
protected: char* repName;
char* repSpecies;
Day repPlanted;
private:
...
};
Каждый экземпляр класса plant будет содержать имя, вид и дату посадки.
Кроме того, для каждого вида растений можно задавать особые оптимальные условия выращивания. Мы хотим, чтобы эта функция переопределялась подклассами, поэтому она объявлена виртуальной при реализации в C++. Три параметра объявлены как защищенные, то есть они будут доступны и классу, и подклассам (закрытая часть спецификации доступна только самому классу).
Изучая предметную область, мы приходим к выводу, что различные группы культивируемых растений - цветы, фрукты и овощи, - имеют свои особые свойства, существенные для технологии их выращивания. Например, для цветов важно знать времена цветения и созревания семян. Аналогично, время сбора урожая важно для абстракций фруктов и овощей. Создадим два новых класса - цветы (Flower) и фрукты-овощи (FruitVegetable); они оба наследуют от класса Plant. Однако некоторые цветочные растения имеют плоды! Для этой абстракции придется создать третий класс, FlowerFruitVegetable, который будет наследовать от классов Flower и FruitVegetablePlant.
Чтобы не было избыточности, в данном случае очень пригодится множественное наследование. Сначала давайте опишем отдельно цветы и фрукты-овощи.
class FlowerMixin {
public: FlowerMixin(Day timeToFlower, Day timeToSeed);
virtual ~FlowerMixin();
Day timeToFlower() const;
Day timeToSeed() const;
protected:
...
};
class FruitVegetableMixin {
public: FruitVegetableMixin(Day timeToHarvest);
virtual ~FruitVegetableMixin();
Day timeToHarvest() const;
protected:
...
};
Мы намеренно описали эти два класса без наследования. Они ни от кого не наследуют и специально предназначены для того, чтобы их подмешивали (откуда и имя Mixin) к другим классам. Например, опишем розу:
class Rose : public Plant, public FlowerMixin...
А вот морковь:
class Carrot : public Plant, public FruiteVegetableMixin {};
В обоих случаях классы наследуют от двух суперклассов: экземпляры подкласса Rose включают структуру и поведение как из класса Plant, так и из класса FlowerMixin. И вот теперь определим вишню, у которой товаром являются как цветы, так и плоды:
class Cherry : public Plant, public FlowerMixin, FruitVegetableMixin...
Множественное наследование - вещь нехитрая, но оно осложняет реализацию языков программирования. Есть две проблемы - конфликты имен между различными суперклассами и повторное наследование. Первый случай, это когда в двух или большем числе суперклассов определено поле или операция с одинаковым именем. В C++ этот вид конфликта должен быть явно разрешен вручную, а в Smalltalk берется то, которое встречается первым. Повторное наследование, это когда класс наследует двум классам, а они порознь наследуют одному и тому же четвертому. Получается ромбическая структура наследования и надо решить, должен ли самый нижний класс получить одну или две отдельные копии самого верхнего класса? В некоторых языках повторное наследование запрещено, в других конфликт решается "волевым порядком", а в C++ это оставляется на усмотрение программиста. Виртуальные базовые классы используются для запрещения дублирования повторяющихся структур, в противном случае в подклассе появятся копии полей и функций и потребуется явное указание происхождения каждой из копий.
Множественным наследованием часто злоупотребляют. Например, сладкая вата - это частный случай сладости, но никак не ваты. Применяйте ту же "лакмусовую бумажку": если B не есть A, то ему не стоит наследовать от A. Часто плохо сформированные структуры множественного наследования могут быть сведены к единственному суперклассу плюс агрегация других классов подклассом.
Примеры иерархии: агрегация. Если иерархия "is а" определяет отношение "обобщение/специализация", то отношение "part of" (часть) вводит иерархию агрегации. Вот пример.
class Garden {
public: Garden();
virtual ~Garden();
protected: Plant* repPlants[100];
GrowingPlan repPlan;
};
Это - абстракция огорода, состоящая из массива растений и плана выращивания.
Имея дело с такими иерархиями, мы часто говорим об уровнях абстракции, которые впервые предложил Дейкстра [67].
В иерархии классов вышестоящая абстракция является обобщением, а нижестоящая - специализацией. Поэтому мы говорим, что класс Flower находится на более высоком уровне абстракции, чем класс Plant. В иерархии "part of" класс находится на более высоком уровне абстракции, чем любой из использовавшихся при его реализации. Так класс Garden стоит на более высоком уровне, чем класс Plant.
Агрегация есть во всех языках, использующих структуры или записи, состоящие из разнотипных данных. Но в объектно-ориентированном программировании она обретает новую мощь: агрегация позволяет физически сгруппировать логически связанные структуры, а наследование с легкостью копирует эти общие группы в различные абстракции.
В связи с агрегацией возникает проблема владения, или принадлежности объектов. В нашем абстрактном огороде одновременно растет много растений, и от удаления или замены одного из них огород не становится другим огородом. Если мы уничтожаем огород, растения остаются (их ведь можно пересадить). Другими словами, огород и растения имеют свои отдельные и независимые сроки жизни; мы достигли этого благодаря тому, что огород содержит не сами объекты Plant, а указатели на них. Напротив, мы решили, что объект GrowingPlan внутренне связан с объектом Garden и не существует независимо. План выращивания физически содержится в каждом экземпляре огорода и погибает вместе с ним. Подробнее про семантику владения мы будем говорить в следующей главе.
Инкапсуляция
Что это значит? Хотя мы описывали нашу абстракцию GrowingPlan как сопоставление действий моментам времени, она не обязательно должна быть реализована буквально как таблица данных. Действительно, клиенту нет никакого дела до реализации класса, который его обслуживает, до тех пор, пока тот соблюдает свои обязательства. На самом деле, абстракция объекта всегда предшествует его реализации. А после того, как решение о реализации принято, оно должно трактоваться как секрет абстракции, скрытый от большинства клиентов. Как мудро замечает Ингалс: "Никакая часть сложной системы не должна зависеть от внутреннего устройства какой-либо другой части" [50]. В то время, как абстракция "помогает людям думать о том, что они делают", инкапсуляция "позволяет легко перестраивать программы" [51].
Абстракция и инкапсуляция дополняют друг друга: абстрагирование направлено на наблюдаемое поведение объекта, а инкапсуляция занимается внутренним устройством. Чаще всего инкапсуляция выполняется посредством скрытия информации, то есть маскировкой всех внутренних деталей, не влияющих на внешнее поведение. Обычно скрываются и внутренняя структура объекта и реализация его методов.
Инкапсуляция, таким образом, определяет четкие границы между различными абстракциями. Возьмем для примера структуру растения: чтобы понять на верхнем уровне действие фотосинтеза, вполне допустимо игнорировать такие подробности, как функции корней растения или химию клеточных стенок. Аналогичным образом при проектировании базы данных принято писать программы так, чтобы они не зависели от физического представления данных; вместо этого сосредотачиваются на схеме, отражающей логическое строение данных [52]. В обоих случаях объекты защищены от деталей реализации объектов более низкого уровня.
Дисков прямо утверждает, что "абстракция будет работать только вместе с инкапсуляцией" [53]. Практически это означает наличие двух частей в классе: интерфейса и реализации. Интерфейс отражает внешнее поведение объекта, описывая абстракцию поведения всех объектов данного класса.
Внутренняя реализация описывает представление этой абстракции и механизмы достижения желаемого поведения объекта. Принцип разделения интерфейса и реализации соответствует сути вещей: в интерфейсной части собрано все, что касается взаимодействия данного объекта с любыми другими объектами; реализация скрывает от других объектов все детали, не имеющие отношения к процессу взаимодействия объектов. Бритон и Парнас назвали такие детали "тайнами абстракции" [54].
Инкапсуляция скрывает детали реализации объекта.
Итак, инкапсуляцию можно определить следующим образом:
Инкапсуляция - это процесс отделения друг от друга элементов объекта, определяющих его устройство и поведение; инкапсуляция служит для того, чтобы изолировать контрактные обязательства абстракции от их реализации.
Примеры инкапсуляции. Вернемся к примеру гидропонного тепличного хозяйства. Еще одной из ключевых абстракций данной предметной области является нагреватель, поддерживающий заданную температуру в помещении. Нагреватель является абстракцией низкого уровня, поэтому можно ограничиться всего тремя действиями с этим объектом: включение, выключение и запрос состояния. Нагреватель не должен отвечать за поддержание температуры, это будет поведением более высокого уровня, совместно реализуемым нагревателем, датчиком температуры и еще одним объектом. Мы говорим о поведении более высокого уровня, потому что оно основывается на простом поведении нагревателя и датчика, добавляя к ним кое-что еще, а именно гистерезис (или запаздывание), благодаря которому можно обойтись без частых включений и выключении нагревателя в состояниях, близких к граничным. Приняв такое решение о разделении ответственности, мы делаем каждую абстракцию более цельной.
Как всегда, начнем с типов.
// Булевский тип
enum Boolean {FALSE, TRUE};
В дополнение к трем предложенным выше операциям, нужны обычные мета-операции создания и уничтожения объекта (конструктор и деструктор). Поскольку в системе может быть несколько нагревателей, мы будем при создании каждого из них сообщать ему место, где он установлен, как мы делали это с классом датчиков температуры TemperatureSensor.
Итак, вот класс Heater для абстрактных нагревателей, написанный на C++:
class Heater {
public: Heater(Location);
~Heater();
void turnOn();
void tum0ff();
Boolean is0n() const;
private:
};
Вот и все, что посторонним надо знать о классе Heater. Внутренность класса это совсем другое дело. Предположим, проектировщики аппаратуры решили разместить управляющие компьютеры вне теплицы (где слишком жарко и влажно), и соединить их с датчиками и исполнительными устройствами с помощью последовательных интерфейсов. Разумно ожидать, что нагреватели будут коммутироваться с помощью блока реле, а оно будет управляться командами, поступающими через последовательный интерфейс. Скажем, для включения нагревателя передается текстовое имя команды, номер места нагревателя и еще одно число, используемое как сигнал включения нагревателя.
Вот класс, выражающий абстрактный последовательный порт.
class SerialPort {
public: SerialPort();
~SerialPort();
void write(char*);
void write(int);
static SerialPort ports[10];
private:
};
Экземпляры этого класса будут настоящими последовательными портами, в которые можно выводить строки и числа.
Добавим еще три параметра в класс Heater.
class Heater {
public:
...
protected: const Location repLocation;
Boolean repIsOn;
SerialPort* repPort;
};
Эти параметры repLocation, repIsOn, repPort образуют его инкапсулированное состояние. Правила C++ таковы, что при компиляции программы, если клиент попытается обратиться к этим параметрам напрямую, будет выдано сообщение об ошибке.
Определим теперь реализации всех операций этого класса.
Heater::Heater(Location 1) : repLocation(1),
repIsOn(FALSE),
repPort(&SerialPort::ports[l]) {}
Heater::Heater() {}
void Heater::turnOn()
{ if (!repls0n) {
repPort->write("*");
repPort->write(repLocation);
repPort->write(1);
repIsOn = TRUE;
}
}
void Heater::turn0ff()
{ if (repIsOn) {
repPort->write("*");
repPort->write(repLocation);
repPort->write(0);
repIsOn = FALSE;
}
}
Boolean Heater::is0n() const
{ return repIsOn;
}
Такой стиль реализации типичен для хорошо структурированных объектно-ориентированных систем: классы записываются экономно, поскольку их специализация осуществляется через подклассы.
Предположим, что по какой-либо причине изменилась архитектура аппаратных средств системы и вместо последовательного порта управление должно осуществляться через фиксированную область памяти. Нет необходимости изменять интерфейсную часть класса - достаточно переписать реализацию. Согласно правилам C++, после этого придется перекомпилировать измененный класс, но не другие объекты, если только они не зависят от временных и пространственных характеристик прежнего кода (что крайне нежелательно и совершенно не нужно).
Обратимся теперь к реализации класса GrowingPlan. Как было сказано, это, в сущности, временной график действий. Вероятно, лучшей реализацией его был бы словарь пар время-действие с открытой хеш-таблицей. Нет смысла запоминать действия час за часом, они происходят не так часто, а в промежутках между ними система может интерполировать ход процесса.
Инкапсуляция скроет от посторонних взглядов два секрета: то, что в действительности график использует открытую хеш-таблицу, и то, что промежуточные значения интерполируются. Клиенты вольны думать, что они получают данные из почасового массива значений параметров.
Разумная инкапсуляция локализует те особенности проекта, которые могут подвергнуться изменениям. По мере развития системы разработчики могут решить, что какие-то операции выполняются несколько дольше, чем допустимо, а какие-то объекты занимают больше памяти, чем приемлемо. В таких ситуациях часто изменяют внутреннее представление объекта, чтобы реализовать более эффективные алгоритмы или оптимизировать алгоритм по критерию памяти, заменяя хранение данных вычислением. Важным преимуществом ограничения доступа является возможность внесения изменений в объект без изменения других объектов.
В идеальном случае попытки обращения к данным, закрытым для доступа, должны выявляться во время компиляции программы.
Вопрос реализации этих условий для конкретных языков программирования является предметом постоянных обсуждений. Так, Smalltalk обеспечивает защиту от прямого доступа к экземплярам другого класса, обнаруживая такие попытки во время компиляции. В тоже время Object Pascal не инкапсулирует представление класса, так что ничто в этом языке не предохраняет клиента от прямых ссылок на внутренние поля другого объекта. Язык CLOS занимает в этом вопросе промежуточную позицию, возлагая все обязанности по ограничению доступа на программиста. В этом языке все слоты могут сопровождаться атрибутами :reader, :writer и :accessor, разрешающими соответственно чтение, запись или полный доступ к данным (то есть и чтение, и запись). При отсутствии атрибутов слот полностью инкапсулирован. По соглашению, признание того, что некоторая величина хранится в слоте, рассматривается как нарушение абстракции, так что хороший стиль программирования на CLOS требует, чтобы при публикации интерфейса класса, документировались бы только имена его функций, а тот факт, что слот имеет функции полного доступа, должен скрываться [55]. В языке C++ управление доступом и видимостью более гибко. Члены класса могут быть отнесены к открытой, закрытой или защищенной частям. Открытая часть доступна для всех объектов; закрытая часть полностью закрыта для других объектов; защищенная часть видна только экземплярам данного класса и его подклассов. Кроме того, в C++ существует понятие "друзей" (friends), для которых открыта закрытая часть.
Скрытие информации - понятие относительное: то, что спрятано на одном уровне абстракции, обнаруживается на другом уровне. Забраться внутрь объектов можно; правда, обычно требуется, чтобы разработчик класса-сервера об этом специально позаботился, а разработчики классов-клиентов не поленились в этом разобраться. Инкапсуляция не спасает от глупости; она, как отметил Страуструп, "защищает от ошибок, но не от жульничества" [56]. Разумеется, язык программирования тут вообще ни при чем; разве что операционная система может ограничить доступ к файлам, в которых описаны реализации классов.На практике же иногда просто необходимо ознакомиться с реализацией класса, чтобы понять его назначение, особенно, если нет внешней документации.
Инстанцирование
Примеры. Наша первая попытка сконструировать класс Queue (очередь) была не особенно успешной, поскольку нам не удалось сделать его безопасным в отношении типов. Мы можем значительно усовершенствовать нашу абстракцию, если прибегнем к конструкции параметризованных классов, которая поддерживается языками C++ и Eiffel.
Template<class Item>
class Queue {
public:
Queue();
Queue(const Queue<Item>&);
virtual ~Queue();
virtual Queue<Item>& operator=(const Queue<Item>&);
virtual int operator==(const Queue<Item>&) const;
int operator!=(const Queue<Item>&) const;
virtual void clear();
virtual void append(const Item&);
virtual void pop();
virtual void remove(int at);
virtual int length() const;
virtual int isEmpty() const;
virtual const Item& front() const;
virtual int location(const void*);
protected:
...
};
В этом новом варианте не используется идиома void*, вместо этого объекты помещаются в очередь и достаются из нее через класс item, объявленный как аргумент шаблона.
Параметризованный класс не может иметь экземпляров, пока он не будет инстанцирован. Объявим две конкретных очереди - очередь целых чисел и очередь экранных объектов:
Queue<int> intQueue;
Queue<DisplayItem*> itemQueue;
Объекты intQueue и itemQueue - это экземпляры совершенно различных классов, которые даже не имеют общего суперкласса. Тем не менее, они получены из одного параметризованного класса Queue. По причинам, которые мы объясним позже в главе 9, во втором случае мы поместили в очередь указатели. Благодаря этому, любые объекты подклассов DisplayItem, помещенные в очередь, не будут "срезаться", но сохранят свое полиморфное поведение.
Рис. 3-10. Инстанцирование.
Это инстанцирование безопасно с точки зрения типов. По правилам C++ будет отвергнута любая попытка поместить в очередь или извлечь из нее что-либо кроме, соответственно, целых чисел и разновидностей DisplayItem.
Отношения между параметризованным классом Queue, его инстанцированием для класса DisplayItem и экземпляром itemQueue показаны на рис. 3-10.
Обобщенные классы. Существует четыре основных способа создавать такие классы, как параметризованный класс Queue. Во-первых, мы можем использовать макроопределения. Именно так это было в раннем C++, но, как пишет Страуструп, "данный подход годился только для небольших проектов" [45], так как макросы неуклюжи и находятся вне семантики языка, более того, при каждом инстанцировании создается новая копия программного кода. Во-вторых, можно положиться на позднее связывание и наследование, как это делается в Smalltalk [46]. При таком подходе мы можем строить только неоднородные контейнерные классы, так как в языке нет средства ввести нужный класс элементов контейнера; каждый элемент в контейнере трактуется как экземпляр некоторого удаленного базового класса. Третий способ реализован в языках семейства Object Pascal, которые имеют и сильные типы, и наследование, но не поддерживают никакой разновидности параметризованных классов. В этом случае приходится создавать обобщенные контейнеры, как в Smalltalk, но использовать явную проверку типа объекта, прежде чем помещать его в контейнер. Наконец, есть собственно параметризованные классы, впервые появившиеся в CLU. Параметризованный класс представляет собой что-то вроде шаблона для построения других классов; шаблон может быть параметризован другими классами, объектами или операциями. Параметризованный класс должен быть инстанцирован перед созданием экземпляров. Механизм обобщенных классов есть в C++ и Eiffel.
Как можно заметить из рис. 3-10, чтобы инстанцировать параметризованный класс Queue мы должны использовать другой класс, например, DisplayItem. Благодаря этому отношение инстанцирования почти всегда подразумевает отношение использования.
Мейер указывает, что наследование - более мощный механизм, чем обобщенные классы и что через наследование можно получить большинство преимуществ обобщенных классов, но не наоборот [47]. Нам кажется, что лучше, когда языки поддерживают и то, и другое.
Параметризованные классы полезны далеко не только для создания контейнеров.Например, Страуструп отмечает их значение для обобщенной арифметики [48].
При проектировании обобщенные классы позволяют выразить некоторые свойства протоколов классов. Класс экспортирует операции, которые можно выполнять над его экземплярами. Наоборот, параметризующий аргумент класса служит для импорта классов и значений, предоставляющих некоторый протокол. C++ проверяет их взаимное соответствие при компиляции, когда фактически и происходит инстанцирование. Например, мы могли бы определить упорядоченную очередь объектов, отсортированных по некоторому критерию. Этот параметризованный класс должен иметь аргумент (класс Item), и требовать от этого аргумента определенное поведение (наличие операции вычисления порядка). При инстанцировании в качестве класса Item годится любой класс, который имеет соответствующий протокол. Таким образом, поведение классов в семействе, происходящем от одного параметризованного класса, может изменяться в весьма широких пределах.
Инструменты
Для нашей библиотеки основная роль шаблонов заключается в параметризации структур типами элементов, которые будут в них содержаться; поэтому такие структуры называют классами-контейнерами. Но, как видно из определения класса Table, шаблоны можно использовать также для передачи классу некоторой информации о реализации.
Еще более сложная ситуация возникает при создании инструментов, которые оперируют с другими структурами. Как уже отмечалось, алгоритмы тоже можно представить в виде классов, объекты которых будут выступать в роли агентов, ответственных за выполнение алгоритма. Такой подход соответствует идее Джекобсона об объекте управления, который служит связующим звеном, осуществляющим взаимодействие обычных объектов [16]. Преимущество данного подхода состоит в возможности создания семейств алгоритмов, объединенных наследованием. Это не только упрощает их использование, но также позволяет объединить концептуально схожие алгоритмы.
Рассмотрим в качестве примера алгоритмы поиска образца внутри последовательности. Существует целый ряд подобных алгоритмов:
У всех этих алгоритмов существуют по крайней мере три общие черты: все они проводят операции над последовательностями (и значит работают с объектами, имеющими схожий протокол), требуют существования операции сравнения для того типа элементов, среди которых ведется поиск (стандартный оператор сравнения может оказаться недостаточным), и имеют одинаковую сигнатуру вызова (целевую строку, образец поиска и индекс элемента, с которого начнется поиск).
Об операции сравнения нужно поговорить особо. Предположим, например, что существует упорядоченный список сотрудников фирмы. Мы хотим произвести в нем поиск по определенному критерию, скажем, найти группы из трех записей с сотрудниками, работающими в одном и том же отделе. Использование оператора operator==, определенного для класса PersonnelRecord, не даст нужного результата, так как этот оператор, скорее всего, производит проверку в соответствии с другим критерием, например, табельным номером сотрудника. Поэтому нам придется специально разработать для этой цели новый оператор сравнения, который запрашивал бы (вызовом соответствующего селектора) название отдела, в котором работает сотрудник. Поскольку каждый агент, выполняющий поиск по образцу, требует своей функции проверки на равенство, мы можем разработать общий протокол введения такой функции в качестве части некоторого абстрактного базового класса. Рассмотрим в качестве примера следующее объявление:
template<class Item, class Sequence>
class PatternMatch {
public: PatternMatch();
PatternMatch(int (*isEqual)(const Item& x, const Item& y));
virtual ~PatternMatch();
virtual void setIsEqualFunction(int (*)(const Item& x, const Item& y));
virtual int match(const Sequence& target, const Sequences; pattern, unsigned int start = 0) = 0;
virtual int match(const Sequence&; target, unsigned int start = 0) = 0;
protected: Sequence rep;
int (*isEqual)(const Item& x, const Item& y);
private: void operator=(coust PattemMatcb&) {}
void operator==(const PatternMatch&) {}
void operator!=(const PatternMatch&) {}
};
Операции присваивания и сравнения на равенство для объектов данного класса и его подклассов невозможны, поскольку мы использовали соответствующие идиомы. Мы сделали это, потому что операции присваивания и сравнения не имеют смысла для абстракций агентов.
Теперь опишем конкретный подкласс, определяющий алгоритм Бойера-Мура:
template<class Item, class Sequence>
class BMPatternMatch : public PatternMatch<Item, Sequence>
{
public: BMPatternMatch();
BMPattemMatch(int (*isEqual) (const Item& x, const Item& y));
virtual ~BMPattemMatch();
virtual int match(const Sequence& target, const Seque unsigned int start = 0);
virtual int match(const Sequence& target, unsigned in
protected: unsigned int length;
unsigned int* skipTable;
void preprogress(const Sequence& pattern);
unsigned int itemsSkip(const Sequence& pattern, const Item& item);
};
Рис. 9-13. Классы поиска.
Открытый протокол этого класса полностью копирует соответствующий протокол своего суперкласса. Кроме того, его описание дополнительно включает два элемента данных и две вспомогательные функции. Одна из особенностей данного класса состоит в создании временной таблицы, которая используется для пропуска длинных неподходящих последовательностей. Эти добавочные элементы нужны для реализации алгоритма.
На рис. 9-13 приведена иерархия классов поиска. Иерархия подобного типа применима для большинства инструментов библиотеки. При этом формируются сходные по структуре семейства классов, что позволяет пользователям легко в них ориентироваться и выбирать те, которые наилучшим образом подходят для их приложений.
9.4. Сопровождение
Одно из наиболее интересных свойств сред разработки заключается в том, что, в случае удачной реализации, они стремятся набрать некую критическую массу функциональности и адаптируемости. Другими словами, если мы правильно выбрали основные абстракции и наделили библиотеку рядом хорошо взаимодействующих между собой механизмов, то вскоре обнаружим, что клиенты используют наш продукт для решения тех задач, о которых разработчики среды и не подозревали. После того, как определились основные схемы использования среды, имеет смысл сделать их формальной частью самой библиотеки. Признаком правильности конструкции среды разработки является возможность внедрения новых моделей поведения с помощью повторного использования уже существующих свойств продукта и без нарушения принципов его архитектуры.
Одной из таких задач является проблема времени жизни объектов. Может встретиться клиент, который не хочет или не нуждается в использовании полно масштабной объектно-ориентированной базы данных, а планирует лишь время от времени сохранять состояние таких структур, как очереди и множества, чтобы иметь возможность получить их состояние при следующем вызове из той же программы или из другого приложения. Принимая во внимание то, что подобные требования могут возникать довольно часто, имеет смысл дополнить нашу библиотеку простым механизмом сохранения объектов.
Сделаем два допущения, касающихся этого механизма. Во-первых, клиент должен обеспечить потоки, в которые объекты будут записываться и считываться. Во-вторых, клиент обязан обеспечить объектам поведение, необходимое для направления в поток.
Для создания такого механизма есть два альтернативных подхода. Можно построить класс-примесь, обеспечивающий семантику "долгожития"; именно такой подход реализован во многих объектно-ориентированных базах данных. В качестве альтернативы можно создать класс, экземпляры которого выступают в качестве агентов, ответственных за перенаправление различных структур в поток. Для того, чтобы обосновать наш выбор, попробуем оценить преимущества и недостатки того и другого подхода.
Как оказалось, для выбранного очень простого механизма сохраняемости примесь не совсем подходит (зато она очень хорошо вписывается в архитектуру настоящей объектно-ориентированной базы данных). При использовании примеси пользователь должен сам добавить ее к своему классу, зачастую переопределив при этом некоторые служебные функции класса-примеси. В нашем случае, для такого простого механизма это окажется неэффективным, так как пользователю будет легче разработать свои средства, чем дорабатывать библиотечные. Таким образом, мы склоняемся ко второму решению, которое потребует от пользователя лишь создания экземпляра уже существующего класса.
Рис. 9-14 иллюстрирует работу такого механизма, продлевающего жизнь объектов за счет работы отдельного агента.
Класс Persist является дружественным классу Queue; мы определяем эту связь внутри описания класса Queue следующим образом:
friend class Persist<Item, Queue<Item>>;
В этом случае классы становятся дружественными только в момент инстан-цирования класса Queue. Внедрив подобные описания дружественности в каждый абстрактный базовый класс, мы обеспечиваем возможность использования Persist с любой структурой библиотеки.
Параметризованный класс Persist содержит операции записи и считывания put и get, а также функции для подключения потоков обмена данными. Мы можем определить данную абстракцию следующим образом:
template<class Item, class Structure>
class Persist {
public: Persist();
Persist(iostream& input, iostream& output);
virtual ~Persist();
virtual void setInputStream(iostream&);
virtual void setOutputStream(iostream&);
virtual void put(Structure&);
virtual void get(Structure&);
protected: iostream* inStreain;
iostream* outStream;
};
Рис. 9-14. Обеспечение сохраняемости с помощью агента.
Реализация данного класса зависит от того, является ли он дружественным классу Structure, который фигурирует в качестве аргумента шаблона. В частности, Persist зависит от наличия в структуре вспомогательных функций purge, cardinality, itemAt, lock, и unlock. Далее срабатывает однородность нашей библиотеки: поскольку каждый базовый класс Structure имеет подобные функции, то persist можно безо всяких изменений использовать для работы со всеми имеющимися в библиотеке структурами.
Рассмотрим в качестве примера реализацию функции Persist::put:
template<class Item, class Structure>
void Persist<Item, Structure>::put(Structure& s)
{ s.lock();
unsigned int count = s.cardinality();
(*outStream) << count << endl;
for (unsigned int index = 0; index < count; index++) (*outStream) << s.itemAt(index);
s.unlock();
}
Эта операция использует разработанный нами ранее механизм блокировки, поэтому она будет работать и для защищенных, и для синхронизированных форм.
Алгоритм работы функции несложен: сначала в поток выводится количество элементов структуры, а затем, последовательно, все ее элементы. Реализация persist::get аналогично выполняет обратное действие:
template<class Item, class Structure>
void Persist<Item, Structure>::get(Structure& s)
{
s.lock();
unsigned int count;
Item item;
if (! inStream->eof()) {
(*inStream) >> count;
s.purge();
for (unsigned int index = 0; (index < count) && (! inStream->eof());
index++)
{
(*inStream) >> item;
s.add(item);
}
}
s.unlock();
}
Для того, чтобы использовать этот простой механизм сохранения данных, клиенту надо всего лишь инстанцировать один дополнительный класс для каждой структуры.
Задача построения среды разработки является довольно сложной. При конструировании основных иерархий классов необходимо учитывать различные, зачастую противоречивые требования к системе. Старайтесь сделать вашу библиотеку как можно более гибкой: никогда нельзя предсказать, как именно попытается ее использовать разработчик. Также очень важно сделать ее как можно более независимой от программной среды - так легче будет использовать ее совместно с другими библиотеками. Предлагаемые абстракции должны быть как можно более простыми, эффективными и понятными разработчику. Самые элегантные решения никогда не будут использованы, если сроки их освоения превысят время, необходимое программисту для решения проблемы своими силами. Сказать, что эффект достигнут, можно будет только когда станет видно, что ваши абстракции используются повторно много раз. То есть, когда разработчик ощутил преимущества их использования и не изобретает велосипед, а сосредоточивает внимание на тех особенностях задачи, которые еще никем не были решены.
Инструменты проектирования
Плохой разработчик, имея систему автоматического проектирования, сможет создать своего программного монстра за более короткий срок чем раньше. Великие проекты создаются великими проектировщиками, а не инструментами. Инструменты проектирования дают возможность проявиться индивидуальности, освобождают ее, чтобы она могла сосредоточиться исключительно на творческих задачах проектирования и анализа. Существуют вещи, которые автоматизированные системы проектирования могут делать хорошо, и есть вещи, которые они вообще не умеют. Например, если мы используем диаграмму объектов, чтобы показать сценарий с сообщением, посылаемым от одного объекта другому, автоматизированная система проектирования может гарантировать, что посылаемое сообщение будет в протоколе объекта; это пример проверки совместимости. Если мы введем инвариант, например, такой: "существует не более трех экземпляров данного класса", то мы ожидаем, что наш инструмент проследит за соблюдением данного требования; это пример проверки ограничения. Кроме того, система может оповестить вас, если какие-либо объявленные классы или методы не используются в проекте (проверка на полноту). Наконец, более сложная автоматическая система проектирования может определить длительность конкретной операции или достижимость состояния на диаграмме состояний; это пример автоматического анализа. Но, с другой стороны, никакая автоматическая система не сможет выявить новый класс, чтобы упростить вашу систему классов. Мы, конечно, можем попытаться создать такой инструмент, используя экспертные системы, но для этого понадобятся, во-первых, эксперты как в области объектно-ориентированного программирования, так и в предметной области, а во-вторых, четко сформулированные правила классификации и много здравого смысла. Мы не ожидаем появления таких средств в ближайшем будущем. В то же время, у нас есть вполне реальные проекты, которыми стоит заняться.
5.2. Диаграммы классов
Интеграция
Теперь, когда ключевые абстракции предметной области выявлены, можно приступить к их соединению в действующее приложение. Мы будем реализовывать и проверять вертикальные срезы системы, а затем последовательно отрабатывать механизмы.
Интеграция объектов верхнего уровня. На рис. 11-7 показана диаграмма объектов нашей системы на самом верхнем уровне, которая полностью соответствует структуре информационной доски, приведенной на рис. 11-1. Физическое содержание объектов доски в коллекции theBlackboard и источников знаний в коллекции theKnowledgeSources показано в соответствии с описанием вложенности классов.
На диаграмме появился экземпляр класса Cryptographer. Он агрегирует объекты доски, источники знаний и контроллер. В результате наша программа может иметь несколько экземпляров этого класса, а следовательно и несколько досок, функционирующих параллельно.
Рис. 11-7. Диаграмма объектов криптоанализа.
Для этого класса следует определить две основные операции:
reset - Перезапустить информационную доску.
decipher - Начать дешифровку криптограммы.
Конструктор этого класса должен создать зависимости между доской и источниками знаний, а также между источниками знаний и контроллером. Метод reset предельно прост: его цель состоит в том, чтобы вернуть эти связи и объекты в начальное состояние.
Метод decipher принимает строку - криптограмму. Теперь функции высокого уровня нашего приложения становятся предельно простыми, как это обычно и происходит в объектно-ориентированных системах:
char* solveProblem(char* ciphertext)
{
Cryptographer theCryptographer;
return theCryptographer.decipher(ciphertext);
}
Метод decipher оказывается несколько сложнее. В первую очередь с помощью операции assertProblem задание помещается на доску. После этого активизируются источники знаний. И, наконец, начинается циклический процесс обращения источников знаний к контроллеру с новыми и новыми предположениями и утверждениями до тех пор, пока не будет найдено решение задачи либо процесс не зайдет в тупик.
Для иллюстрации можно воспользоваться диаграммами взаимодействия или диаграммами объектов, но код на C++ выглядит тоже не слишком сложно:
theBlackboard.assertProblem();
theKnowledgeSources.reset();
while (!theController.isSolved || !theController.unableToProceed())
theController.processNextHint();
if (theBlackboard.isSolved())
return theBlackboard.retrieveSolution();
Теперь нам лучше всего дополнить алгоритм соответствующими архитектурными интерфейсами. Хотя в данный момент его дееспособность минимальна, но реализация в виде вертикального среза системной архитектуры позволяет проверить ключевые системные решения.
Посмотрим на две операции, определенные в классе decipher, а именно assertProblem и retrieveSolution. Первая из них интересна тем, что создает структуру доски. Опишем наш алгоритм следующим образом:
убрать из строки все начальные и концевые пробелы
if получилась пустая строка return
создать объект-предложение
занести предложение на доску
создать объект-слово (самое крайнее слева)
занести слово на доску
добавить слово к предложению
for каждый символ строки слева направо
if символ есть пробел
сделать текущее слово предыдущим
создать объект-слово
занести слово на доску
добавить слово к предложению
else
создать объект "буква шифра"
занести букву на доску
добавить букву к слову
В главе 6 уже упоминалось, что целью проектирования является создание наброска реализации. Эта запись представляет достаточно детализированный алгоритм, так что показывать его полную реализацию на C++ нет необходимости.
Операция retrieveSolution очень проста: она возвращает строку, записанную в данный момент на доске. Вызывая эту операцию до того как функция isSolved вернула значение True, можно получать частичные решения.
Реализация механизма предположений. Итак, мы умеем устанавливать и извлекать значения объектов доски. Теперь нам нужен механизм выдвижения высказывании об этих объектах. Этот механизм интересен ввиду его динамичности. При поиске решения предположения непрерывно создаются и отзываются, чем как раз и приводится в действие весь процесс.
На рис. 11- 8 показан сценарий выдвижения предположений. Источник знаний сообщает об имеющихся предположениях информационной доске, которая применяет их к алфавиту и оповещает остальные источники.
В простейшем случае, чтобы отменить предположение, мы просто прокручиваем этот механизм в другую сторону. Например, чтобы отменить предположение о букве, мы убираем из ее коллекции все предположения вплоть до неверного.
Рис. 11-8. Выдвижение предположений.
Можно действовать тоньше. Пусть мы предположили, что однобуквенное слово соответствует I (нужна гласная). Далее, сделано предположение, что некоторое двухбуквенное сочетание - это NN (нужны согласные). Если первое предположение окажется ошибочным, то второе вполне может быть сохранено. При таком подходе класс Assumption нужно дополнить еще одним методом, регистрирующим связь предположений между собой (взаимозависимость). Реализацию этого поведения можно отложить на более поздний срок, поскольку оно мало влияет на архитектуру.
Интерфейс и реализация
Мейер [19] и Снайдерс [20] высказали идею контрактного программирования:
большие задачи надо разделить на много маленьких и перепоручить их мелким субподрядчикам. Нигде эта идея не проявляет себя так ярко, как в проектировании классов.
По своей природе, класс - это генеральный контракт между абстракцией и всеми ее клиентами. Выразителем обязательств класса служит его интерфейс, причем в языках с сильной типизацией потенциальные нарушения контракта можно обнаружить уже на стадии компиляции.
Идея контрактного программирования приводит нас к разграничению внешнего облика, то есть интерфейса, и внутреннего устройства класса, реализации. Главное в интерфейсе - объявление операций, поддерживаемых экземплярами класса. К нему можно добавить объявления других классов, переменных, констант и исключительных ситуаций, уточняющих абстракцию, которую класс должен выражать. Напротив, реализация класса никому, кроме него самого, не интересна. По большей части реализация состоит в определении операций, объявленных в интерфейсе класса.
Мы можем разделить интерфейс класса на три части:
открытую (public) - видимую всем клиентам;
защищенную (protected) - видимую самому классу, его подклассам и друзьям (friends);
закрытую (private) - видимую только самому классу и его друзьям.
Разные языки программирования предусматривают различные комбинации этих частей. Разработчик может задать права доступа к той или иной части класса, определив тем самым зону видимости клиента.
В частности, в C++ все три перечисленных уровня доступа определяются явно. В дополнение к этому есть еще и механизм друзей, с помощью которого посторонним классам можно предоставить привилегию видеть закрытую и защищенную области класса. Тем самым нарушается инкапсуляция, поэтому, как и в жизни, друзей надо выбирать осторожно. В Ada объявления могут быть сделаны закрытыми или открытыми. В Smalltalk все переменные - закрыты, а методы - открыты. В Object Pascal все поля и операции открыты, то есть никакой инкапсуляции нет [Речь идет о старых версиях Object Pascal - Прим.
редактора-2]. В CLOS обобщенные функции открыты, а слоты могут быть закрытыми, хотя узнать их значения все равно можно.
Состояние объекта задается в его классе через определения констант или переменных, помещаемые в его защищенной или закрытой части. Тем самым они инкапсулированы, и их изменения не влияют на клиентов.
Внимательный читатель может спросить, почему же представление объекта определяется в интерфейсной части класса, а не в его реализации. Причины чисто практические: в противном случае понадобились бы объектно-ориентированные процессоры или очень хитроумные компиляторы. Когда компилятор обрабатывает объявление объекта, например, такое:
DisplayItem item1;
он должен знать, сколько отвести под него памяти. Если бы эта информация содержалась в реализации класса, нам пришлось бы написать ее полностью, прежде, чем мы смогли бы задействовать его клиентов. То есть, весь смысл отделения интерфейса от реализации был бы потерян.
Константы и переменные, составляющие представление класса, известны под разными именами. В Smalltalk их называют переменные экземпляра, в Object Pascal - поля, в C++ - члены класса, а в CLOS - слоты. Мы часто будем использовать эти термины как синонимы.
Инженерное дело как наука и искусство
На практике любая инженерная дисциплина, будь то строительство, механика, химия, электроника или программирование, содержит в себе элементы и науки, и искусства. Петроски красноречиво утверждает: "Разработка новых структур предполагает и полет фантазии, и синтез опыта и знаний: все то, что необходимо художнику для реализации своего замысла на холсте или бумаге. После того, как этот замысел созрел в голове инженера-художника, он обязательно должен быть проанализирован с точки зрения применимости данного научного метода инженером-ученым со всей тщательностью, присущей настоящему ученому" [38]. Аналогично, Дейкстра отмечает, что "Программная постановка задачи является упражнением в применении абстракции и требует способностей как формального математика, так и компетентного инженера" [39].
Когда разрабатывается совершенно новая система, роль инженера как художника выдвигается на первый план. Это происходит постоянно при проектировании программ. А тем более при работе с системами, обладающими обратной связью, и особенно в случае систем управления и контроля, когда нам приходится писать программное обеспечение, требования к которому нестандартны, и к тому же для специально сконструированного процессора. В других случаях, например, при создании прикладных научных средств, инструментов для исследований в области искусственного интеллекта или даже для систем обработки информации, требования к системе могут быть хорошо и точно определены, но определены таким образом, что соответствующий им технический уровень разработки выходит за пределы существующих технологий. Нам, например, могут предложить создать систему, обладающую большим быстродействием, большей вместимостью или имеющей гораздо более мощные функциональные возможности по сравнению с уже существующими. Во всех этих случаях мы будем стараться использовать знакомые абстракции и механизмы ("устойчивые промежуточные формы" в терминах Саймона) как основу новой системы. При наличии большой библиотеки повторно используемых программных компонентов, инженер-программист должен их по-новому скомпоновать, чтобы удовлетворить всем явным и неявным требованиям к системе, точно так же, как художник или музыкант находит новые возможности своего инструмента. Но так как подобных богатых библиотек практически не существует, инженер-программист обычно может использовать, к сожалению, лишь относительно небольшой список готовых модулей.
Искусственный интеллект: криптоанализ
Мыслящие существа способны проявлять очень сложные формы поведения, обладая сознанием, механизмы которого мы понимаем очень смутно. Подумайте, например, как вы планируете маршрут поездки по городу, чтобы выполнить массу дел. В плохо освещенном помещении вам удается распознавать границы предметов и избегать столкновений. Вы можете сосредоточиться на беседе с одним собеседником на шумной вечеринке, где много людей говорит одновременно. Ни одна из этих задач не имеет четкого алгоритмического решения. Планирование маршрута относится к классу NP-полных задач. Передвижение в темноте подразумевает принятие решения на основе неполной и нечеткой зрительной информации. Выделение речи одного человека из множества разговоров требует умения улавливать полезную информацию в шуме и отфильтровать нужные сообщения из общей какофонии.
Эти и подобные им проблемы привлекают внимание исследователей в области искусственного интеллекта, которые стремятся улучшить наши представления о разуме человека. В частности, создаются интеллектуальные системы, которые подражают некоторым аспектам поведения человека. Ерман, Ларк и Хайес-Рот указывали, что "интеллектуальные системы отличаются от традиционных рядом признаков (не все из них обяэательны):
способностью достигать целей, меняющихся во времени;
способностью усваивать, использовать и преобразовывать знания;
способностью оперировать с разнообразными подсистемами, варьируя используемые методы;
интеллектуальным взаимодействием с пользователями и другими системами;
самостоятельным распределением ресурсов и концентрацией внимания" [1].
Реализация в системе хотя бы одного из этих требований уже является непростой задачей. Еще сложнее сделать интеллектуальную систему для использования в некоторых специфических прикладных областях, например, в медицинской диагностике и диспетчеризации авиарейсов: такие системы должны, как минимум, не причинять вреда, а искусственный интеллект практически ничего не знает о здравом смысле.
Успехи энтузиастов в этой области несколько преувеличены; но, тем не менее, искусственный интеллект дал немало хороших практических идей, в частности представление знаний, концепция информационной доски и экспертные системы [2]. В данной главе рассматриваются подходы к созданию интеллектуальной системы расшифровки криптограмм на основе метода информационной доски, в достаточной степени моделирующего человеческий способ решения задачи. Как мы увидим, методы объектно-ориентированного проектирования очень хорошо работают в этой области.
11.1. Анализ
Использование
Пример. В недавнем примере объекты rampController и growingRamp иллюстрировали связь между объектами, которую мы представляли в виде отношения использования между их классами TemperatureController и TemperatureRamp.
class TemperatureController {
public:
TemperatureController(Location);
~TemperatureController();
void process(const TemperatureRamp&);
Minute schedule(const TemperatureRamp&) const;
private:
Heater h;
};
Класс TemperatureRamp упомянут как часть сигнатуры функции-члена process; это дает нам основания сказать, что класс TemperatureController пользуется услугами класса TemperatureRamp.
Клиенты и серверы. Отношение использования между классами соответствует равноправной связи между их экземплярами. Это то, во что превращается ассоциация, если оказывается, что одна из ее сторон (клиент) пользуется услугами другой (сервера). Пример клиент-серверных отношений показан на рис. 3-9.
На самом деле, один класс может использовать другой по-разному. В нашем примере это происходит в сигнатуре интерфейсной функции. Можно представить, что TemperatureController внутри реализации функции schedule использует, например, экземпляр класса Predictor (предсказатель). Отношения целого и части тут ни при чем, поскольку этот объект не входит в объект TemperatureController, а только используется. В типичном случае такое отношение использования проявляет себя, если в реализации какой-либо операции происходит объявление локального объекта используемого класса.
Строгое отношение использования иногда несколько ограничительно, поскольку клиент имеет доступ только к открытой части интерфейса сервера. Иногда по тактическим соображениям мы должны нарушить инкапсуляцию, для чего, собственно, и служат "дружеские" отношения классов в C++.
Использование объектного подхода
Возможность применения объектного подхода доказана для задач самого разного характера. На рис. 2-6 приведен перечень областей, для которых реализованы объектно-ориентированные системы. Более подробные сведения об этих и других проектах можно найти в приведенной библиографии.
В настоящее время объектно-ориентированное проектирование - единственная методология, позволяющая справиться со сложностью, присущей очень большим системам. Однако, следует заметить, что иногда применение OOD может оказаться нецелесообразным, например, из-за неподготовленности персонала или отсутствия подходящих средств разработки. К этой теме мы вернемся в главе 7.
Итерация
Итерация - это еще один архитектурный шаблон нашей библиотеки. В главе 3 уже отмечалось, что итератор представляет собой операцию, обеспечивающую последовательный доступ ко всем частям объекта. Оказывается, такой механизм нужен не только пользователям, он необходим и при реализации самой библиотеки, в частности, ее базовых классов.
При этом перед нами стоял выбор: можно было определять итерации как часть протокола объектов или создавать отдельные объекты, ответственные за итеративный опрос других структур. Мы выбрали второй подход по двум причинам:
Наличие выделенного итератора классов позволяет одновременно проводить несколько просмотров одного и того же объекта.
Наличие итерационного механизма в самом классе несколько нарушает его инкапсуляцию; выделение итератора в качестве отдельного механизма поведения способствует достижению большей ясности в описании класса.
Для каждой структуры определены две формы итераций. Активный итератор требует каждый раз от клиента явного обращения к себе для перехода к следующему элементу. Пассивный итератор применяет функцию, предоставляемую клиентом, и, таким образом, требует меньшего участия клиента. Чтобы обеспечить безопасность типов, для каждой структуры создаются свои итераторы.
Рассмотрим в качестве примера активный итератор для класса Queue:
template <class Item>
class QueueActiveIterator {
public: QueueActiveIterator(const Queue<Item>&);
~QueueActiveIterator();
Пассивный итератор реализует "применяемую" функцию. Эта идиома обычно используется в функциональных языках программирования. void reset();
int next();
int isDone() const;
const Item* currentItem() const;
protected: const Queue<Item>& queue;
int index;
};
Каждому итератору в момент создания ставится в соответствие определенный объект. Итерация начинается с "верха" структуры, что бы это ни значило для данной абстракции.
С помощью функции currentItem клиент может получить доступ к текущему элементу; значение возвращаемого указателя может быть нулевым в случае, если итерация завершена или если массив пуст.
Переход к следующему элементу последовательности происходит после вызова функции next (которая возвращает 0, если дальнейшее движение невозможно, как правило, из-за того, что итерация завершена). Селектор isDone служит для получения информации о состоянии процесса: он возвращает 0, если итерация завершена или структура пуста. Функция reset позволяет осуществлять неограниченное количество итерационных проходов по объекту.
Например, при наличии следующего объявления:
BoundedQueue<NetworkEvent> eventQueue;
фрагмент кода, использующий активный итератор для захода в каждый элемент очереди, будет выглядеть так:
QueueActiveIterator<NetworkEvent> iter(eventQueue);
while (!iter.isDone()) { iter.currentItem()->dispatch();
iter.next();
}
Итерационная схема, приведенная на рис. 9-9, иллюстрирует данный сценарий работы и, кроме того, раскрывает некоторые детали реализации итератора. Рассмотрим их более подробно.
Конструктор класса QueueActiveIterator сначала устанавливает связь между итератором и конкретной очередью. Затем он вызывает защищенную функцию cardinality, которая определяет количество элементов в очереди. Таким образом, конструктор можно описать следующим образом:
template<class Item>
QueueActiveIterator<Item>::QueueActiveIterator(const Queue<Item>& q)
:queue(q), index(q.cardinality() ? 0 : -1) {}
Класс QueueActiveIterator имеет доступ к защищенной функции cardinality класса Queue, поскольку числится в дружественных ему.
Операция итератора isDone проверяет принадлежность текущего индекса допустимому диапазону, который определяется количеством элементов очереди:
Рис. 9-9. Механизм итерации.
template<class Item>
int QueueActiveIterator<Item>::isDone() const
{ return ((index < 0) || (index >= queue.cardinality()));
}
Функция currentItem возвращает указатель на элемент, на котором остановился итератор. Реализация итератора в виде индекса объекта в очереди дает возможность в процессе итераций без труда добавлять и удалять элементы из очереди:
template<class Item>
const Item* QueueActiveIterator<Item>::currentItem() const
{ return isDone() ? 0 : &queue.itemAt(index);
}
При выполнении данной операции итератор снова вызывает защищенную функцию очереди, на сей раз itemAt. Кстати, currentItem можно использовать для работы как с ограниченной, так и с неограниченной очередью. Для ограниченной очереди itemAt просто возвращает элемент массива по соответствующему индексу. Для неограниченной очереди операция itemAt будет осуществлять проход по связному списку. Правда, как мы помним, класс Unbounded хранит информацию о последнем элементе, к которому было обращение, поэтому переход к следующему за ним элементу очереди (что и происходит при продвижении итератора) будет достаточно простым.
Операция next увеличивает значение текущего индекса на единицу, что соответствует переходу к следующему элементу очереди, а затем проверяет допустимость нового значения индекса:
template<class Item>
int QueueActiveIterator<Item>::next()
{ index++;
return !isDone();
}
Итератор, таким образом, в процессе своей работы вызывает две защищенные функции класса Queue: cardinality и itemAt. Определив эти функции как чисто виртуальные, мы передали ответственность за их конкретную оптимальную реализацию классам, производным от Queue.
Ранее отмечалось, что одна из основных задач наших архитектурных решений заключается в том, чтобы дать возможность клиенту копировать, присваивать и проверять на равенство экземпляры абстрактного базового класса, даже если они имеют различное представление. Эта возможность достигается за счет использования итераторов и некоторых служебных функций, позволяющих просматривать структуры независимо от их представления. Например, оператор присваивания для класса Queue можно определить следующим образом:
template<class Item>
Queue<Item>& Queue<Item>::operator=(const Queue<Item>& q)
{ if (this == &q) return *this;
((Queue<Item>&)q).lock();
purge();
QueueActiveIterator<Itea> iter(q);
while (!iter.isDone()) { add(*iter.currentItem());
iter.next();
}
((Queue<Item>&)q).unlock();
return *this;
}
В данном алгоритме используется идиома блокирования, которая более подробно рассмотрена в следующем разделе.
Присваивание осуществляется в порядке просмотра активным итератором структуры, определяемой аргументом q. Сначала защищенная служебная функция purge очищает очередь, а затем к ней с помощью другой защищенной служебной функции add последовательно добавляются новые элементы. Тот факт, что процесс итерации осуществляется с помощью полиморфных функций, дает возможность копировать, присваивать и проверять на равенство объекты, имеющие одинаковую структуру, но с разными представлениями.
Пассивный итератор, который также называют аппликатором, характеризуется тем, что он применяет определенную функцию к каждому элементу структуры. Для класса Queue пассивный итератор можно определить следующим образом:
template <class Item>
class QueuePassiveIterator {
public: QueuePassiveIterator(const Queue<Item>&);
~QueuePassiveIterator();
int apply(int (*)(const Item&));
protected: const Queue<Item>& queue;
};
Пассивный итератор действует на все элементы структуры за (логически) одну операцию. Таким образом, функция apply последовательно производит одну и ту же операцию над каждым элементом структуры, пока передаваемая итератору функция не возвратит нулевое значение или пока не будет достигнут конец структуры (в первом случае функция apply сама возвратит нулевое значение в знак того, что итерация не была завершена).
Изменение аппаратных средств
Мы уже говорили, что аппаратные средства развиваются быстрее, чем программное обеспечение. Более того, всегда будут причины, вынуждающие нас выбрать в ходе проектирования такие аппаратные решения, о которых потом мы будем сожалеть [Например, часть аппаратуры придется закупить у третьей стороны, а потом обнаружится, что поставленная продукция не отвечает оговоренным условиям. Или даже хуже того: поставщик критически важной продукции вышел из бизнеса. В таких случаях менеджер проекта должен выбрать одно из двух: (1) стенать в ночи; (2) подыскать замену и надеяться, что архитектура системы достаточно гибка, чтобы приспособиться к изменениям. Объектно-ориентированные анализ и проектирование помогут нам достигнуть (2), хотя иногда очень утешительно прибегнуть к (1)]. Поэтому рабочая аппаратура в больших системах устаревает гораздо раньше программы. Например, после нескольких лет эксплуатации мы можем заменить дисплеи на всех поездах и во всех диспетчерских центрах. Как это может повлиять на существующий проект? Если во время разработки мы сохраняли интерфейсы подсистем па высоком уровне абстракции, это изменение аппаратуры приведет лишь к незначительным изменениям в программе. Мы подправим только совокупность процедур, относящуюся к дисплеям, не затрагивая другие подсистемы, которые вообще ничего не знают об особенностях конкретных рабочих станций. Это достигается благодаря тому, что поведение всех рабочих станций скрыто в подсистеме Displays. Таким образом, подсистема действует как стена абстракций, которая защищает остальных клиентов от наших трудностей, вызванных разнообразием дисплеев.
Аналогично, радикальные изменения в стандартах телекоммуникации затронут нашу реализацию в очень ограниченном отношении. Наш проект гарантирует, что только подсистема Messages связана с сетевыми коммуникациями. Таким образом, фундаментальные изменения в сети не отразятся ни на каком высокоуровневом клиенте; подсистема Messages защищает их от капризов сетевой моды.
Итак, воображаемые изменения, которые мы вводили, не смогли разрушить структуру созданного нами проекта.
Это - верный признак хорошо спроектированной объектно-ориентированной системы.
Дополнительная литература
Требования к системе управления движением основываются на Продвинутой системе управления поездами (Advanced Train Control System), описанной Марфи (Murphy) [С 1988].
Передача и проверка сообщений присутствует практически во всех системах управления и контроля. Плинта, Ли и Риссман (Plinta, Lee, and Rissman) [С 1989] дали блестящее изложение этих вопросов и предложили механизм передачи сообщений по процессорам в распределенной системе, безопасный с точки зрения типов.
Изменение технических требований
Если принятые проектные решения были реализованы правильно, то новые технические требования к системе могут быть удовлетворены при минимальных изменениях проекта. Допустим, что предъявлены три новые требования к данной системе:
возможность дешифровки с иностранных языков;
возможность дешифровки перестановочного и простого подстановочного шифра, использующего (одну) подстановку и перестановку;
способность к самообучению.
Первое требование самое простое, поскольку связь нашей системы с английским языком не является существенной. Она отражается только на правилах источников знаний. Даже класс Alphabet сделан независимым от конкретного национального алфавита.
Второе требование существенно сложнее, но разрешимо в рамках механизма доски. Это потребует введения новых источников знаний относительно шифров перестановки. Ключевые механизмы и абстракции при этом также полностью сохранятся, но потребуется введение новых классов, которые будут действовать в рамках существующих механизмов выдвижения предположений и вывода.
Труднее всего выполнить последнее требование, так как обучение компьютеров относится к области искусственного интеллекта. Можно, например, предложить контроллеру в тупиковых ситуациях обращаться за помощью к пользователю системы с просьбой выдвинуть предположение. Такие предположения (вкупе с последовательностью действий, которая завела в тупик) могут регистрироваться системой и позволят в дальнейшем избегать подобных тупиков. Такой простейший механизм обучения может быть введен в нашу систему без существенного изменения структуры классов и в рамках действующих механизмов.
Дополнительная литература
При рассмотрении архитектурных шаблонов Шоу (Shaw) [A 1991] обсуждает метафору информационной доски и другие базовые идеи.
Енглемор и Морган (Englemore and Morgan) [С 1988] дали исчерпывающее обсуждение информационных досок, включая их эволюцию, теорию, проектирование и приложение. Существует описание двух объектно-ориентированных систем информационных досок: ВВ1 из Стэнфорда и BLOB, разработанной для Британского министерства обороны.
Другие полезные сведения относительно информационных досок могут быть найдены у Хайеса-Рота (Hayes-Roth) [J 1985] и Нии (Nii) [J 1986].
Подробное обсуждение индуктивного и дедуктивного подходов в системах формального вывода можно найти в работах Барра и Фейгенбаума (Barr and Feigenbamn) [J 1981], Брахмана и Левескье (Brachman and Levesque) [G 1985], Хайес-Рота, Ватермана и Лена (Hayes-Roth, Waterman, and Lenat) [J 1983], а также Винстона и Хорна (Winston and Horn) [G 1989].
Мейер и Матиас (Meyer and Matyas) [I 1982] рассмотрели сильные и слабые стороны разных шифров и алгоритмы их дешифровки.
Измерение качества абстракции
По мнению Ингалса "для построения системы должен использоваться минимальный набор неизменяемых компонент; сами компоненты должны быть по возможности стандартизованы и рассматриваться в рамках единой модели" [51]. Применительно к объектно-ориентированному проектированию такими компонентами являются классы и объекты, отражающие ключевые абстракции системы, а единство обеспечивается соответствующими механизмами реализации.
Опыт показывает, что процесс выделения классов и объектов является последовательным, итеративным. За исключением самых простых задач с первого раза не удается окончательно выделить и описать классы. В главах 4 и 7 показано, как в процессе работы сглаживаются противоречия, возникающие при начальном определении абстракций. Очевидно, такой процесс связан с дополнительными затратами на перекомпиляцию, согласование и внесение изменений в проект системы. Очень важно, следовательно, с самого начала по возможности приблизиться к правильным решениям, чтобы сократить число последующих шагов приближения к истине. Для оценки качества классов и объектов, выделяемых в системе, можно предложить следующие пять критериев:
зацепление;
связность;
достаточность;
полнота;
примитивность.
Термин зацепление взят из структурного проектирования, но в более вольном толковании он используется и в объектно-ориентированном проектировании. Стивенс, Майерс и Константайн определяют зацепление как "степень глубины связей между отдельными модулями. Систему с сильной зависимостью между модулями гораздо сложнее воспринимать и модифицировать. Сложность системы может быть уменьшена путем уменьшения зацепления между отдельными модулями" [52]. Пример неправильного подхода к проблеме зацепления привел Пейдж-Джонс, описав модульную стереосистему, в которой источник питания размещен в одной из звуковых колонок [53].
Кроме зацепления между модулями в объектно-ориентированном анализе, существенно зацепление между классами и объектами. Существует определенное противоречие между явлениями зацепления и наследования.
С одной стороны, желательно избегать сильного зацепления классов; с другой стороны, механизм наследования, тесно связывающий подклассы с суперклассами, помогает выгодно использовать сходство абстракций.
Понятие связности также заимствовано из структурного проектирования. Связность - это степень взаимодействия между элементами отдельного модуля (а для OOD еще и отдельного класса или объекта), характеристика его насыщенности. Наименее желательной является связность по случайному принципу, когда в одном классе или модуле собираются совершенно независимые абстракции. Для примера можно вообразить класс, соединяющий абстракции собак и космических аппаратов. Наиболее желательной является функциональная связность, при которой все элементы класса или модуля тесно взаимодействуют в достижении определенной цели. Так, например, класс Dog будет функционально связным, если он описывает поведение собаки, всей собаки, и ничего, кроме собаки.
К идеям зацепления и связности тесно примыкают понятия достаточности, полноты и примитивности. Под достаточностью подразумевается наличие в классе или модуле всего необходимого для реализации логичного и эффективного поведения. Иначе говоря, компоненты должны быть полностью пригодны к использованию. Для примера рассмотрим класс set (множество). Операция удаления элемента из множества в этом классе, очевидно, необходима, но будет ошибкой не включить в этот класс и операцию добавления элемента. Нарушение требования достаточности обнаруживается очень быстро, как только создается клиент, использующий абстракцию. Под полнотой подразумевается наличие в интерфейсной части класса всех характеристик абстракции. Идея достаточности предъявляет к интерфейсу минимальные требования, а идея полноты охватывает все аспекты абстракции. Полнотой характеризуется такой класс или модуль, интерфейс которого гарантирует все для взаимодействия с пользователями. Полнота является субъективным фактором, и разработчики часто ею злоупотребляют, вынося на верх такие операции, которые можно реализовать на более низком уровне.Из этого вытекает требование примитивности. Примитивными являются только такие операции, которые требуют доступа к внутренней реализации абстракции. Так, в примере с классом set операция Add (добавление к множеству элемента) примитивна, а операция добавления четырех элементов не будет примитивной, так как вполне эффективно реализуется через операцию добавления одного элемента. Конечно, эффективность тоже вещь субъективная. Операция, которая требует прямого доступа к структуре данных, примитивна по определению. Операция, которая может быть описана в терминах существующих примитивных операций, но ценой значительно больших вычислительных затрат, также является кандидатом на включение в разряд примитивных [Примером может служить операция добавления к множеству произвольного числа элементов (а не обязательно четырех). - Примеч. ред.].
Эволюция
Цель. Цель эволюции - наращивать и изменять реализацию, последовательно совершенствуя ее, чтобы в конечном счете создать готовую систему.
Эволюция архитектуры в значительной степени состоит в попытке удовлетворить нескольким взаимоисключающим требованиям ко времени, памяти и т.д. - одно всегда ограничивает другое. Например, если критичен вес компьютера (как при проектировании космических систем), то должен быть учтен вес отдельного чипа памяти. В свою очередь количество памяти, допустимое по весу, ограничивает размер программы, которая может быть загружена. Ослабьте любое ограничение, и станет возможным альтернативное решение; усильте ограничение, и некоторые решения отпадут. Эволюция при реализации программного проекта лучше чем монолитный набор приемов помогает определить, какие ограничения существенны, а какими можно пренебречь. По этой причине эволюционная разработка сосредоточена прежде всего на функциональности и только затем - на локальной эффективности. Обычно в начале проектирования мы слишком мало знаем, чтобы предвидеть слабое место в эффективности системы. Анализируя поведение каждого нового релиза, используя гистограммы и тому подобную технику, команда разработчиков через какое-то время сможет лучше понять, как настроить систему.
Таким образом, эволюция - это и есть процесс разработки программы. Как пишет Андерт, проектирование "есть время новшеств, усовершенствований, и неограниченной свободы изменять программный код, чтобы достигнуть целей. Производство - управляемый методичный процесс подъема качества изделия к надлежащему уровню" [24].
Пейдж-Джонс называет ряд преимуществ такой поступательной разработки:
"Обеспечивается обратная связь с пользователями, когда это больше всего необходимо, полезно и значимо.
Пользователи получают несколько черновых версий системы для сглаживания перехода от старой системы к новой.
Менее вероятно, что проект будет снят с финансирования, если он вдруг выбился из графика.
Главные интерфейсы системы тестируются в первую очередь и наиболее часто.
Более равномерно распределяются ресурсы на тестирование.
Реализаторы могут быстрее увидеть первые результаты работы системы, что их морально поддерживает.
Если сроки исполнения сжатые, то можно приступить к написанию и отладке программ до завершения проектирования".
Результаты. Основным результатом эволюции является серия исполнимых релизов, представляющих итеративные усовершенствования изначальной архитектурной модели. Вторичным продуктом следует признать выявление поведения, которое используется для исследования альтернативных подходов и дальнейшего анализа темных углов системы.
Действующие релизы выпускаются по графику, намеченному в начале планирования. Для скромного по размерам проекта, требующего 12-18 месяцев на разработку от начала до конца, это могло бы означать: по релизу каждые два или три месяца. Для более сложных проектов, требующих больше усилий разработчиков, можно выпускать релиз каждые шесть месяцев и реже. Более редкий график подозрителен, так как он не вынуждает разработчиков должным образом завершать микропроцессы и может скрыть опасные области.
Для кого делается действующий релиз программы? В начале процесса разработки основные действующие релизы передаются разработчиками контролерам качества, которые тестируют их по сценариям, составленным при анализе, и накапливают информацию о полноте, корректности и устойчивости работы релиза. Это раннее накопление данных помогает при выявлении проблем качества, которые будут учтены в следующих релизах. Позднее действующие релизы передаются конечным (альфа и бета) пользователям некоторым управляемым способом. "Управляемым" означает, что разработчики тщательно выверяют требования к каждому релизу и определяют аспекты, которые желательно проверить и оценить.
Специфика микропроцесса предполагает, что при многочисленных внутренних релизах разработчики выпускают наружу лишь некоторые исполнимые версии. Внутренние релизы представляют своего рода процесс непрерывной интеграции системы и завершают каждый цикл микропроцесса.
Косвенно подразумевается, что документация системы эволюционирует вместе с архитектурными релизами. Чтобы не относиться к ведению документации как к основному занятию, лучше всего получать ее, как естественный, полуавтоматически генерируемый побочный продукт эволюционного процесса.
Виды деятельности. Эволюция связана с двумя видами деятельности: микропроцесс и управление изменениями.
Работа, выполняемая между релизами, представляет процесс разработки в сжатом виде: это как раз и есть один цикл микропроцесса. Мы начинаем с анализа требований к следующему релизу, переходим к проектированию архитектуры и исследуем классы и объекты, необходимые для реализации этого проекта. Типичный порядок действий таков:
Определить функциональные точки, которые попадут в новый релиз, и области наивысшего риска, особенно те, которые были выявлены еще при эволюции предыдущего релиза.
Распределить задачи по релизам среди членов команды и начать новый микропроцесс. Контролировать микропроцесс, просматривая проект, и проверять состояние дел в важных промежуточных этапах с интервалами от нескольких дней до двух недель.
Когда потребуется понять семантику требуемого поведения системы, поручить разработчикам сделать прототип поведения. Четко установить назначение каждого прототипа и определить критерии готовности. После завершения решить, как включить результаты прототипирования в этот или последующие релизы.
Завершить микропроцесс интеграцией и очередным действующим релизом.
После каждого релиза следует перепроверить сроки и требования в основном плане релизов. Как правило, это незначительные корректировки дат или перенос функциональности из одного релиза в другой.
Управление изменениями необходимо именно в связи со стратегией итеративного развития. Всегда соблазнительно вносить неупорядоченные изменения в иерархию классов, их протоколы или механизмы, но это подтачивает стратегическую архитектуру и приводит к тому, что разработчики сами начинают путаться в собственном коде.
При эволюции системы на практике ожидаются следующие типы изменений:
Добавление нового класса или нового взаимодействия между классами.
Изменение реализации класса.
Изменение представления класса.
Реорганизация структуры классов.
Изменение интерфейса класса.
Каждый тип изменений имеет свою причину и стоимость.
Проектировщик вводит новые классы, если обнаружились новые абстракции или понадобились новые механизмы. Цена выполнения таких изменений обычно несущественна для управления разработкой. Если добавляется новый класс, нужно рассмотреть, куда он попадет в существующей структуре классов. Когда вводится новое взаимодействие классов, должен быть произведен минимальный анализ предметной области, чтобы убедиться, что оно действительно удовлетворяет одному из шаблонов взаимодействия.
Изменение реализации также обходится недорого. Обычно при объектно-ориентированной разработке сначала создается интерфейс класса, а потом пишется его реализация (то есть код функций-членов). Если только интерфейс в приемлемой степени стабилен, можно выбрать любое внутреннее представление этого класса и выполнить реализацию его методов. Реализация отдельного метода может быть изменена (обычно для исправления ошибки или повышения эффективности) позже. Можно скорректировать реализацию метода, чтобы воспользоваться преимуществами новых методов, определенных в существующем или во вновь введенном суперклассе. В любом случае изменение реализации метода обходится сравнительно недорого, особенно, если она была своевременно инкапсулирована.
Подобным образом можно было бы изменить представление класса (в C++ - защищенные и закрытые члены класса). Обычно это делается, чтобы получить более эффективные (с точки зрения памяти или скорости) экземпляры класса. Если представление класса инкапсулировано, что возможно в Smalltalk, C++, CLOS и Ada, то изменение в представлении не будет разрушать логику взаимодействия объектов-пользователей с экземплярами класса (если, конечно, новое представление обеспечивает ожидаемое поведение класса). С другой стороны, если представление класса не инкапсулировано, что также возможно в любом языке, то изменение в представлении класса чрезвычайно опасно, так как клиенты могут от него зависеть.
Это особенно верно в случае подклассов: изменение представления суперкласса вызовет изменения представления всех его подклассов. Во всяком случае, изменение представления класса имеет цену: нужно произвести перекомпиляцию интерфейса и реализации класса, сделать то же для всех его клиентов, для клиентов тех клиентов и т.д.
Реорганизация структуры классов системы встречается довольно часто, хотя и реже, чем другие упомянутые виды изменений. Как отмечают Стефик и Бобров, "Программисты часто создают новые классы и реорганизуют имеющиеся, когда они видят удобную возможность разбить свои программы на части" [26]. Изменение структуры классов обычно происходит в форме изменения наследственных связей, добавления новых абстрактных классов и перемещения обязанностей и реализации общих методов в классы более верхнего уровня в иерархии классов. На практике структура классов системы особенно часто реорганизуется вначале, а потом, когда разработчики лучше поймут взаимодействие ключевых абстракций, стабилизируется. Реорганизация структуры классов поощряется на ранних стадиях проектирования, потому что в результате может получиться более лаконичная программа. Однако реорганизация структуры классов не обходится даром. Обычно изменение положения верхнего класса в иерархии делает устаревшими определения всех классов под ним и требует их перекомпиляции (а, значит, и перекомпиляции всех зависимых от них классов и т.д.).
Еще один важный вид изменений, к которому приходится прибегать при эволюции системы, - изменение интерфейса класса. Разработчик обычно изменяет интерфейс класса, чтобы добавить некоторый новый аспект, удовлетворить семантике некоторой новой роли объектов класса или добавить новую операцию, которая всегда была частью абстракции, но раньше не была экспортирована, а теперь понадобилась некоторому объекту-пользователю. На практике использование эвристик для построения классов, которые мы обсуждали в главе 3 (особенно требование примитивного, достаточного и полного интерфейса), сокращает вероятность таких изменений.
Однако наш опыт никогда не бывает окончательным. Мы никогда не определим нетривиальный класс так, чтобы интерфейс его сразу оказался правильным.
Редко, но встречается удаление существующего метода; это обычно делается только для того, чтобы улучшить инкапсуляцию абстракции. Чаще мы добавляем новый метод или переопределяем метод, уже объявленный в некотором суперклассе. Во всех трех случаях это изменение дорого стоит, потому что оно логически затрагивает всех клиентов, требуя как минимум их перекомпиляции. К счастью, эти последние виды изменений, добавление и переопределение методов, совместимы снизу вверх. На самом деле вы обнаружите, что большинство изменений интерфейса, произведенного над определенными классами при эволюции системы, совместимы снизу вверх. Это позволяет для уменьшения воздействия этих изменений применить такие изощренные технологии, как инкрементная компиляция. Инкрементная компиляция позволяет нам вместо целых модулей перекомпилировать только отдельные описания и операторы, то есть перекомпиляции большинства клиентов можно избежать.
Почему перекомпиляция так неприятна? Для маленьких систем здесь нет проблем: перекомпиляция всей системы занимает несколько минут. Однако для больших систем это совсем другое дело. Перекомпиляция программы в сотни тысяч строк может занимать до половины суток машинного времени. Представьте себе, что вам понадобилось внести изменение в программное обеспечение компьютерной системы корабля. Как вы сообщите капитану, что он не может выйти в море, потому что вы все еще компилируете? В некоторых случаях цена перекомпиляции бывает так высока, что разработчикам приходится отказаться от внесения некоторых, представляющих разумные усовершенствования, изменений. Перекомпиляция представляет особую проблему для объектно-ориентированных языков, так как наследование вводит дополнительные компиляционные зависимости [27]. Для строго типизированных объектно-ориентированных языков программирования цена перекомпиляции может быть даже выше; в этих языках время компиляции принесено в жертву безопасности.
Все изменения, обсуждавшиеся до настоящего времени, сравнительно легкие: самый большой риск несут существенные изменения в архитектуре, которые могут погубить весь проект. Часто такие изменения производят чересчур блестящие инженеры, у которых слишком много хороших идей [28].
Путевые вехи и характеристики. Мы благополучно завершим фазу реализации, когда релизы перерастут в готовый продукт. Первой мерой качества, следовательно, будет то, в какой степени мы справились с реализацией функциональных точек, распределенных по промежуточным релизам, и насколько точно соблюдается график, составленный при их планировании.
Две других основных меры качества - скорость обнаружения ошибок и показатель изменчивости ключевых архитектурных интерфейсов и тактических принципов.
Грубо говоря, скорость обнаружения ошибок - это мера того, как быстро отыскиваются новые ошибки [29]. Вкладывая средства в контроль качества в начале разработки, мы можем получить количественные оценки качества для каждого релиза, которые менеджеры команды смогут использовать для определения областей риска и обновления команды разработчиков. После каждого релиза должен наблюдаться всплеск обнаружения ошибок. Стабильность этого показателя обычно свидетельствует о том, что ошибки не обнаруживаются, а его чрезмерная величина говорит о том, что архитектура еще не стабилизировалась или что новые элементы неверно спроектированы или реализованы. Эти характеристики используются при уточнении цели очередного релиза.
Показатель изменчивости архитектурного интерфейса или тактических принципов является основной характеристикой стабильности архитектуры [30]. Локальные изменения вероятны в течение всего процесса эволюции, но если структуры наследования или границы между категориями классов или подсистем постоянно перестраиваются, то это признак нерешенных проблем в архитектуре, что должно быть учтено как область риска при планировании следующего релиза.
Как выбирать отношения
Сотрудничество. Отношения между классами и объектами связаны с конкретными действиями. Если мы хотим, чтобы объект X послал объекту Y сообщение M, то прямо или косвенно класс X должен иметь доступ к классу Y, иначе невозможно вызвать в классе X операцию M. Под доступностью мы понимаем способность одной абстракции видеть другую и обращаться к ее открытым ресурсам. Абстракции доступны одна другой только тогда, когда перекрываются их области видимости и даны необходимые права доступа (так, закрытая часть класса доступна только ему самому и его друзьям). Таким образом, зацепление связано с видимостью.
Одним из полезных правил является закон Деметера, который утверждает, что "методы любого класса не должны зависеть от структуры других классов, а только от структуры (верхнего уровня) самого класса. В каждом методе посылаются сообщения только объектам из предельно ограниченного множества классов" [56]. Следование этому закону позволяет создавать слабо зацепленные классы, реализация которых скрыта. Такие классы достаточно автономны и для понимания их логики нет необходимости знать строение других классов.
При анализе структуры классов системы в целом можно обнаружить, что иерархия наследования либо широкая и мелкая, либо узкая и глубокая, либо сбалансированная. В первом случае структура классов выглядит как лес из свободно стоящих деревьев. Классы могут свободно смешиваться и вступать во взаимоотношения [57]. Во втором случае структура классов напоминает одно дерево с ветвями классов, имеющих общего предка [58]. Каждый из вариантов имеет свои достоинства и недостатки. Классы, составляющие лес, независимы друг от друга, но, вероятно, не лучшим образом используют возможности специализации и обобществления кода. В случае дерева классов эта "коммунальность" используется максимально, поэтому каждый из классов имеет меньший размер. Однако в последнем случае классы невозможно понять без контекста всех их предков.
Иногда требуется выбирать между отношениями наследования, агрегации и использования.
Например, должен ли класс Car (автомобиль) наследовать, содержать или использовать классы Engine (двигатель) и wheel (колесо)? В данном случае более целесообразны отношения использования. По мнению Мейера, между классами A и B "отношения наследования более пригодны тогда, когда любой объект класса B может одновременно рассматриваться и как объект A" [59]. С другой стороны, если объект является чем-то большим, чем сумма его частей, то отношение агрегации не совсем уместно.
Механизмы и видимость. Отношения между объектами определяется в основном механизмами их взаимодействия. Вопрос состоит только в том, кто о чем должен знать. Например, на ткацкой фабрике материалы (партии) поступают на участки для обработки. Как только они попадают на участок, об этом надо известить управляющего. Является ли поступление материала на участок операцией над участком, над материалом, или тем и другим сразу? Если это операция над участком, то класс участка должен быть видим для материала. Если это операция над материалом, то класс материала должен быть видим для участка, так как партия материала должна различать участки. В случае операции над помещением и участком нужно обеспечить взаимную видимость. Аналогично следует определить отношение между управляющим и участком (но не материалом и управляющим): либо управляющий должен знать об участке, либо участок об управляющем.
Иногда в процессе проектирования полезно явно определить видимость объектов. Существуют четыре основных способа сделать так, чтобы объект X (клиент) видел объект Y (сервер):
сервер является глобальным;
сервер передается клиенту в качестве параметра операции;
сервер является частью клиента в смысле классов;
сервер локально объявляется в области видимости клиента.
Эти варианты можно комбинировать. Y может быть частью X и при этом быть видимым другим объектам. В языке Smalltalk такой способ обычно означает зависимость между двумя объектами. Общая зона видимости приводит к структурной зависимости, то есть один объект не имеет исключительных прав доступа к другому: состояние этого другого объекта может быть изменено несколькими способами.
Как выбрать операции?
Функциональность. Описание интерфейса класса или модуля - трудная работа. Обычно первое приближение делается, исходя из структурного смысла класса, а затем, когда появляются клиенты класса, интерфейс уточняется, модифицируется и дополняется. В частности может возникнуть потребность в создании новых классов или в изменении взаимодействия существующих.
В пределах каждого класса принято иметь только примитивные операции, отражающие отдельные аспекты поведения. Такие методы называются точными. Принято также отделять методы, не связанные между собой. Это облегчает образование подклассов с переопределением поведения. Решение о количестве методов может быть обусловлено двумя причинами: описание поведения в одном методе упрощает интерфейс, но усложняет и увеличивает размеры самого метода; расщепление метода усложняет интерфейс, но делает каждый из методов проще. По наблюдению Мейера "хороший проектировщик умеет найти компромисс между большим числом связей (дробление системы на фрагменты) и большим размером модулей (что может привести к потере управляемости)" [54].
В объектно-ориентированном проектировании принято рассматривать методы класса как единое целое, поскольку все они взаимодействуют друг с другом для реализации протокола абстракции. Таким образом, определив поведение, нужно решить, в каком из классов это поведение реализуется. Халберт и O'Брайен предложили следующие критерии для принятия такого решения:
• Повторная используемость | Будет ли это поведение полезно более чем в одном контексте? |
• Сложность | Насколько трудно реализовать такое поведение? |
• Применимость | Насколько данное поведение характерно для класса, в который мы хотим включить поведение? |
• Знание реализации | Надо ли для реализации данного поведения знать секреты класса? |
Обычно операции объявляются, как методы класса, к объектам которого относятся данные действия. Однако в языках Object Pascal, C++, CLOS и Ada допускается описание операций в виде свободных подпрограмм (утилит класса).
Свободная подпрограмма, в терминологии C++, - это функция, не являющаяся элементом класса. Свободные подпрограммы не могут переопределяться подобно обычным методам, в них нет такой общности. Наличие утилит позволяет выполнить требование примитивности и уменьшить зацепление между классами, особенно если эти операции высокого уровня задействуют объекты многих различных классов.
Аспекты расхода памяти и времени. После того, как мы приняли решение о необходимости конкретной функции и определили ее семантику, следует принять решение об использовании ею времени и памяти. Для выражения таких решений принято использовать понятие лучшего, среднего и худшего вариантов, где худший - это верхний допустимый предел расходов.
Раньше мы уже отмечали, что поскольку один объект посылает другому сообщение, эти два объекта должны быть каким-то образом синхронизированы. В случае многих потоков управления это означает, что передача сообщений сложнее, чем управление вызовами подпрограмм. Для большинства языков программирования синхронизация просто не нужна, поскольку в них программы однопотоковые, и все объекты действуют последовательно. Мы говорим в таких случаях о простой передаче сообщений, так как ее семантика больше похожа на простой вызов подпрограмм. Однако в языках, поддерживающих параллелизм [Ada и Smalltalk имеют прямую поддержку параллельности. Языки типа C++ такой поддержкой не обладают, но в них часто можно обеспечить семантику параллельности за счет расширения классами (зависящими от платформы): примером служит библиотека AT&T для C++], нужно побеспокоиться о более изощренных системах передачи сообщений, чтобы избежать случаев, когда два потока работают одновременно и несогласованно с одним и тем же объектом. Объекты, семантика которых сохраняется при многопоточности, являются или синхронизированными, или защищенными.
В некоторых обстоятельствах полезно отмечать параллельность как для отдельных операций, так и для объекта в целом, так как разные операции могут потребовать разных форм синхронизации.
Выделяют следующие формы передачи сообщений:
• Синхронная | Операция активизируется только при готовности передающего и принимающего сообщения объектов; ожидание взаимной готовности может быть неопределенно долгим. |
• С учетом задержки | То же, что и синхронная, однако, в случае, если принимающий не готов, передающий не выполняет операцию. |
• С ограничением времени | То же, что и синхронная, однако, посылающий будет ждать готовности принимающего не дольше некоторого времени. |
• Асинхронная | Операция выполняется вне зависимости от готовности принимающего. |
Нужная форма выбирается для каждой операции отдельно, но только после того, как ее функциональная семантика определена.
Классический и современный подходы
Со времен Платона проблема классификации занимала умы бесчисленных философов, лингвистов, когнитивистов, математиков. Поэтому было бы разумно изучить накопленный опыт и применить его в объектно-ориентированном проектировании. Исторически известны только три подхода:
классическая категоризация;
концептуальная кластеризация;
теория прототипов [17].
Классическая категоризация. В классическом подходе "все вещи, обладающие данным свойством или совокупностью свойств, формируют некоторую категорию. Причем наличие этих свойств является необходимым и достаточным условием, определяющим категорию" [18]. Например, холостые люди - это категория: каждый человек или холост, или женат, и этот признак достаточен для решения вопроса, к какой категории принадлежит тот или иной индивидуум. С другой стороны, высокие люди не определяют категории, если, конечно, мы специально не уточним критерий, позволяющий четко отличать высоких людей от невысоких.
Классическая категоризация пришла к нам от Платона и Аристотеля. Последний в своей классификации растений и животных пользовался техникой рассуждений, напоминающей современную детскую игру в 20 вопросов (Это минерал, животное или растение? Это покрыто мехом или перьями? Может ли оно летать? Пахнет ли оно?) [20]. Такой подход нашел последователей, наиболее выдающимися из которых были: Фома Аквинский, Декарт, Локк. По утверждению Фомы Аквинского: "Мы можем именовать вещи согласно нашим знаниям об их природе, получаемым через познание их свойств и действий" [21].
Принципы классической категоризации отражены в современной теории развития ребенка. Пьяже утверждает, что после первого года жизни ребенок осознает существование объектов и затем начинает приобретать навыки их классификации, вначале пользуясь базовыми категориями, такими, как собаки, кошки и игрушки [22]. Позднее ребенок осознает, с одной стороны более общие (животные), а с другой стороны, более частные категории (колли, доги, овчарки) [23].
Таким образом, классический подход в качестве критерия похожести объектов использует родственность их свойств.
В частности, объекты можно разбивать на непересекающиеся множества в зависимости от наличия или отсутствия некоторого признака. Мински предположил, что "лучшими являются такие наборы свойств, элементы которых мало взаимодействуют между собой. Этим объясняется всеобщая любовь к таким критериям как размер, цвет, форма и материал. Так как эти критерии не пересекаются, про какой-нибудь предмет можно утверждать, что он большой, серый, круглый и деревянный" [24]. Вообще говоря, свойства не обязательно должны быть измеряемыми, в качестве их можно использовать наблюдаемое поведение. То обстоятельство, что птицы летают, а рыбы нет, позволяет отличить орла от форели.
Проблема классификации На рис. 4-1 показаны 10 поездов, обозначенных буквами от А до J. Каждое изображение состоит из паровоза и нескольких вагонов. Прежде чем продолжать чтение, попытайтесь за 10 минут определить несколько групп изображений, составленных по какому-то логическому признаку. Например, изображения можно разбить на три группы: в одной группе поезда имеют черные колеса, в другой группе - белые, а в третьей - и белые, и черные. Этот пример взят из работы Степпа и Михальски о концептуальном объединении [19]. Очевидно, "правильного" разбиения на группы не существует. Наши изображения были классифицированы 93 различными способами. Наиболее распространенный способ классификаций по длине состава: были выделены три группы: составы с двумя, тремя и четырьмя вагонами. Второй по популярности вид классификации - по цвету колес поезда. Сорок из девяносто трех видов классификации были уникальными (то есть вид содержал только один экземпляр). Экспериментируя с этим рисунком, мы убедились в правоте Степпа и Михальски. Большинство опрошенных нами предлагали один из двух наиболее популярных видов классификации (по длине состава и цвету колес поезда). Один опрошенный предложил следующее: в одной группе составы помечены буквами, нарисованными с помощью только прямых линий (A, Е, F, H и I), в другой - буквами с кривыми линиями. Вот уж, действительно, пример нетривиального мышления. Если вы уже справились с заданием, давайте изменим условия. Представим, что круги обозначают груз с токсичными веществами, прямоугольники - лесоматериалы, все остальные знаки обозначают пассажиров. Попытайтесь теперь классифицировать изображения и заметьте, как дополнительная информация влияет на вашу точку зрения. В наших опытах большинство опрошенных классифицировало поезда по тому, содержит состав токсичный груз или нет. Мы заключили, что новые сведения о реальной ситуации облегчают и улучшают классификацию. |
Какие конкретно свойства надо принимать во внимание? Это зависит от обстановки. Например, цвет автомобиля надо зафиксировать в задаче учета продукции автомобилестроительного завода, но он не интересен программе, управляющей уличным светофором. Вот почему мы говорим, что нет абсолютного критерия классификации, одна и та же структура классов может подходить для одной задачи и не годиться для другой. Джеймс пишет: "Нельзя утверждать, что некоторая схема классификации лучше других отражает структуру и порядок вещей в природе. Природе безразличны наши попытки в ней разобраться. Некоторые классификации действительно важнее других, но только в связи с нашими интересами, а не потому, что они вернее или полнее отражают реальность" [25].
Современное западное мышление по большей части насквозь пропитано классической категоризацией, однако, как показывает пример с высокими и низкими людьми, этот подход не всегда работает. Косок отмечает, что "естественные категории не четко отграничены друг от друга. Большинство птиц летает, но не все. Стул может быть деревянным, металлическим или пластмассовым, а количество ног у него целиком зависит от прихоти конструктора. Практически невозможно перечислить определяющие свойства естественной категории, так, чтобы не было исключений" [26]. Это, действительно, коренные пороки классической категоризации, которые и попытались исправить в современных подходах. Ими мы сейчас займемся.
Рис. 4-1. Проблема классификации.
Концептуальная кластеризация. Это более современный вариант классического подхода. Он возник из попыток формального представления знаний. Степп и Михальски пишут: "При таком подходе сначала формируются концептуальные описания классов (кластеров объектов), а затем мы классифицируем сущности в соответствии с этими описаниями" [27]. Например, возьмем понятие "любовная песня". Это именно понятие, а не признак или свойство, поскольку степень любовности песни едва ли можно измерить.
Но если можно утверждать, что песня скорее про любовь, чем про что-то другое, то мы помещаем ее в эту категорию.
Концептуальную кластеризацию можно связать с теорией нечетких (многозначных) множеств, в которой объект может принадлежать к нескольким категориям одновременно с разной степенью точности. Концептуальная кластеризация делает в классификации абсолютные суждения, основываясь на наилучшем согласии.
Теория прототипов. Классическая категоризация и концептуальная кластеризация - достаточно выразительные методы, вполне пригодные для проектирования сложных программных систем. Но все же есть ситуации, в которых эти методы не работают. Рассмотрим более современный метод классификации, теорию прототипов, предпосылки которой можно найти в книге по психологии восприятия Рош и ее коллег [28].
Существуют некоторые абстракции, которые не имеют ни четких свойств, ни четкого определения. Лакофф объясняет эту проблему так: "По утверждению Виттгенстейна (Wittgenstein), существуют категории (например, игры), которые не соответствуют классически образцам, так как нет признаков, свойственных всем играм... По этой причине их можно объединить так называемой семейной схожестью... Виттгенстейн утверждает, что у категории игр нет четкой границы. Категорию можно расширить и включить новые виды игр при условии, что они напоминают уже известные игры" [29]. Вот почему этот подход называется теорией прототипов: класс определяется одним объектом-прототипом, и новый объект можно отнести к классу при условии, что он наделен существенным сходством с прототипом.
Лаков и Джонсон применяют классификацию на основе прототипов к упомянутой выше проблеме стульев. Они замечают, что "мы считаем мягкий пуф, парикмахерское кресло и складной стул стульями не потому, что они удовлетворяют некоторому фиксированному набору признаков прототипа, но потому, что они имеют достаточное фамильное сходство с прототипом... Не требуется никакого общего набора свойств прототипа, которое годилось бы и для пуфика и для парикмахерского кресла, но они оба - стулья, так как каждый из них в отдельности похож на прототипный стул, пусть даже каждый по-своему.
Свойства, определяемые при взаимодействии с объектом (свойства взаимодействия), являются главными при определении семейного сходства" [30].
Понятие свойств взаимодействия - центральное для теории прототипов. В концептуальной кластеризации мы группируем в соответствии с различными концепциями. В теории прототипов классификация объектов производится по степени их сходства с конкретным прототипом.
Применение классических и новых теорий. Разработчику, озабоченному постоянно меняющимися требованиями к системе и вечно сражающемуся с напряженным планом при ограниченных ресурсах, предмет нашего обсуждения может показаться далеким от реальности. В действительности, три рассмотренных подхода к классификации имеют непосредственное отношение к объектно-ориентированному проектированию.
На практике мы идентифицируем классы и объекты сначала по свойствам, важным в данной ситуации, то есть стараемся выделить и отобрать структуры и типы поведения с помощью словаря предметной области. "Потенциально возможных абстракций, как правило, очень много" [31]. Если таким путем не удалось построить удобоваримой структуры классов, мы пробуем концептуальный подход. В этом случае в центре внимания уделяется поведение объектов, когда они взаимодействуют друг с другом. Наконец, мы пробуем выделить прототипы и ассоциировать с ними объекты.
Эти три способа классификации составляют теоретическую основу объектно-ориентированного подхода к анализу, предлагающего много практических советов и правил, которые можно применить для идентификации классов и объектов при проектировании сложной программной системы.
Классификация
Классификация - средство упорядочения знаний. В объектно-ориентированном анализе определение общих свойств объектов помогает найти общие ключевые абстракции и механизмы, что в свою очередь приводит нас к более простой архитектуре системы. К сожалению, пока не разработаны строгие методы классификации и нет правила, позволяющего выделять классы и объекты. Нет таких понятий, как "совершенная структура классов", "правильный выбор объектов". Как и во многих технических дисциплинах, выбор классов является компромиссным решением.
На одной из конференций программистам был задан вопрос: "Какими правилами вы руководствуетесь при определении классов и объектов?" Страуструп, разработчик языка C++, ответил: "Это как поиск святого Грааля. Не существует панацеи". Габриель, один из разработчиков CLOS, сказал: "Это вопрос, на который нет простого ответа. Я просто пробую" [1]. К счастью, имеется богатый опыт классификации в других науках, на основе которого разработаны методики объектно-ориентированного анализа. Каждая такая методика предлагает свои правила (эвристики) идентификации классов и объектов. Они и будут предметом этой главы.
Классификация и объектно-ориентированное проектирование
Определение классов и объектов - одна из самых сложных задач объектно-ориентированного проектирования. Наш опыт показывает, что эта работа обычно содержит в себе элементы открытия и изобретения. С помощью открытий мы распознаем ключевые понятия и механизмы, которые образуют словарь предметной области. С помощью изобретения мы конструируем обобщенные понятия, а также новые механизмы, которые определяют правила взаимодействия объектов. Поэтому открытие и изобретение - неотъемлемые части успешной классификации. Целью классификации является нахождение общих свойств объектов. Классифицируя, мы объединяем в одну группу объекты, имеющие одинаковое строение или одинаковое поведение.
Классификация есть средство упорядочение знаний.
Разумная классификация, несомненно, - часть любой науки. Михальски и Степп утверждают: "неотъемлемой задачей науки является построение содержательной классификации наблюдаемых объектов или ситуаций. Такая классификация существенно облегчает понимание основной проблемы и дальнейшее развитие научной теории" [2]. Та же философия относится и к инженерному делу. В области строительной архитектуры и городского планирования, как отмечает Александер, для архитектора "его проектная деятельность, и скромная, и гигантская по размеру, управляется целиком образами, которые он держит в своем сознании в данный момент, и его способностью комбинировать эти образы при создании нового проекта" [3].
Неудивительно, что классификация затрагивает многие аспекты объектно-ориентированного проектирования. Она помогает определить иерархии обобщения, специализации и агрегации. Найдя общие формы взаимодействия объектов, мы вводим механизмы, которые станут фундаментом реализации нашего проекта. Классификация помогает правильно определить модульную структуру. Мы можем расположить объекты в одном или разных модулях, в зависимости от степени схожести объектов; зацепление и связность - всего лишь меры этой схожести.
Классификация играет большую роль при распределении процессов между процессорами. Мы направляем процессы на один процессор или на разные в зависимости от того, как эти процессы связаны друг с другом.
Классы и объекты
И инженер, и художник должны хорошо чувствовать материал, с которым они работают. В объектно-ориентированной методологии анализа и создания сложных программных систем основными строительными блоками являются классы и объекты. Выше было дано всего лишь неформальное определение этих двух элементов. В этой главе мы рассмотрим природу классов и объектов, взаимоотношения между ними, а также сообщим несколько полезных правил проектирования хороших абстракций.
3.1. Природа объекта
Классы поддержки
При реализации класса, ответственного за манипуляции с текстовыми строками, мы столкнулись с тем, что возможностей, предоставляемых классами поддержки Bounded и Unbounded, явно недостаточно. Ограниченная форма, в частности, оказывается неэффективной для работы со строками с точки зрения памяти, так как мы должны инстанцировать эту форму в расчете на максимально возможную строку, и следовательно понапрасну расходовать память на более коротких строках. Неограниченная форма, в свою очередь, неэффективна с точки зрения быстродействия: поиск элемента в строке может потребовать последовательного перебора всех элементов связного списка. По этим причинам нам пришлось разработать третий, "динамический" вариант:
Структура хранится в "куче" в виде массива, длина которого может уменьшаться или увеличиваться.
Соответствующий класс поддержки Dynamic представляет собой промежуточный вариант по отношению к ограниченному и неограниченному классам, обеспечивающий быстродействие ограниченной формы (возможно прямое индексирование элементов) и эффективность хранения данных, присущую неограниченной форме (память выделяется только под реально существующие элементы).
Ввиду того, что протокол данного класса идентичен протоколу классов Bounded и Unbounded, добавление к библиотеке нового механизма не составит большого труда. Мы должны создать по три новых класса для каждого семейства (например, DynamicString, GuardedDynamicString и SynchronizedDynamicString). Таким образом, мы вводим следующий класс поддержки:
template<class Item, class StorageManager>
class Dynamic {
public: Dynamic(unsigned int chunkSize);
protected: Item* rep;
unsigned int size;
unsigned int totalChunks;
unsigned int chunkSize;
unsigned int start;
unsigned int stop;
void resize(unsigned int currentLength,
unsigned int newLength, int preserve - 1);
unsigned int expandLeft(unsigned int from);
unsigned int expandRight(unsigned int from);
void shrinkLeft(unsigned int from);
void shrinkRight(unsigned int from);
};
Последовательности разбиваются на блоки в соответствии с аргументом конструктора chunkSize. Таким образом, клиент может регулировать размер будущего объекта.
Из интерфейса видно, что класс Dynamic имеет много общего с классами Bounded и Unbounded. Отличия в реализации трех типов классов каждого семейства будут минимальны.
Займемся теперь классом ассоциативных массивов. Его реализация потребует новой переработки ограниченной, динамической и неограниченной форм. В частности, поиск элемента в ассоциативном массиве требует слишком много времени, если его приходится вести перебором всех элементов. Но производительность можно значительно увеличить, используя открытые хеш-таблицы.
Абстракция открытой хеш-таблицы проста. Таблица представляет собой массив последовательностей, которые называются клетками. Помещая в таблицу новый элемент, мы сначала генерируем хеш-код по этому элементу, а затем используем код для выбора клетки, куда будет помещен элемент. Таким образом, открытая хеш-таблица делит длинную последовательность на несколько более коротких, что значительно ускоряет поиск.
Соответствующую абстракцию можно определить следующим образом:
template<class Item, class Value, unsigned int Buckets, class Container>
class Table {
public: Table(unsigned int (*hash)(const Item&));
void setHashFunction(unsigned int (*hash)(const Item&));
void clear();
int bind(const Item&, const Value&);
int rebind(const Item&, const Value&);
int unbind(const Item&);
Container* bucket(unsigned int bucket);
unsigned int extent() const;
int isBound(const Item&) const;
const Value* valueOf(const Item&) const;
const Container *const bucket(unsigned int bucket) const;
protected: Container rep[Buckets];
};
Использование класса Container в качестве аргумента шаблона позволяет применить абстракцию хеш-таблицы вне зависимости от типа конкретной последовательности.
Рассмотрим в качестве примера ( сильно упрощенное) объявление неограниченного ассоциативного массива, построенного на базе классов Table и Unbounded:
template<class Item, class Value, unsigned int Buckets,
class StorageManager>
class UnboundedMap : public Map<Item, Value> {
public: UnboundedMap();
virtual int bind(const Item&, const Value&);
virtual int rebind(const Item&, const Value&);
virtual int unbind(const Item&);
protected: Table<Item, Value, Buckets, Unbounded<Pair<Item, Value>, StorageManager>> rep;
};
В данном случае мы истанцируем класс Table контейнером unbounded. Рис. 9-12 иллюстрирует схему взаимодействия этих классов.
В качестве свидетельства общей применимости этой абстракции мы можем использовать класс Table при реализации классов множеств и наборов.
Рис. 9-12. Классы поддержки.
Ключевые абстракции
Поиск и выбор ключевых абстракций. Ключевая абстракция - это класс или объект, который входит в словарь проблемной области. Самая главная ценность ключевых абстракций заключена в том, что они определяют границы нашей проблемы: выделяют то, что входит в нашу систему и поэтому важно для нас, и устраняют лишнее. Задача выделения таких абстракций специфична для проблемной области. Как утверждает Голдберг, "правильный выбор объектов зависит от назначения приложения и степени детальности обрабатываемой информации" [51].
Как мы уже отмечали, определение ключевых абстракций включает в себя два процесса: открытие и изобретение. Мы открываем абстракции, слушая специалистов по предметной области: если эксперт про нее говорит, то эта абстракция обычно действительно важна [52]. Изобретая, мы создаем новые классы и объекты, не обязательно являющиеся частью предметной области, но полезные при проектировании или реализации системы. Например, пользователь банкомата говорит "счет, снять, положить"; эти термины - часть словаря предметной области. Разработчик системы использует их, но добавляет свои, такие, как база данных, диспетчер экрана, список, очередь и так далее. Эти ключевые абстракции созданы уже не предметной областью, а проектированием.
Наиболее мощный способ выделения ключевых абстракций - сводить задачу к уже известным классам и объектам. Как будет показано ниже в главе 6, при отсутствии таких повторно используемых абстракций мы рекомендуем пользоваться сценариями, чтобы вести процесс идентификации классов и объектов.
Уточнение ключевых абстракций. Определив кандидатов на роли ключевых абстракций, мы должны оценить их по критериям, описанным в предыдущих главах. По словам Страуструпа "программист должен задаваться вопросами: Как создаются объекты класса? Как можно копировать и/или уничтожать объекты данного класса? Какие операции могут быть выполнены над этим объектом? Если ответы на эти вопросы туманны, то, возможно, общая концепция не ясна и лучше сесть и подумать еще раз, чем бросаться программировать" [53].
Определив новые абстракции, мы должны найти их место в контексте уже существующих классов и объектов. Не стоит пытаться делать это строго сверху вниз или снизу вверх. Халберт и О'Брайен утверждают, что "нет особой необходимости строить иерархию классов, начиная с самого верхнего класса, и потом дополнять ее подклассами. Чаще вы создаете несколько независимых иерархий, осознаете их общие черты и выделяете один или несколько суперклассов. Требуется несколько проходов вверх и вниз по иерархии, чтобы создать программный проект" [54]. Это не карт-бланш на хакерство, а всего лишь наблюдение, основанное на опыте и подтверждающее тот факт, что объектно-ориентированное проектирование - процесс последовательных приближений. Сходное наблюдение делает Страуструп: "Наиболее частые реорганизации в иерархии классов - это сведение совпадающих частей двух классов в один и разделение класса на два новых" [55].
Классы и объекты должны быть на надлежащем уровне абстракции: не слишком высоко и не слишком низко.
Трудно сразу расположить классы и объекты на правильных уровнях абстракции. Иногда, найдя важный класс, мы можем передвинуть его вверх в иерархии классов, тем самым увеличивая степень повторности использования кода. Это называется продвижением класса [56]. Аналогично, можем прийти к выводу, что класс слишком обобщен, и это затрудняет наследование: происходит семантический разрыв или конфликт зернистости [57]. В обоих случаях мы пытаемся выявить зацепление или недостаточную связность абстракций и смягчить конфликт.
Программисты часто легкомысленно относятся к правильному наименованию классов и объектов, но на самом деле очень важно отразить в обозначении классов и объектов сущность описываемых ими предметов. Программы необходимо писать тщательно, как художественную литературу, дума я и о читателях, и о компьютере [58]. При идентификации одного только объекта вам нужно придумать имена: для него, для его класса и для модуля, в котором класс объявлен.
Умножьте на тысячу объектов и сотни классов, и вы поймете, как остра проблема.
Мы предлагаем следующие правила:
Объекты следует называть существительными: theSensor или shape.
Классы следует называть обобщенными существительными: Sensors, Shapes.
Операции-модификаторы следует называть активными глаголами: Draw, moveLeft.
У операций-селекторов в имя должен включаться запрос или форма глагола "to be": extentOf, isOpen.
Подчеркивание и использование заглавных букв - на ваше усмотрение, постарайтесь лишь не противоречить сами себе.
Идентификация механизмов
Как найти механизмы? В предыдущем обсуждении мы называли механизмами структуры, посредством которых объекты взаимодействуют друг с другом и ведут себя так, как требуется. Так же как при разработке класса фактически определяется поведение отдельных объектов, так же и механизмы служат для задания поведения совокупности объектов. Таким образом, механизмы представляют шаблоны поведения.
Рассмотрим требование, предъявляемое к автомобилю: нажатие на акселератор должно приводить к увеличению оборотов двигателя, а отпускание акселератора - к их уменьшению. Как это происходит, водителю совершенно безразлично. Может быть использован любой механизм, обеспечивающий нужное поведение, и его выбор - дело вкуса разработчика. Например, допустимо любое из предложенных ниже инженерных решений:
Механическая связь между акселератором и карбюратором (обычное решение).
Под педалью ставится датчик давления, который соединяется с компьютером, управляющим карбюратором (механизм управления по проводам).
Карбюратора нет. Бак с горючим находится на крыше автомобиля и топливо свободно течет в двигатель. Поток топлива регулируется зажимом на трубке. Нажатие на педаль акселератора ослабляет зажим (очень дешево).
Какую именно реализацию выберет разработчик, зависит от таких параметров, как стоимость, надежность, технологичность и т.д.
Подобно тому, как было бы недопустимой невежливостью со стороны клиента нарушать правила пользования сервером, также и выход за пределы правил и ограничений поведения, заданных механизмом, социально неприемлем.
Водитель был бы удивлен, если бы, нажав на педаль акселератора, он увидел зажегшиеся фары.
Ключевые абстракции определяют словарь проблемной области, механизмы определяют суть проекта. В процессе проектирования разработчик должен придумать не только начинку классов, но и то, как объекты этих классов будут взаимодействовать друг с другом. Но конкретный механизм взаимодействия все равно придется разложить на методы классов. В итоге протокол класса будет отражать поведение его объектов и работу механизмов, в которых они участвуют.
Механизмы, таким образом, представляют собой стратегические решения в проектировании, подобно проектированию структуры классов. С другой стороны, проектирование интерфейса какого-то одного класса - это скорее тактическое решение. Стратегические решения должны быть выполнены явно, иначе у нас получится неорганизованная толпа объектов, кидающихся выполнять работу, расталкивая друг друга. В наиболее элегантных, стройных и быстрых программах воплощены тщательно разработанные механизмы.
Механизмы суть средства, с помощью которых объекты взаимодействуют друг с другом для достижения необходимого поведения более высокого уровня.
Механизмы представляют только один из шаблонов, которые мы находим в структурированных системах. Так, на нижнем конце своеобразной биологической пирамиды находятся идиомы. Это обороты, специфические для языков программирования или программистских культур, и отражающие общепринятые способы выражаться [Определяющей характеристикой идиомы является то, что ее игнорирование или нарушение влечет немедленные социальные последствия: вы превращаетесь в йеху или, еще хуже, в чужака, не заслуживающего уважения]. Например, в CLOS не принято использовать подчеркивание в именах функций или переменных, хотя в Ada это дело обычное [59]. Изучая язык, приходится учить его идиомы, которые обычно передаются в форме фольклора. Однако, как отметил Коплейн, идиомы играют важную роль в кодификации шаблонов низкого уровня. Он заметил, что "многие общепрограммистские действия идиоматичны" и поэтому распознание таких идиом позволяет "использовать конструкции C++ для выражения функциональности вне самого этого языка с сохранением иллюзии, что они являются частью языка" [60].
Место на верху пирамиды занимают среды разработки. Среда разработки - это собрание классов, предназначенных для определенной прикладной ситуации. Среда дает готовые классы, механизмы и услуги, которыми можно сразу пользоваться или приспосабливать для своих нужд.
Если идиомы составляют часть программистской культуры, то среды разработки обычно - коммерческий продукт. Например, Apple MacApp и его преемник Bedrock - среды, написанные на C++ и предназначенные для построения приложений со стандартным интерфейсом пользователя Macintosh. Аналогичную роль для Windows играют Microsoft Foundation Classes и ObjectWindows корпорации Borland.
Примеры механизмов. Рассмотрим механизм рисования, применяемый обычно в графических интерфейсах пользователя. Для того, чтобы представить какой-либо рисунок на экране, необходимы несколько объектов: окно, вид, модель, которую надо показать, и, наконец, клиент, который знает, когда надо нарисовать модель, но не знает, как это сделать. Сначала клиент дает окну команду нарисовать себя. Так как окно может включать в себя ряд видов, оно в свою очередь приказывает каждому из них нарисовать себя. Каждый вид посылает сообщение своей модели нарисовать себя, в результате чего и появляется изображение на экране. В этом механизме модель полностью отделена от окна и вида, в котором она представлена: виды могут посылать сообщения моделям, но модели не могут посылать сообщения видам. Smalltalk использует вариант этого механизма, названный парадигмой Model-View-Controller, модель-вид-контроллер (MVC) [61].
Механизмы, таким образом, представляют уровень повторного использования в проектировании, более высокий, чем повторное использование индивидуальных классов. MVC, например, является основой интерфейса пользователя в языке Smalltalk. Эта парадигма в свою очередь строится на базе механизма зависимостей, который вложен в поведение базового класса языка Smalltalk (класса object) и часто используется библиотекой классов языка Smalltalk.
Примеры механизмов можно найти во многих системах.
Структуру операционной системы, например, можно описать на высоком уровне абстракции по тем механизмам, которые используются для диспетчеризации программ. Система может быть монолитной (как MS-DOS), иметь ядро (UNIX) или представлять собой иерархию процессов (операционная система THE) [62]. В системах искусственного интеллекта использованы разнообразные механизмы принятия решений. Одним из наиболее распространенных является механизм рабочей области, в которую каждый индивидуальный источник знаний независимо заносит свои сведения. В таком механизме не существует центрального контроля, но любое изменение в рабочей области может явиться толчком для выработки системой нового пути решения поставленной задачи [63]. Коад похожим образом выявил ряд общих механизмов в объектно-ориентированных системах, включая шаблоны временных ассоциаций, протоколирование событий и широковещательную рассылку сообщений [64]. Во всех случаях эти механизмы проявляются не как индивидуальные классы, а как структуры сотрудничающих классов.
На этом завершается наше изучение классификации и понятий, являющихся основой объектно-ориентированного проектирования. Следующие три главы посвящены самому методу, в частности системе обозначений, процессу проектирования и рассмотрению практических примеров.
Выводы
Идентификация классов и объектов - важнейшая задача объектно-ориентированного проектирования; процесс идентификации состоит из открытия и изобретения.
Классификация есть проблема группирования (кластеризации) объектов.
Классификация - процесс последовательных приближений; трудности классификации обусловлены в основном тем, что есть много равноправных решений.
Есть три подхода к классификации: классическое распределение по категориям (классификация по свойствам), концептуальная кластеризация (классификация по понятиям) и теория прототипов (классификация по схожести с прототипом).
Метод сценариев - это мощное средство объектно-ориентированного анализа, его можно использовать для других методов: классического анализа, анализа поведения и анализа предметной области.
Ключевые абстракции отражают словарь предметной области; их находят либо в ней самой, либо изобретают в процессе проектирования.
Механизмы обозначают стратегические проектные решения относительно совместной деятельности объектов многих различных типов.
Дополнительная литература
Проблема классификации вечна. В своей работе "Политик" Платон вводит классический подход к классификации, группируя объекты со схожими свойствами. Аристотель в "Категориях" продолжает эту тему и анализирует различие между классами и объектами. Несколькими веками позже Фома Аквинский в "Summa Theologica" и затем Декарт в "Рассуждении о методе" обдумывают философию классификации. Среди современных объективистских философов можно назвать Рэнда (Rand) [I 1979].
Альтернативы объективистскому взгляду на мир обсуждаются Лаковым (Lakoff) [I 1990] и Голдстейном и Алжером (Goldstein and Alger) [C 1992].
Умение классифицировать - важный человеческий навык. Теории приобретения этого навыка в раннем детстве строились первоначально Пьяже (Piaget) и были подытожены Майером (Maier) [A 1969]. Лефрансуа (Lefrancois) [A 1977] дал легко читаемое введение в эти идеи и блестяще изложил процесс формирования у детей концепции объекта.
Когнитивисты изучили проблему классификации во всех деталях. Ньэлл и Саймон (Newell and Simon) [A 1972] дали ни с чем не сравнимый источник материала по человеческим навыкам классификации. Более подробная информация может быть найдена в работах Саймона (Simon) [A 1982], Хофстадтера (Hofstadter) [I 1979], Зиглера и Ричардса (Siegler and Richards) [A 1982] и Стиллинга и др. (Stillings et al.) [A 1987]. Лингвист Лаков (Lakoff) [A 1988] анализировал способы, которыми разные человеческие языки справляются с проблемами классификации и что это говорит о мышлении. Мински (Minsky) [A 1986] подошел к этому вопросу с другой стороны, от теории структуры сознания.
Концептуальную кластеризацию как подход к представлению знания через классификацию в деталях описали Михальски и Степп (Michalski and Stepp) [А 1983, 1986], Пекхам и Марьянский (Peckham and Maryanski) [J 1988] и Coya (Sowa) [A 1984].
Анализ предметных областей, подход к выделению ключевых абстракций и механизмы изучения словаря предметной области описаны во всеобъемлющем собрании работ Прието-Диаса и Аранго (Prieto-Diaz and Arango) [A 1991]. Иско (Iscoe) [В 1988] принадлежит несколько важных достижений в этой области. Дополнительная информация может быть найдена в работах Иско, Броуна и Вета (Iscoe, Browne and Weth) [В 1989], Мура и Бэйлина (Moore and Bailin) [В 1988] и Аранго (Arango) [В 1989].
Интеллектуальная классификация часто требует нового, нестандартного взгляда на мир, и этому искусству можно научить. Фон Оич (Von Oech) [I 1990] предлагает некоторые пути развития творческих способностей. Коад (Coad) [A 1993] создал настольную игру Object Game, способствующую развитию навыков идентификации классов и объектов.
Хотя эта область пребывает еще в младенческом состоянии, но некоторая многообещающая работа по каталогизации шаблонов уже проведена. В частности, выявлены идиомы, механизмы и среды разработки. Интересные ссылки: Коплиен (Coplien) [G 1992], Коад (Coad) [А 1992], Джонсон (Johnson) [А 1992], Шоу (Shaw) [А 1989,1990, 1991], Вирфс-Брок (Wirfs-Brock) [С 1991]. Работа Александера (Alexander) [I 1979] посвящена применению шаблонов в архитектуре и городском планировании.
Математики пытались развить эмпирические подходы к классификации, доведя их до того, что называется теорией измерения. Стивене (Stevens) [A 1946] и Кумбс, Райфа и Тралл (Coombs, Raiffa and Thrall) [A 1954] провели в этом направлении плодотворную работу.
Классификационное Общество Северной Америки издает журнал с периодичностью два выпуска в год, содержащий множество статей по вопросам классификации.
Ключевые абстракции и механизмы
В результате изучения требований к системе управления движением становится очевидно, что мы должны решить четыре основные подзадачи:
сеть
база данных
интерфейс "человек/компьютер"
управление аналоговыми устройствами в реальном времени.
Как мы пришли к выводу, что именно в этих подзадачах сконцентрирован основной риск разработки?
Систему связывает воедино распределенная сеть передачи данных. С помощью радио передаются сообщения: между ответчиками и поездами, между поездами и наземными контроллерами, между поездами и блоками интерфейсов путевых устройств, между наземными контроллерами и путевыми устройствами. Кроме того, сообщения должны передаваться между диспетчерскими центрами и отдельными наземными контроллерами. Надежная работа всей системы обеспечивается своевременным и надежным приемом и передачей сообщений.
Кроме того, система должна одновременно хранить информацию о местоположении и планируемых маршрутах множества поездов. Мы должны поддерживать постоянно обновляемую информацию и гарантировать ее целостность даже в случае попыток одновременно записать и считать информацию из разных мест сети. Следовательно, нам нужна распределенная база данных.
Проектирование человеко-машинного интерфейса ставит еще одну группу задач. Дело в том, что пользователями системы в основном являются машинисты и диспетчеры; но никто из них не обязан обладать профессиональными навыками работы с компьютером. Пользовательский интерфейс операционных систем, таких как UNIX или Windows, пригоден (по большей части) для специалиста-программиста, но считается слишком враждебным для конечных пользователей таких сред, как система управления движением. Следовательно, все формы взаимодействия должны быть спроектированы в расчете на эту особую группу пользователей.
Наконец, система управления движением должна взаимодействовать с разнообразными датчиками и исполнительными механизмами. Не останавливаясь здесь на природе этих устройств, отметим, что принципы управления ими не зависят от конкретного типа устройства и должны быть выбраны однотипными во всей системе.
Каждая из этих четырех подзадач включает целый ряд обособленных вопросов. Системные архитекторы должны найти ключевые абстракции и механизмы каждой задачи, и тогда мы сможем пригласить экспертов для решения каждой отдельной подзадачи независимо от других. Однако, ни анализ, ни проектирование не удастся завершить за один проход, - круг за кругом анализ будет обнаруживать новые архитектурные проблемы, решение которых потребует нового анализа. Таким образом, разработка будет неизбежно пошаговой и итеративной.
Из краткого проблемного анализа четырех главных подзадач мы видим, что существуют три высокоуровневые ключевые абстракции:
• Поезда | Локомотивы и вагоны. |
• Пути | Профиль пути, его качество и путевые устройства. |
• Планы | Расписания, приказы, устранение накладок, назначение полномочии и подбор бригад. |
Каждый поезд характеризуется текущим положением на путях и может иметь только один активный план движения. Аналогично, в каждой точке пути может быть самое большое один поезд. Каждый план относится только к одному поезду, но ко многим точкам пути.
Мы можем выделить ключевой механизм для каждой из четырех (почти независимых) подзадач:
передача сообщений
планирование движения поездов
отображение информации
сбор данных от датчиков.
Эти четыре механизма составляют душу нашей системы. Они являются наиболее сложными и рискованными частями проекта. Важно, чтобы мы поручили лучшим системным архитекторам поэкспериментировать с различными подходами и постепенно создать среду, на базе которой более молодые разработчики сделают все остальное.
12.2. Проектирование
Как уже отмечалось в главе 6, создание архитектуры подразумевает выявление основной структуры классов и спецификацию общих взаимодействий, которые оживляют классы. Сконцентрировав внимание прежде всего на этих механизмах, мы с самого начала выявляем элементы наибольшего риска и нацеливаем на них все усилия системных архитекторов. Результаты этой фазы дают хорошую основу (в виде классов и взаимодействий), на базе которой строятся функциональные элементы нашей системы.
В данном разделе мы подробно рассмотрим семантику каждого из четырех выделенных ключевых механизмов.
Концепции
Первая часть посвящена анализу сложности, присущей программным системам, в частности анализу того, как эта сложность проявляется. Мы вводим объектную модель как средство борьбы со сложностью. Мы рассматриваем основные элементы объектной модели: абстрагирование, инкапсуляцию, модульность, иерархию, типизацию, параллелизм, устойчивость. Мы задаемся такими глубинным вопросами как "Что такое класс?" и "Что такое объект?". Поскольку выявление осмысленных классов и объектов - ключевая задача объектно-ориентированного проектирования, значительное время мы уделяем вопросам классификации. В частности, мы рассматриваем подходы к классификации в других дисциплинах: биологии, лингвистике и психологии, а затем применяем полученные выводы к обнаружению классов и объектов внутри программных систем.
Сэр Исаак Ньютон по секрету признавался друзьям, что он
знает, как гравитация ведет себя, но не знает, почему.
Лили Томлин (Lily Tomlin)
В поисках признаков разумной жизни во Вселенной
(The Search for Signs of Intelligent Life in the Universe)
Концептуализация
Цель. Концептуализация должна установить основные требования к системе. Для каждой принципиально новой части программы или даже для нового применения существующей системы найдется такой момент, когда в голову разработчика, архитектора, аналитика или конечного пользователя западет идея о новом приложении.
Это может быть новое деловое предприятие, дополнительное изделие на поточной линии или, например, новая функция в существующей программной системе. Цель концептуализации не в том, чтобы полностью определить идею, а в том, чтобы выработать взгляд на нее и мысленно проверить ее.
Результаты. Первичными продуктами концептуализации являются прототипы системы. Определенно, каждой существенно новой программной системе необходим некоторый черновой прототип, пусть и выполненный "на скорую руку". Такие прототипы не полны по самой своей природе и разработаны лишь схематически. Однако, нужно сохранять интересные (пусть, возможно, и отвергнутые) прототипы, так как этим организация поддерживает корпоративную память о первоначальном замысле и сохраняет связь с исходными предположениями. При проектировании этот архив дает незаменимый материал для экспериментирования, к которому аналитики и архитекторы могут возвращаться, когда хотят опробовать новые идеи.
Очевидно, для грандиозных приложений (национального или международного значения), само построение прототипов может оказаться большим свершением. Ведь гораздо лучше столкнуться с трудностями при реализации, обнаружив, что неверны какие-то предположения о функциональности, эффективности, размере или сложности системы, чем пренебречь прогрессивным решением. Такое пренебрежение может грозить финансовой или социальной катастрофой.
Подчеркнем: прототипы хороши, но их следует выбросить. Нельзя позволять им непосредственно эволюционировать в готовую систему, если к этому не имеется достаточно серьезных оснований. Сжатые сроки не являются уважительной причиной: оптимизация краткосрочной разработки, игнорирующая последующие затраты владельца программного продукта, - типичный пример ложной экономии.
Виды деятельности. Концептуализация по самой своей природе - творческая деятельность, и, следовательно, она не должна быть скована жесткими правилами разработки. Возможно, самое важнее для организации - создать структуру, которая обеспечивала бы достаточные ресурсы для возникновения и исследования новых идей [Если организация не сделает этого сама, то отдельные разработчики все равно сделают это, не спрашиваясь у компании, в которой они работают. Так и возникают новые программистские фирмы. Их появление хорошо для индустрии в целом, но не для самой осиротевшей компании]. Новые идеи могут исходить из самых различных источников: конечных пользователей, групп пользователей, разработчиков, аналитиков, проектировщиков, распространителей и т.д. Для руководства важно вести регистрацию этих идей, располагая их по приоритетам и распределяя ограниченные ресурсы так, чтобы исследовать самые многообещающие из них. Когда для исследования выбрано конкретное направление, типичен следующий порядок дальнейших действий:
Решить, какие цели преследуются при опробовании концепции и каковы критерии того, что считать благополучным исходом.
Собрать подходящую команду для разработки прототипа. Часто она состоит из единственного члена (который и есть тот самый мечтатель). Самое лучшее, что организатор может сделать, чтобы облегчить усилия команды - не стоять на ее пути.
Оценить готовый прототип и принять ясное решение о проектировании конечного продукта или о дальнейшем исследовании. Решение приступить к разработке конечного продукта нужно принимать с разумным учетом потенциального риска, выявленного при опробовании концепции.
Концептуализация не содержит ничего специфически объектно-ориентированного. Каждая программная парадигма должна предусматривать опробование концепций. Однако, как часто бывает, разработка прототипов обычно происходит быстрее в тех случаях, когда на лицо зрелая объектно-ориентированная среда.
Довольно часто концепции опробуются на одном языке (например, на Smalltalk), а разработка конечного продукта ведется на другом (скажем, C++).
Путевые вехи и характеристики. Важно, чтобы для оценки прототипа были установлены четкие критерии. Работу над прототипом чаще планируют по срокам (имея в виду, что прототип должен быть завершен к определенной дате), чем по требованиям. Это не всегда плохо, так как искусственно ограничивает усилия по созданию прототипа и пресекает попытки выпустить концептуально недоношенный продукт.
Менеджеры верхнего звена могут оценить здоровье организации по ее отношению к новым идеям. Любая организация, которая сама не генерирует новые идеи, либо уже мертва, либо близка к этому. Наиболее благоразумное действие в такой ситуации - выделить независимые подразделения либо вообще уйти из бизнеса. С другой стороны, любая организация, заваленная новыми идеями, но неспособная определить их разумный приоритет, неуправляема. Такие компании часто тратят впустую существенные ресурсы, перескакивая к разработке изделия слишком рано, без исследования риска. Наиболее благоразумно здесь было бы формализовать процесс производства и наладить переход от концепции к продукту.
Литературные ссылки
Предисловие
Mills, Н. 1985. DPMA and Human Productivity. Houscon, TX: Data Processing Management, Association.
Часть I. Концепции
Wagner, J. 1986. The Search for Signs of Intelligent Life in the Universe. New York, NY: Harper and Row, p.202. By permission of ICM. Inc.
Глава 1. Сложность
[1] Brooks, F. April 1987. No Silver Bullet: Essence and Accidents of Software Engineering. IEEE Computer vol.20(4), p.12.
[2] Peters, L. 1981. Software Design. New York, NY: Yourdon Press, p.22.
[3] Brooks. No Silver Bullet, p.11.
[4] Parnas, D. July 1985. Software Aspects ofStrategic Defense Systems. Victoria, Canada: University of Victoria. Report DCS-47-IR.
[5] Peter, L. 1986. The Peter Pyramid. New York, NY: William Morrow, p.153.
[6] Waldrop, M. 1992. Complexity: The Emerging Science at the Edge of Order and Chaos. New-York, NY: Simon and Schuster.
[7] Courtois, P. June 1985. On Time and Space Decomposition of Complex Structures. Communications of the ACM vol.28(6), p.596.
[8] Simon, H. 1982. The Sciences of the Artificial. Cambridge, MA: The MIT Press, p.218.
[9] Rechtin, E. October 1992. The Art of Systems Architecting. IEEE Spectrum, vol.29( 10), p.66.
[10] Simon. Sciences, p.217.
[11] Ibid, р. 221.
[12] Ibid, p.209.
[13] Gall, J. 1986. Systemantics: How Systems Really Work and How They Fail. Second Edition. Ann Arbor, MI: the General Systemantics Press, p.65.
[14] Miller, G. March 1956. The Magical Number Seven, Plus or Minus Two: Some Limits on Our Capacity for Processing Information. The Psychological Reviev vol.63(2), p.86.
[15] Simon. Sciences, p.81.
[16] Dijktra, E. 1979. Programming Considered as a Human Activity. Classics in Software Engineering. New York, NY: Yourdon Press, p.5.
[17] Parnas, D. December 1985. Software Aspects of Strategic Defense Systems. Communications of the ACM vol.28(12), p.1328.
[18] Tsai, J. and Ridge, J. November 1988. Intelligent Support for Specifications Transformation. IEEE Software vol.5(6), p. 34.
[19] Stein, J.
March 1988. Object- oriented Programming and Database Design. Dr. Dobb's Journal of Software Tools for the Professional Programmer, No. 137, p.18.
[20] Peters. Software Design.
[21] Yau, S. and Tsai, J. June 1986. A Survey of Software Design Techniques. IEEE Transactions on Software Engineering vol.SE-12(6).
[22] Teledyne Brown Engineering. Software Methodology Catalog. Report MC87-COMM/ADP-0036. October 1987. Tinton Falls, NJ.
[23] Sommerville, 1.1985. Software Engineering. Second Edition. Workingham, England: Addison-Wesley, p.68.
[24] Yourdon, E. and Constantine, L. 1979. Structured Design. Englewood Cliffs, NJ: Prentice-Hall.
[25] Myers, G. 1978. Composite/Structured Design. New York, NY: Van Nostrand Reinhold.
[26] Page-Jones, M. 1988. The Practical Guide to Structured. Systems Design. Englewood Cliffs. NJ: Yourdon Press.
[27] Wirth, N. January 1983. Program Development by Stepwise Refinement. Communications of the ACM vol.26(1).
[28] Wirth, N. 1986. Algorithms and Data Structures. Englewood Cliffs, NJ: Prentice-Hall.
[29] Dahl, O., Dijkstra, E. and Hoare, C.A.R. 1972. Structured Programming. London. England: Academic Press.
[30] Mills, H., Linger, R. and Hevner, A. 1986. Principles of Information System Design and Analysis. Orlando, FL: Academic Press.
[31] Jackson, M. 1975. Principles of Program Design. Orlando, FL: Academic Press.
[32] Jackson, M. 1983. System Development. Englewood Cliffs, NJ: Prentice-Hall.
[33] Orr, K. 1971. Structured Systems Development. New York, NY: Yourdon Press.
[34| Langdon, G. 1982. Computer Design. San Jose, CA: Computeach Press, p.6.
[35] Miller. Magical Number, p.95.
[36] Shaw, M. 1981. ALPHARD: From and Content. New York, NY: Springer-Verlag, p.6.
[37] Goldberg, A. 1984. Smalltalft-80: The Interactive Programming Environment. Reading, MA: Addison-Wesley, p.80.
[38] Petroski, H. 1985. To Engineerls Human. St Martin's Press: New York, p.40.
[39] Dijkstra, E. January 1993. American Programmer vol.6(1).
[40] Mostow, J.
Spring 1985. Toward Better Models of the Design Process. Al Magazine vol.6(1), p.44.
[41] Stroustrup, В. 1991. The C++ Programming Language. Second Edition. Reading, MA: Addison-Wesley, p.366.
[42] Eastman, N. 1984. Software Engineering and Technology. Technical Directions vol.10(1): Bethesda, MD: IBM Federal Systems Division, p.5.
[43] Brooks. No Silver Bullet, p.10.
Глава 2. Объектная модель
[1] Rentsch, Т. September 1982. Object-Oriented Programming. SIGPLAN Notices vol.17(12), p.51.
[2] Wegner, P. June 1981. The Ada Programming Language and Environment. Unpublished draft.
[3] Abbott, R. August 1987. Knowledge Abstraction. Communications of the ACM vol.30(8), p.664.
[4] Ibid, p.664.
[5] Shankar, K. 1984. Data Design: Types, Structures, and Abstractions. Handbook of Software Engineering. New York, NY: Van Nostrand Reinhold, p.253.
[6] Macintosh MacApp 1.1.1 Programmer's Reference. 1986. Cupertino, CA: Apple Computer, p.2.
[7] Bhaskar, K. October 1983. How Object-oriented Is Your System? SICPLAK Notices vol.18(10), p.8.
[8] Stefik, M. and Bobrow, D. Winter 1986. Object-oriented Programming: Themes and Variations, AI Magazine vol.6(4), p.41.
[9] Yonezawa, A. and Tokoro, M. 1987. ObjecE-Oriented Concurrent Programming. Cambridge, MA: The MIT Press, p.2.
[10] Levy, H. 1984. Capability-Based Computer Systems. Bedford, MA: Digital Press, p.13.
[11] Ramamoorthy, С. and Sheu, P. Fall 1988. Object-oriented Systems. IEEE Expert vol.3(3), p.14.
[12] Myers, G. 1982. Advances in Computer Architecture. Second Edition. New York, NY: John Wiley and Sons, p.58.
[13] Levy. Capability-Based Computer.
[14] Kavi, K. and Chen, D. 1987. Architectural Support for Object-oriented Languages. Proceedings of the Thirty-second IEEE Computer Society International Conference. IEEE.
[15] iAPX432 Object Primer. 1981. Santa Clara, CA: Intel Corporation.
[16] Dally, W.J. and Kajiya.J.T. March 1985. An Object-oriented Architecture, SIGARCH Newsletter vol.13(3).
[17] Dahlby, S., Henry, G., Reynolds, D.
and Taylor, P. 1982. The IBM System/38: A High Level Machine, in Computer Structures: Principles and Examples. New York, NY: McGraw-Hill.
[18] Dijkstra. E. May 1968. The Structure of the "THE" Multiprogramming System. Communications of the ACM vol.11(5).
[19] Pashtan, A. 1982. Object-Oriented Operating Systems: An Emerging Design Methodology. Proceedings of the ACM'S2 Conference. ACM.
[20] Parnas, D. 1979. On the Criteria to the Be Used in Decomposing Systems into Modules, in Classics in Software Engineering. New York, NY: Yourdon Press.
[21] Liskov, B. and Zilles, S. 1977. An Introduction to Formal Specifications of Data Abstractions. Current Trends in Programming Methodology: Software Specification and Design vol.1. Englewood Cliffs. NJ: Prentice-Hall.
[22] Guttag, J. 1980. Abstract Data Types and the Development of Data Structures, in Programming Language Design. New York, NY: Computer Society Press.
[23] Shaw. Abstraction Techniques.
[24] Nygaard, K. and Dahl, O-J. 1981. The Development of the Simula Languages, in History of Programming Languages. New York, NY: Academic Press, p.460.
[25] Atkinson, M. and Buneman, P. June 1987. Types and Persistence in Database Programming Languages. ACM Computing Surveys vol.19(2), p.105.
[26] Rumbaugh, J. April 1988. Relational Database Design Using an Object-oriented Methodology. Communications of the ACM vol.31(4), p.415.
[27] Chen, P. March 1976. The Entity-Relationship Model - Toward a Unified View of Data. ACM Transactions on Database Systems vol.1(1).
[28] Barr,A.and Feigenbaum. E. 1981. The Handbook ofArtificial Intelligence. vol.1.Los Altos, CA: William Kaufmann, p.216.
[29] Stillings, N., Feinstein, M., Garfield.J., Rissland, E., Rosenbaum, D., Weisler. S., Baker-Ward, L. 1987. Cognitive Science: An Introduction. Cambridge, MA: The MIT Press, p.305.
[30] Rand, Ayn. 1979. Introduction to Objectivist Epistemology. New York, NY: New American Library.
[31] Minsky, M. 1986. The Society of Mind. New York, NY: Simon and Schuster.
[32] Jones, A. 1979. The Object Model: A Conceptual Tool for Structuring Software. Operating Systems. New York, NY: Springer-Verlag, p.8.
[33] Stroustrup, В. May 1988. What Is Object-oriented Programming? IEEE Software vol.5(3), p.10.
[34] Cardelli, L. and Wegner, P. On Understanding Types, Data Abstraction, and Polymorphism. December 1985. ACM Computing Surveys vol.17(4). p.481.
[35] DeMarco, T. 1979. Structured Analysis and System Specification. Englewood Cliffs, NJ: Prentice-Hall.
[36] Yourdon, E. 1989. Modem Structured Analysis. Englewood Cliffs, NJ: Prentice-Hall.
[37] Gane, C. and Sarson, T. 1979. Structured Systems Analysis. Englewood Cliffs, NJ: Prentice-Hall.
[38] Ward, P. and Mellor, S. 1985. Structured Development for Real-Time Systems. Englewood Cliffs, NJ: Yourdon Press.
[39] Hatley, D. and Pirbhai, 1.1988. Strategies for Real-Time System Specification. New York, NY: Dorset House.
[40] Jenkins, M. and Glasgow, J. January 1986. Programming Styles in Nial. IEEE Software vol.3(1), p.48.
[41] Bobrow, D. and Stefik, M. February 1986. Perspectives on Artificial Intelligence Programming. Science vol.231, p.951.
[42] Dahl, O., Dijkstra, E. and Hoare, C.A.R. 1972. Structured Programming. London, England: Academic Press, p.83.
[43] Shaw, M. October 1984. Abstraction Techniques in Modern Programming Languages. IEEE Software vol.1(4), p.10.
[44] Berzins, V. Gray, M. and Naumann, D. May 1986. Abstraction-Based Software Development. Communications of the ACM vol. 29(5), p.403.
[45] Abelson, H. and Sussman, G. 1985. Structure and Interpretation of Computer Programs. Cambridge, MA: The MIT Press, p.126.
[46] Ibid, p.132.
[47] Seidewitz, E. and Stark, M. 1986. Towards a General Object-oriented Software Development Methodology. Proceedings of the First International Conference on Ada Programming Language Applications for the NASA Space Station. NASA Lyndon B.Johnson Space Center. TX: NASA, p.D.4.6.4.
[48] Meyer, B. 1988. Object-oriented Software Construction.
New York. NY: Prentice-Hall.
[49] Wirfs-Brock. R. and Wilkerson, B. October 1989. Object-oriented Design: A Responsibility-Driven Approach. SICPLAN Notices vol.24(10).
[50] Ingalls, D. The Smalltalk-76 Programming System Design and Implementation. Proceedings of the Fifth Annual ACM Symposium on Principles of Programming Languages. ACM, p.9.
[51] Gannon.J., Hamlet. R. and Mills. H. July 1987. Theory of Modules. IEEE Transactions on Software Engineering vol.SE-13(7), p.820.
[52] Date, С. 1986. Relational Database: Selected Writings. Reading, MA: Addison-Wesley, p.180.
[53] Liskov, B. May 1988. Data Abstraction and Hierarchy. SIGPLAN Notices vol.23(5). p.19.
[54] Britton, K. and Parnas. D. December 8. 1981. A-7E Softs-are Module Guide. Washington, D.C. Naval Research Laboratory, Report 4702, p.24.
[55] Gabriel, R. 1990. Private Communication.
[56] Stroustrup, B. 1988. Private Communication.
[57] Myers. G. 1978. Composite/Structured Design. New York. NY: Van Nostrand Reinhold, p.21.
[58] Liskov, B. 1980. A Design Methodology for Reliable Software Systems, in Tutorial on Software Design Techniques. Third Edition. New York, NY: IEEE Computer Society, p.66.
[59] Zelkowitz, M. June 1978. Perspectives on Software Engineering. ACM Computing Surveys vol.10(2), p.20.
[60] Parnas, D., Clements, P. and Weiss, D. March 1985. The Modular Structure of Complex Systems. IEEE Transactions on Software Engineering vol.SE-11(3), p.260.
[61] Britton and Parnas. A-7E Software, p.2.
[62] Parnas. D., Clements, P. and Weiss, D. 1983. Enhancing Reusability with Information Hiding. Proceedings of the Workshop on Reusability in Programming. Stratford, CT: ITT Programming. p.241.
[63] Meyer. Object-oriented Software Construction, a. 47.
[64] Сох, В. 1986. Object-Oriented Programming: An Evolutionary Approach. Reading, MA: Addison-Wesley, p.69.
[65] Danforth, S. and Tomlinson. C. March 1988. Type Theories and Object-Oriented Programming. ACM Computing Surveys vol.20(1), p.34.
[66] Liskov. 1988.
р. 23.
[67] As quoted in Liskov. 1980. p.67.
[68] Zilles, S. 1984. Types, Algebras, and Modeling, in On Conceptual Modeling: Perspectives from Artificial Intelligence. Databases, and Programming Languages. New York, NY: Springer-Verlag, p.442.
[69] Doming, A. and Ingalls, D. 1982. A Type Declaration and Inference System for Smalltalk. Palo Alto, CA: Xerox Palo Research Center, p.134.
[70] Wegner. P. October 1987. Dimensions of Object-oriented Language Design. SIGPLAN Notices vol.22(12). p.171.
[71] Stroustrup, B. 1992. Private communication.
[72] Tesler, L. August 1981. The Smalltalk Environment. Byte vol.6(8), p.142.
[73] Borning and Ingalls. Type Declaration, p.133.
[74] Thomas, D. March 1989. What's in an Object? Byte vol.14(3), p.232.
[75] Lim, J. and Johnson, R. April 1989. The Heart of Object-oriented Concurrent Programming. SIGPLAN Notices vol.24(4), p.165.
[76] Ibid, p.l65.
[77] Black, A., Hutchinson, N., Jul, E., Levy, H. and Carter, L. July 1986. Distribution and Abstract Types in Emerald. Report 86-02-04. Seattle, WA: University of Washington, p.3.
[78] Proceedings of the ACM SIGPLAN Workshop on Object-Based Concurrent Programming. April 1989. SIGPLAN Notices vol.24(4), p.1.
[79] Atkinson, M., Bailey, P., Chisholm, K., Cockshott, P. and Morrison, R. 1983. An Approach to Persistent Programming. The Computer Journal vol.26(4), p.360.
[80] Khoshafian, S. and Copeland, G. November 1986. Object Identity. SIGPLAN Notices vol.21(11), p.409.
[81] Vbase Technical Overview. September 1987. Billerica, MA: Ontologic, p.4.
[82] Stroustrup, В. November 1987. Possible Directions for C++. Proceedings of the USENIX C++ Workshop. Santa Fe, NM, p.14.
[83] Meyer. Object-oriented Software Construction, p.30-31.
[84] Robson, D. August 1981. Object-oriented Software Systems, Byte vol.6(8), p.74.
Глава 3. Классы и объекты
[1] Lefrancois, G. 1977. Of Children: An Introduction to Child Development. Second Edition. Belmont, CA: Wadsworth, p.244-246.
[2] Nygaard, K.
and Dahl, O-J. 1981. The Development of the Simula Languages, in History of Programming Languages. New York, NY: Academic Press, p.462.
[3] Halbert, D. and O'Brien, P. September 1988. Using Types and Inheritance in Object-oriented Programming. IEEE Software vol. 4(5), p.73.
[4] Smith, M. and Tockey, S. 1988. An Integrated Approach to Software Requirements Definition Using Objects. Seattle, WA: Boeing Commercial Airplane Support Division, p.132.
[5] Сох, В. 1986. Object-oriented Programming: An Evolutionary Approach. Reading, MA: Addison-Wesley, p.29.
[6] MacLennan, B. December 1982. Values and Objects in Programming Languages. SICPLAN Notices vol.17(12), p.78.
[7] Lippman, S. 1989. C++ Primer. Reading, MA: Addison-Wesley, p.185.
[8] Adams, S. 1993. Private communication.
[9] Wirfs-Brock, R.,Wilkerson, В. and Wiener, L. 1990. Designing Object-oriented Software. Englewood Cliffs, New Jersey: Prentice-Hall, p.61.
[10] Rubin, K. 1993. Private communication.
[11] Macintosh MacApp 1.1.1 Programmer's Reference. 1986. Cupertino. CA: Apple Computer, p.4.
[12] Khoshafian, S. and Copeland, G. November 1986. Object Identity. SIGPLAN Notices vol.21(ll).p.406.
[13] Ingalls, D. 1981. Design Principles behind Smalltalk. Byte vol.6(8), p.290.
[14] Gall, J. 1986. Systemantics: Ноw Systems Really Work and How They Fail. Second. Edition. Ann Arbor, MI: The General Systemantics Press, p.158.
[15] Seidewitz, E. and Stark, M. 1986. Towards a General Object-oriented Software Development Methodology. Proceedings of the First International Conference on Ada Programming Language Applications for the NASA Space Station. NASA Lyndon B. Johnson Space Center. TX: NASA. p.D.4.6.4.
[16] Rumbaugh, J., Blaha, M., Premerlani, W., Eddy, F. and Lorensen, W. 1991. Object-oriented Modeling and Design. Englewood Cliffs, New Jersey: Prentice-Hall, p.459.
[17] Webster's Third New International Dictionary of the English Language, unabridged. 1986. Chicago. Illinois: Merriam-Webster.
[18] Stroustrup, B. 1991.
The C++ Programming Language, Second Edition. Reading, MA: Addison-Wesley, p.422.
[19] Meyer, B. 1987. Programmingas Contracting. Report TR-EI-12/CO. Goleta, CA: Interactive Software Engineering.
[20] Snyder, A. November 1986. Encapsulation and Inheritance in Object-oriented Programming Languages. SIGPLAN Notices vol. 21(11).
[21] LaLonde, W. April 1989. Designing Families of Data Types Using Exemplars. ACM Transactions on Programming Languages and Systems vol.11(2), p.214.
[22] Rumbaugh, J. April 1988. Relational Database Design Using an Object-oriented Methodology. Communications of the ACM vol.31(4), p.417.
[23] Lieberman, H. November 1986. Using Prototypical Objects to Implement Shared Behavior in Object-oriented Systems. SIGPLAN Notices vol.21(11).
[24] Rumbaugh,1991.p.312.
[25] Brachman, R. October 1983. What IS-A Is and Isn't: An Analysis of Taxonomic Links in Semantic Networks. IEEE Computer vol.16(10), p.30.
[26] Micallef, J. April/May 1988. Encapsulation, Reusability, and Extensibility in Object-oriented Programming Languages. Journal of Object-oriented Programming vol.1(1). p.15.
[27] Snyder. Encapsulation, p.39.
[28] Cardelli, L. and Wegner. P. On Understanding Types, Data Abstraction, and Polymorphism. December 1985. ACM Computing Surveys vol.17(4), p.475.
[29] As quoted in Harland, D., Szyplewski, M. and Wainwright, J. October 1985. An Alternative View of Polymorphism. SIGPLAN Notices vol.20( 10).
[30] Kaplan, S. and Johnson, R. July 21,1986. Designing and Implementing/or Reuse. Urbana. IL University of Illinois, Department of Computer Science, p.8.
[31] Deutsch, P. 1983. Efficient Implementation of the Smalltalk-80 System, in Proceedings of the 11th Annual ACM Symposium on the Principles a/Programming Languages, p.300.
[32] Ibid, p.299.
[33] Duff, С. August 1986. Designing an Efficient Language. Byte vol.11(8), p.216.
[34] Stroustrup, В. 1988. Private communication.
[35] Stroustrup, В. November 1987. Possible Directions for C++. Proceedings of the USENIX C++ Workshop.
Santa Fe, New Mexico, p.8.
[36] Keene, S. 1989. Object- Oriented Programming in Common Lisp. Reading, MA: Addison-Wesley, p.44.
[37] Winston. P. and Horn. B. 1989. Lisp. Third Edition. Reading, MA: Addison-Wesley, p.510.
[38] Micallef, J. April/May 1988. Encapsulation. Reusability, and Extensibility in Object-Oriented Programming Languages. Journal of Object-Oriented Programming vol.1 (1), p.25.
[39] Snyder. Encapsulation, p.41.
[40] Vlissides, J. and Linton, M. 1988. Applying Object-oriented Design to Structured Graphics. Proceedings of USENIX C++ Conference. Berkeley, CA: USENIX Association, p.93.
[41] Meyer, В. 1988. Object-oriented Software Construction. New York. NY: Prentice-Hall, p.274.
[42] Keene. Object-oriented Programming, p.118.
[43] Snyder. Encapsulation, p.43.
[44] Hendler, J. October 1986. Enhancement for Multiple Inheritance. SIGPLAN Notice vol.21(10), p.100.
[45] Stroustrup, 1987. p.3.
[46] Stroustrup, В. 1988. Parameterized Types for C++. Proceedings of USENIX C++ Conference. Berkley, CA: USENIX Association, p.1.
[47] Meyer, В. November 1986. Gcnericity versus Inheritance. SIGPLAN Notices vol.21(11), p.402.
[48] Stroustrup. 1988, p.4.
[49] Robson, D. August 1981. Object-oriented Software Systems. Byte vol.6(8), p.86.
[50] Goldberg, A. and Robson, D. 1983. Smalltalk-80: The Language and Its Implementation. Reading, MA: Addison-Wesley, p.287.
[51] Ingalls, D. August 1981. Design Principles Behind Smalltalk. Byte vol.6(8), p.286.
[52] Stevens, W., Myers. G. and Constantine, L. 1979. Structured Design, in Classics in Software Engineering. New York, NY: Yourdon Press, p.209.
[53] Page-Jones, M. 1988. The Practical Guide to Structured Systems Design. Englewood Cliffs, New Jersey: Yourdon Press, p.59.
[54] Meyer. 1987, p.4.
[55] Halbert, D. and O'Brien, P. September 1988. Using Types and Inheritance in Object-oriented Programming. IEEE Software vol.4(5), p.74.
[56] Sakkinen, M. December 1988. Comments on "the Law of Demeter" and C++.
SIGPLAN Notices vol.23(12), p.36.
[57] Lea, D. August 12,1988. User's Guide to GNU C++ Library. Cambridge. MA: Free Software Foudation, p.12.
[58] Ibid.
[59] Meyer. 1988, р. 332.
[60] Wirth, N. 1986. Algorithms and Data Structures. Englewood Cliffs. NJ: Prentice-Hall, p.37.
[61] Keene. Object-oriented Programming, p.68.
[62] Parnas, D., Clements, P. and Weiss, D. 1989. Enhancing Reusability with Information Hiding. Software Reusability. New York, NY: ACM Press, p.143.
Глава 4. Классификация
[1] As quoted in Swaine, M. June 1988. Programming Paradigms. Dr. Dobb's Journal of Software Tools. No.140, p.110.
[2] Michalski, R. and Stepp, R. 1983. Learning from Observation: Conceptual Clustering, in Machine Learning: An Artificial Intelligence Approach. Palo Alto, CA: Tioga. p.332.
[3] Alexander, С. 1979. The Timeless Way of Building. New York, NY: Oxford University Press, p.203.
[4] Darwin, С. 1984. The Origin of Species. vol.49 of Great Books of the Western World. Chicago, IL: Encyclopedia Britannica, p.207.
[5] The New Encyclopedia Britannica. 1985. Chicago, IL Encyclopedia Britannica. vol.3, p.356.
[6] Gould, S. June 1992. We Are All Monkey's Uncles. Natural History.
[7] May, R. September 16,1988. How Many Species Are There on Earth? Science vol.241, p.1441.
[8] As quoted in Lewin, R. November 4,1988. Family Relationships Are a Biological Conundrum. Science vol.242, p.671.
[9] The New Encyclopedia Britannica vol.3, p.156.
[10] Descartes, R. 1984. Rules for the Direction of the Mind. vol.31 of Great Books of the Western World. Chicago, IL: Encyclopedia Britannica, p.32.
[11] Shaw, M. May 1989. Larger Scale Systems Require Higher-Level Abstractions. SIGSOFT Engineering Notes vol.14(3), p.143.
[12] Goldstein, Т. May 1989. The Object-oriented Programmer. The C++ Report vol.1(5).
[13] Coombs, С., Raiffa, H. and Thrall, R. 1954. Some Views on Mathematical Models and Measurement Theory. Psychological Review vol.61(2), p.132.
[14] Flood, R. and Carson, E. 1988.
Dealing with Complexity. New York, NY: Plenum Press, p.8.
[15] Birtwistle, G., Dahl, O-J., Myhrhaug, В. and Nygard, K. 1979. Simula begin. Lund. Sweden: Studentlitteratur, p.23.
[16] Heinlein, R. 1966. The Moon Is a Harsh Mistress. New York, NY: The Berkeley Publishing Group, p.11.
[17] Sowa, J. 1984. Conceptual Structures: Information Processing in Mind and Machine. Reading, MA: Addison-Wesley, p.16.
[18] Lakoff, G. 1987. Women. Fire, and Dangerous Things: What Categories Reveal About the Mind. Chicago, IL: The University of Chicago Press, p.161.
[19] Stepp, R. and Michalski, R. February 1986. Conceptual Clustering of Structured Objects: A Goal-Oriented Approach. Artificial Intelligence vol.28( 1), p.53.
[20] Wegner, P. 1987. The Object-Oriented Classification Paradigm, in Research Directions in Object-Oriented Programming. Cambridge, MA: The MIT Press, p.480.
[21] Aquinas, Т. 1984. Summa Theologica. vol.19 of Great Books of the Western World. Chicago, IL: Encyclopedia Britannica, p.71.
[22] Maier, H. 1969. Three Theories of Child Development: The Contributions of Erik H. Erickson, Jean Piaget and Robert R. Sears, and Their Applications. New York, NY: Harper and Row, p.111.
[23] Lakoff. Women. Fire, p.32.
[24] Minsky, M. 1986. The Society of Mind. New York, NY: Simon and Schuster, p.199.
[25] The Great Ideas: A Syntopicon of Great Books of the Western World. 1984. vol.1 of Great Books of the Western World. Chicago, IL: Encyclopedia Britannica, p.293.
[26] Kosko, В. 1992. Neural Networks and Fuzzy Systems. Englewood Cliffs, NJ: Prentice-Hall, p.xx.
[27] Stepp, p.44.
[28] Lakoff. Women, Fire, and Dangerous Things, p. 7.
[29] Ibid, p.16.
[30] Lakoff, G. and Johnson, M. 1980. Metaphors We Live By. Chicago, IL: The University of Chicago Press, p.122.
[31] Meyer, В. 1988. Private communication.
[32] Shlaer, S. and Mellor, S. 1988. Object-oriented Systems Analysis: Modeling the World in Data. Englewood Cliffs, NJ: Yourdon Press, p.15.
[33] Ross, R. 1987.
Entity Modeling: Techniques and Application. Boston, MA: Database Research Group, p.9.
[34] Coad, P. and Yourdon, E. 1990. Object-oriented Analysis. Englewood Cliffs, NJ: Prentice-Hall, p.62.
[35] Shlaer, S. and Mellor, S. 1992. Object Lifecycles: Modeling the World in States. Englewood Cliffs, New Jersey: Yourdon Press.
[36] Wirfs-Brock, R., Wilkerson, B. and Wiener, L. 1990. Designing Object-oriented Software. Englewood Cliffs, New Jersey: Prentice-Hall, p.61.
[37] Rubin, K. and Goldberg, A. September 1992. Object Behavior Analysis. Communications of the ACM, vol.35(9), p.48.
[38] Dreger, В. 1989. Function Point Analysis. Englewood Cliffs, NJ: Prentice-Hall, p.4.
[39] Arango, G. May 1989. Domain Analysis: From Art Form to Engineering Discipline. SIGSOFT Engineering Notes vol.14(3), p. 153.
[40] Moore, J. and Bailin, S. 1988. Position Paper on Domain Analysis. Laurel, MD: СТА, р. 2.
[41] Jacobson, I., Christerson, M.,Jonsson, P. and Overgaard, G. 1992. Object-oriented Software Engineering. Workingham, England: Addison-Wesley, p.VIII.
[42] Zahniseer, R. July/August 1990. Building Software In Groups. American Programmer, vol.3(7-8).
[43] Goldstein, N. and Alger, J. 1992. Developing Object-oriented Software for the Macintosh. Reading, Massachusetts: Addison-Wesley, p.161.
[44] Beck, K. and Cunningham, W. October 1989. A Laboratory for Teaching Object-oriented Thinking. SIGPLAN Notices vol. 24(10).
[45] Abbott, R. November 1983. Program Design by Informal English Descriptions. Communications of the ACM vol.26(11).
[46] Saeki, M., Horai, H. and Enomoto, H. May 1989. Software Development Process from Natural Language Specification. Proceedings of the 11th International Conference on Software Engineering. New York, NY: Computer Society Press of the IEEE.
[47] McMenamin, S. and Palmer, J. 1984. Essential Systems Analysis. New York, NY: Yourdon Press, p.267.
[48] Ward, P. and Mellor, S. 1985. Structured Development for Real-time Systems. Englewood Cliffs, NJ: Yourdon Press.
[49] Seidewitz, E. and Stark, M. August 1986. General Object-oriented Software Development, Report SEL-86-002. Greenbelt, MD: NASA Goddard Space Flight Center, p.5-2.
[50] Seidewitz, E. 1990. Private Communication.
[51] Goldberg, A. 1984. Smalltalk-80: The Interactive Programming Environment. Reading, MA: Addison-Wesley, p.77.
[52] Thomas, D. May/June 1989. In Search of an Object-oriented Development Process. Journal of Object-Oriented Programming vol.2(1), p.61.
[53] Stroustrup, В. 1986. The C++ Programming Language. Reading, MA: Addison-Wesley, p.7.
[54] Halbert, D. and O'Brien, P. September 1988. Using Types and Inheritance in Object-oriented Programming. IEEE Software vol.4(5), p.75.
[55] Stefik, M. and Bobrow, D. Winter 1986. Object-oriented Programming: Themes and Variations, Al Magazine vol.6(4), p.60.
[56] Stroustrup, В. 1991. The C++ Programming Language, Second Edition. Reading, Massachusetts: Addison-Wesley, p.377.
[57] Stefik and Bobrow. Object-oriented Programming, p.58.
[58] Lins, С. 1989. A First Look at Literate Programming. Structured Programming.
[59] Gabriel, R. 1990. Private communication.
[60] Coplien, J. 1992. Advanced C++ Programming Styles and Idioms. Reading, Massachusetts: Addison-Wesley.
[61] Adams, S.July 1986. MetaMethods: The MVC Paradigm, in HOOPLA: Hooray for Object-oriented Programming Languages. Everette, WA: Object-oriented Programming for Smalltalk Applications Developers Association vol.1(4), p.6.
[62] Russo, V., Johnston, G. and Campbell, R. September 1988. Process Management and Exception Handling in Multiprocessor Operating Systems Using Object-oriented Design Techniques. SIGPLAN Notices vol.23(11), p.249.
[63] Englemore, R. and Morgan, Т. 1988. Blackboard Systems. Wokingham, England: Addison-Wesley, p.v.
[64] Coad, P. September 1992. Object-oriented Patterns. Communications of the ACM, vol.35(9).
Часть II. Метод
Petroski, H. 1985. То Engineer is Human. New York, NY: St Martin's Press, p.73.
Глава 5. Обозначения
[1] Shear, D. December 8, 1988. CASE Shows Promise, but Confusion Still Exists. EDN vol.33(25), p.168.
[2] Whitehead, A. 1958. An Introduction to Mathematics. New York, NY: Oxford University Press.
[3] Defense Science Board. Report of the Defense Science Board Task Force on Military Software. September 1987. Washington, D.C.: Office of the Undersecretary of Defense for Acquisition, p.8.
[4] Kleyn, M. and Gingrich, P. September 1988. GraphTrace - Understanding Object-Oriented Systems Using Concurrently Animated Views. SIGPLAN Notices vol.23(11), p.192.
[5] Weinberg, G. 1988. Rethinking Systems Analysis and Design. New York, NY: Dorset House, p.157.
[6] Intel. 1981. iAPX432 Object Primer. Santa Clara. CA.
[7] Rumbaugh, J., Blaha, M., Premerlani, W., Eddy, F. and Lorensen, W. 1991. Object-oriented Modeling and Design. Englewood Cliffs, New Jersey: Prentice-Hall.
[8] Stroustrup, B. 1991. The C++ Programming Language. Second Edition. Reading, Massachusetts: Addison-Wesley Publishing Company.
[9] Kiczales, G., Rivieres, J. and Bobrow, D. 1991. The Art of the Metaobject Protocol. Cambridge, Massachusetts: The MIT Press.
[10] Gamma, E., Helm, R., Johnson, R., Vlissides, J. 1993. A Catalog of Object-oriented Design Patterns. Cupertino, California: Taligent.
[11] Harel, D. 1987. Statecharts: A Visual Formalism for Complex Systems. Science of Computer Programming vol.8.
[12] Rumbaugh, Object-oriented Modeling and Design.
[13] Bear, S., Alien, P., Coleman, D. and Hayes, F. Graphical Specification of Object-oriented Systems. Object-oriented Programming Systems, Languages, and Applications. Ottawa, Canada: OOPSLA'90.
[14] Rumbaugh, Object-oriented Modeling and Design.
[15] Jacobson, I., Christerson, M., Johnson, P. and Overgaard, G. 1992. Object-oriented Software Engineering. Workingham, England: Addison-Wesley Publishing Company.
Глава 6. Процесс
[1] Brooks, F. 1975. The Mythical Man-Month. Reading, MA: Addison-Wesley, p.42.
[2] Stroustrup, В. 1991. The C++ Programming Language, Second Edition.
Reading, MA: Addison-Wesley.
[3] Maccoby, M. December 1991. The Innovative Mind at Work. IEEE Spectrum, vol.28(12).
[4] Lammers, S. 1986. Programmers at Work. Redmond, WA: Microsoft Press.
[5] Druke, M. 1989. Private Communication.
[6] Jones, C. September 1984. Reusability in Programming: A Survey of the State of the Art. IEEE transactions on Software Engineering, vol.SE-10(5).
[7] Humphrey, W. 1989. Managing the Software Process. Reading, MA: Addison-Wesley, p.5.
[8] Curtis, В. May 17, 1989. ...But You Have to Understand, This Isn't the Way We Develop Software at Our Company. MCC Technical Report Number STP-203-89. Austin, TX: Microelectronics and Computer Technology Corporation, p.x.
[9] Parnas, D. and Clements, P. 1986. A Rational Design Process: How and Why to Fake It. IEEE Transactions on Software Engineering vol.SE-12(2).
[10] Boehm, B. August 1986. A Spiral Model of Software Development and Enhancement. Software Engineering Notes vol.11(4), p.22.
[11] Stroustrup, B. 1991. The C++ Programming Language, Second Edition. Reading, MA: Addison-Wesley, p.362.
[12] Brownsword, L 1989. Private communication.
[13] Stroustrup, p.373.
[14] Vonk, R. 1990. Prototyping. Englewood Cliffs, NJ: Prentice-Hall, p.31.
[15] Gilb, Т. 1988. Principles of Software Engineering Management. Reading, MA: Addison-Wesley, p.92.
[16] Mellor, S., Hecht, A., Tryon, D. and Hywari, W. September 1988. Object-oriented Analysis: Theory and Practice, Course Notes, in Object-oriented Programming Systems, Languages, and Applications. San Diego, CA: OOPSLA'88, p.1.3.
[17] Symons, С. 1988. Function Point Analysis: Difficulties and Improvements. IEEE Transactions on Software Engineering vol.14(1).
[18] Dreger, B. 1989. Function Point Analysis. Englewood Cliffs, NJ: Prentice-Hall, p.5.
[19] deChampeaux, D., Balzer, В., Bulman, D., Culver-Lozo, K., Jacobson, I., Mellor, S. The Object-oriented Software Development Process. Vancouver, Canada: OOPSLA'92.
[20] Davis, A. 1990. Software Requirements: Analysis and Specification.
Englewood Cliffs, NJ: Prentice-Hall.
[21] Rubin, K. 1993. Private communication.
[22] Jacobson, I., Christerson, M., Jonsson, P., and Overgaard, G. 1992. Object- oriented Software Engineering. Workingham, England: Addison-Wesley Publishing Company.
[23] Rubin, K. and Goldberg, A. September 1992. Object Behavior Analysis. Communications of the ACM vol.35(9).
[24] Andert, G. 1992. Private communication.
[25] Page-Jones, M. 1988. The Practical Guide to Structured Systems Design. Englewood Cliffs, NJ: Yourdon Press, pp.261-265.
[26] Stefik, M. and Bobrow, D. Winter 1986. Object-oriented Programming: Themes and Variations, AI Magazine vol.6(4), p.41.
[27] Меуеr, В. 1988. Object-oriented Software Construction. New York, NY: Prentice-Hall, p.340.
[28] Andert, G. 1993. Private communication.
[29] Walsh, J. Preliminary Defect Data from the Iterative Development of a Large C++ Program. Vancouver. Canada: OOPSLA'92.
[30] Chmura, L., Norcio, A. and Wicinski, T. July 1990. Evaluating Software Design Processes by Analyzing Change Date Over Time. IEEE Transactions on Software Engineering vol.16(7).
[31] As quoted in Sommerville, I. 1989. Software Engineering. Third Edition. Wokingham, England: Addison-Wesley, p.546.
Глава 7. Практические вопросы
[1] Dijkstra, E. May 1986. The Structure of the "THE" Multiprogramming System. Communications of the ACM vol.11(5), p.341.
[2] Kishida, K., Teramoto, M., Torri, K. and Urano, Y. September 1988. Quality Assurance Technology in Japan. IEEE Software vol.4(5), p.13.
[3] Hawryszkiewycz, 1.1984. Database Analysis and Design. Chicago, IL: Science Reserch Associates, p.115.
[4] van Genuchten, M. June 1991. Why is Software Late? An Empirical Study of Reasons for Delay in Software Development. IEEE Transactions on Software Engineering vol.17(6), p.589.
[5] Gilb, Т. 1988. Principles of Software Engineering Management. Reading, Massachusetts: Addison-Wesley Publishing Company, p.73.
[6] As quoted in Zelkowitz, M. June 1978.
Perspectives on Software Engineering. ACM Computing Surveys vol.10(2), p.204.
[7] Showalter, J. 1989. Private communication.
[8] Davis, A., Bersoff, E. and Comer, E. October 1988. A Strategy for Comparing Alternative Software Develpopment Lite Cycle Models. IEEE Transactions on Software Engineering vol.14(10), p.1456.
[9] Goldberg, A. 1993. Private communication.
[10] Schulmer, G. and McManus, J. 1992. Handbook of Software Quality Assurance, second Edition. New York, NY: Van Nostrand Reinhold, p.5.
[11] Schulmeyer, p.7.
[12] Schulmeyer, p.184.
[13] Schulmeyer, p.169.
[14] Walsh, J. Preliminary Defect Data from the Iterative Development of a Large C++ Program. Vancouver, Canada: OOPSLA'92.
[15] Chidamber, S. and Kemerer, C. 1993. A Metrics Suite for Object-Oriented Design. Cambridg, Massachusetts: MIT Sloan School of Management.
[16] Lang, K. and Peralmutter, B. November 1986. Oaklisp: an Object-oriented Scheme with First-Class Types. SIGPLAN Notices vol.21(11), p.34.
[17] Meyrowitz, N. November 1986. Intermedia: The Architecture and Construction of an Object-oriented Hypermedia System and Applications Framework. SIGPLAN Notices, vol.21(11), p.200.
[18] Kempf, R. October 1987. Teaching Object-oriented Programming With the KEE System. SIGPLAN Notices, vol.22( 12), p.11.
[19] Schmucker, K. 1986. Object-oriented Programming for the Macintosh. Hasbrouk Heights, NJ: Hayden, p.11.
[20] Taylor, D. 1992. Object-oriented Information Systems. New York, New York John Wiley and Sons.
[21] Pinson, L. and Wiener, R. 1990. Applications of Object-oriented Programming. Reading, Massachusetts: Addison-Wesley Publishing Company.
[22] Simonian, R. and Crone, M. November/December 1988. InnovAda: True Object-Oriented Programming in Ada. Journal of Object-Oriented Programming vol.1(4), p.19.
[23] Pascoe, G. August 1986. Elements of Object-oriented Programming. Byte vol.11(8), p.144.
[24] Russo, V. and Kaplan, S. 1988. А C++ Interpreter for Scheme. Proceedings of USENIX C++ Conference.
Berkeley, CA: USENIX Association, p.106.
Часть III. Примеры приложений
Minsky, M. April 1970. Form and Content in Computer Science. Journal of the Association for Computing Machinery vol.17(2), p.197.
Глава 9. Среда разработки: библиотека базовых классов
[1] C++ Booch Components Class Catalog. 1992. Santa Clara, CA: Rational.
[2] Knuth, D. 1973. The Art of Computer Programming, Vol.1-3. Reading, MA: Addison-Wesley.
[3] Aho, A., Hopcroft, J. and Ullman, J. 1974. The Design and Analysis of Computer Programs. Reading, MA: Addison-Wesley.
[4] Kernighan, B. and Plauger, P. 1981. Software Tools in Pascal. Reading, MA: Addison-Wesley.
[5] Sedgewick, R. 1983. Algorithms. Reading, MA: Addison-Wesley.
[6] Stubbs, D. and Webre, N. 1985. Data Structures with Abstract Data Types and Pascal. CA: Brooks/Cole.
[7] Tenenbaum, A. and Augenstein, M. 1981. Data Structures Using Pascal. Englewood Cliffs, NJ: Prentice-Hall.
[8] Wirth, N. 1986. Algorithms and Data Structures, Second Edition. Englewood Cliffs, NJ: Prentice-Hall.
[9] Wirfs-Brock, R. October 1991. Object-Oriented Frameworks. American Programmer vol.4(10), p.27.
[10] Stroustrup, Bjarne. 1991. The C++ Programming Language, Second Edition. Reading, Massachusetts: Addison-Wesley, p.429.
[11] Coggins, J. September 1990. Design and Management of C++ Libraries. Chapel Hill, North Carolina, p.1.
[12] Ellis, M. and Stroustrup, B. 1990. The Annotated C++ Reference Manual. Reading, Massachusetts: Addison-Wesley, p.155.
[13] Ellis and Stroustrup, p.297.
[14] Ellis and Stroustrup, p.90.
[15] Wirfs-Brock, 1993. Private communication.
[16] Jacobson, I., Christerson, M.,Jonsson, P. and Overgaard, G. 1992. Object-oriented Software Engineering. Workingham, England: Addison-Wesley Publishing Company, p.184.
Глава 10. Архитектура клиент-сервер: складской учет
[1] Mirnno, P. April 1993. Client-Server Computing. American Programmer, Arlington MA: Cutter Information Corporation, p.19.
[2] Mimno, p.21.
[3] Berson, A. 1992. Client/Server Architecture.
New York, NY: Me Graw-Hill, p.34.
[4] Berson, p.37.
[5] Berson, p.12.
[6] Berson, p.13.
[7] Date, С. 1981. An Introduction to Database Systems. Vol.1. Reading, Massachusetts: Addison-Wesley, p.4.
[8] Date. An Introduction, p.10.
[9] Hawryszkiewycz, 1.1984. Database Analysis and Design. Chicago, IL: Science Research Associates, p.425.
[10] Wiorkowski, G. and Kull, D. 1988. DB2 Design and Development Guide. Reading, MA: Addison-Wesley, p.29.
[11] Date. An Introduction, p.63.
[12] Wiorkowski and Kull. DB2 Design, p.2.
[13] Date. An Introduction, p.238.
[14] Wiorkowski and Kull. DB2 Design, p.15.
[15] Date, С. 1986. Relational Database: Selected Writings. Reading, MA: Addison-Wesley, p.461.
[16] Rumbaugh, J. July/August 1992. Onward to OOPSLA. Journal of Object-Oriented Programming, vol.5(4).
[17] Rumbaugh, J., Blaha, M., Premerlani, W., Eddy, F. and Lorensen, W. 1991. Object-oriented Modeling and Design. Englewood Cliffs, New Jersey: Prentice-Hall, p.386.
[18] Ibid.
[19] Date. An Introduction, p.237.
[20] Berson, p.39.
[21] Berson, p.441.
[22] Date, С. 1987. The Guide to the SQL Standard. Reading, MA: Addison-Wesley, p.32.
[23] Berson, p.244.
[24] Berson, p.61.
[25] Ibid.
Глава 11. Искусственный интеллект: криптоанализ
[1] Erman, L., Lark, J. and Hayes-Roth, F. December 1998. ABE: An Environment for Engineering Intelligent Systems. IEEE Transactions on Software Engineering vol.14(12), p.1758.
[2] Shaw, M. 1991. Heterogeneous Design Idioms for Software Architecture. Pittsburgh, Pennsylvania: Carnegie Mellon University.
[3] Meyer, C. and Matyas. 1982. Cryptography. New York, NY: John Wiley and Sons, p.1.
[4] Nii, P. Summer 1986. Blackboard Systems: The Blackboard Model of Problem Solving and the Evolution of Blackboard Architectures. AI Magazine vol.7(2), p.46.
[5] Englemore, R. and Morgan, T. 1988. Blackboard Systems. Wokingham, England: Addison-Wesley, p.16.
[6] Ibid, p.19.
[7] Ibid, p.6.
[8] Ibid, p.12.
[9] Nii. Blackboard Systems, p.43.
[10] Englemore and Morgan. Blackboard Systems, p. 11.
Глава 12. Управление: контроль за движением поездов
[1] Murphy, E. December 1988. All Aboard for Solid State. IEEE Spectrum vol.25(13), p.42.
[2] Rockwell Advanced Railroad Electronic Systems. 1989. Cedar Rapids, IA: Rockwell International.
[3] Tanenbaum, A. 1981. Computer Networks. Englewood Cliffs, NJ: Prentice-Hall.
Послесловие
Lefrancois, G. 1977. Of Children: An Introduction to Child Development, Second Edition. Belmont, CA:Wadsworth, p.371.
Приложение: Объектно-ориентированные языки программирования
[1] Wulf, W. January 1980. Trends in the Design and Implementation of Languages. IEEE Computer vol.13(1), p.15.
[2] Birtwistle, G., Dahl, O-J., Myhrhaug, В. and Nygard, K. 1979. Simula begin. Lund, Sweden: Studentlitteratur.
[3] Schmucker, K. 1986. Object-oriented Programming for the Macintosh. Hasbrouk Heights, NJ: Hayden, p.346.
[4] LaLonde, W. and Pugh, J. 1990. Inside Smalltalk, Volumes 1 and 2. Englewood Cliffs, New Jersey: Prentice-Hall.
[5] Ingalls, D. The Smalltalk-76 Programming System Design and Implementation. Proceedings of the Fifth Annual ACM Symposium on Principles of Programming Languages, ACM, p.9.
[6] Borning, A. and Ingalls, D. 1982. Multiple Inheritance in Smalltalk-80. Proceedings of the National Conference on Artificial Intelligence. Meno Park, CA: AAAI.
[7] Goldberg, A. and Robson, D. 1989. Smalltalk-80: The Language. Reading, MA: Addison-Wesley.
[8] Goldberg, A. 1984. Smalltalk-80: The Interactive Programming Environment. Reading, MA: Addison-Wesley.
[9] Krasner, G. 1983. Smalltalk-80: Bits of History. Words of Advice. Reading, MA: Addison-Wesley.
[10] LaLonde, 1990.
[11] Schmucker, K. August 1986. Object-Oriented Languages for the Macintosh. Byte vol.11 (8), р. 179.
[12] Macintosh Programmer's Workshop Pascal 3.0 Reference. 1989. Cupertino, CA: Apple Computer.
[13] Stroustrup, B. 1986. The C++ Programming Language, Second Edition. Reading, MA: Addison-Wesley, p.4.
[14] Gorlen, K. 1989.
An Introduction to C++, in UNIX System VAT&T C++ Language System, Release 2. 0 Selected Readings. Murray Hill, NJ: AT&T Bell Laboratories, p.2-1.
[15] Ellis, M. and Stroustrup, B. 1990. The Annotated C++ Reference Manual. Reading, Massachusetts: Addison-Wesley Publishing Company.
[16] Stroustrup, B. 1991. The C++ Programming Language, Second Edition. Reading, MA: Addison-Wesley.
[17] Keene, S. 1989. Object-oriented Programming in Common Lisp. Reading, MA: Addison-Wesley, p.215.
[18] Bobrow, D. 1990. Private communication.
[19] Bobrow, D., DeMichiel, L., Gabriel, R., Keene, S., Kiczales, G. and Moon, D. September 1988. Common Lisp Object System Specification X3J13 Document 88-002R. SIGPLAN Notices vol.23.
[20] Reference Manual for the Ada Programming Language. February 1983. Washington, D.C.: Department of Defence, Ada Joint Program Office, p.1-3.
[21] Ibid.
[22] Meyer, B. 1988. Object-oriented Software Construction. New York, NY: Prentice-Hall.
[23] Saunders, J. March/April 1989. A Survey of Object-oriented Programming Languages. Journal of Object-oriented Programming vol.1(6).
[24] Ibid, p.6.