Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Буч Г. - Объектно-ориентированный анализ и проектирование с примерами приложений на C++ - 2001

.pdf
Скачиваний:
1500
Добавлен:
13.08.2013
Размер:
5.88 Mб
Скачать

setQuantity

setLocation

setSupplier

productID

description

quantity

location

supplier

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

Скоропортящиеся продукты, требующие определенного режима хранения.

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

Комплектные товары, которые поставляются в определенных сочетаниях (например, радиопередатчики и приемники) и поэтому взаимозависимы.

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

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

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

Рис. 10-7. Классы товаров

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

Механизм транзакций

Архитектура клиент/сервер построена на взаимодействии клиентской и серверной частей приложения, для реализации которого необходим

определенный механизм. Берсон указал, что "существует три базовых вида взаимодействия между процессами в архитектуре клиент/сервер" [20]:

конвейеры (pipes)

удаленный вызов процедур (RPC)

взаимодействие клиент/сервер через SQL.

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

Мы ранее уже упомянули о классе транзакции, но не остановились подробно на его семантике. Берсон определяет транзакцию как "единицу обмена и обработки информации между локальной и удаленной программами, которая отражает логически законченную операцию или результат" [21]. Это и есть определение нужной нам абстракции: объект-транзакция является агентом, ответственным за выполнение некоторого удаленного действия, а, следовательно, отчетливо отделяет само действие от механизма его реализации.

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

С внешней стороны можно выделить следующие операции, описывающие суть поведения в проектируемой системе:

attachOperation

dispatch

commit

rollback

status

Для каждой транзакции определяется полный перечень операций, которые она должна выполнить. Это означает, что для класса Transact ion необходимо определить функции-члены, такие как attachoperation, которые предоставляют другим объектам возможность объединить набор SQLоператоров для исполнения в качестве единой транзакции.

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

Концепция атомарности наиболее существенна в семантике транзакций. Если в некоторой транзакции операция выполняется над несколькими строками таблицы, то либо все действия должны быть выполнены, либо содержимое таблицы должно быть оставлено без изменении. Следовательно, когда мы посылаем транзакцию (dispatch), мы имеем в виду выполнение группы операций как единого целого.

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

Выполнение транзакции несколько усложняется при работе с распределенными базами данных. Как реализовать протокол завершения транзакций при работе с локальной базой достаточно понятно, а что необходимо сделать при работе с данными, размещенными на нескольких серверах? Для этого используется так называемый двухфазный протокол завершения транзакций [23]. В этом случае агент, то есть объект класса Transaction, разделяет транзакцию на несколько фрагментов и раздает их для выполнения различным серверам. Это называется фазой подготовки. Когда все серверы сообщили о том, что готовы к завершению, центральный агент транзакции передает им всем команду commit. Это называется фазой завершения. Только при правильном завершении всех разделенных компонент транзакции основная транзакция считается завершенной. Если хотя бы на одном сервере выполнение операций будет неполным, мы откатим всю транзакцию. Это возможно потому, что каждый экземпляр Transaction знает, как откатить свою транзакцию.

Рис. 10-8. Транзакции

Изложенное выше представление о классе транзакций показано на рис. 10-8. Мы видим здесь иерархию транзакций. Класс Transaction является базовым для всех транзакций и содержит в себе все ключевые аспекты поведения. Производные специализированные классы вносят в общее поведение свои особенности. Мы различаем, например, классы

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

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

Во всяком случае, существование базового класса Transaction позволяет выполнять нам любое атомарное действие. Например, на C++ он мог бы выглядеть так:

public:

Transaction(};

virtual ~Transact ion (); virtual void set0peration(const

UnboundedCollection<SQLStatement>&); virtual int dispatch();

virtual void commit(); virtual void rollbackO; virtual int status{) const; protected:

...

};

Обратим внимание, что для построения этого класса мы использовали базовые классы, определенные нами в главе 9. В данном случае мы построили транзакцию в форме индексированной коллекции операторов. Для манипулирования этой коллекцией использован параметризованный класс

UnboundedCollection.

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

Создание клиентской части приложения

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

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

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

Второй вопрос находится в сфере стратегии проекта, но для его успешного разрешения у нас имеется множество хороших примеров. Существуют коммерческие продукты, например, Х Window System от MIT, Open Look, Windows от Microsoft, MacApp от Apple, NextStep от Next, Presentation Manager от IBM. Все эти продукты существенно различаются: некоторые основываются на сети, а некоторые опираются на концепцию ядра, некоторые позволяют действовать на уровне пикселей, а другие считают примитивами более сложные геометрические фигуры. В любом случае все они позволяют существенно упростить создание графического интерфейса пользователя. Ни один из перечисленных продуктов не родился за одну ночь. Все они постепенно развивались из самых простых систем, прошли путь проб и ошибок. В результате эти системы вобрали в себя набор абстракций, достаточный для построения пользовательского интерфейса. Поскольку нет однозначного ответа на вопрос о лучшем интерфейсе, то существуют несколько вариантов оконной модели.

В главе 9 мы уже упоминали о том, что при работе с большими библиотеками классов (каковыми являются и библиотеки графического интерфейса) важно понять механизмы их построения. Для нашей задачи основным механизмом является реакция GUI-приложений на события. Берсон указывал, что для клиентской части приложения существенны события, связанные со следующими объектами [24]:

• мышь

клавиатура

меню

обновление окна

изменения размера окна

активизация/деактивация

начало/завершение.

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

Берсон обратил внимание на наличие нескольких альтернативных моделей обработки событий [25]:

• Цикл обработки событий В цикле просматривается очередь событии и для каждого события вызывается соответствующая процедура обработки.

• Обратный вызов

Приложение регистрирует функцию

обратного вызова для каждого элемента GUI; обратный вызов происходит,

когда элемент зарегистрирует событие.

• Гибридная модель

Сочетание циклического опроса и функций

обратного вызова.

 

Изрядно упрощая, можно утверждать, что в интерфейсе MacApp используется цикл, в Motif - функции обратного вызова, a Microsoft Windows является примером гибридной модели.

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

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

10.3. Эволюция

Управление релизами

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

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

Модификация или удаление данных о клиентах; модификация или удаление данных о продуктах: модификация заказа; запросы о клиентах, заказах и продуктах.

Интеграция всех похожих транзакции, связанных с поставщиками: создание заказа и выписка счета.

Интеграция всех оставшихся транзакций, связанных со складом: составление отчетов и выписка расходных накладных.

Интеграция всех оставшихся транзакций, связанных с бухгалтерией: поступление оплаты.

Интеграция всех оставшихся транзакции, связанных с отгрузкой.

Интеграция всех оставшихся транзакций, связанных с планированием.

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

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

Генераторы приложений

При создании приложений типа системы складского учета необходимо произвести множество экранных форм и отчетов. Для больших систем эта работа не столько сложна, сколько велика по объему и однообразна. По этой причине сегодня весьма популярны генераторы приложений на основе языков четвертого поколения (4GL). Использование этих языков не противоречит идеям объектно-ориентированного проектирования. Напротив, 4GL-ЯЗЫКИ позволяют при правильном применении существенно упростить написание кода.

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

Такой подход позволяет нам воспользоваться преимуществами 4GL, сохраняя иллюзию полностью объектно-ориентированной архитектуры. Кроме того, языки четвертого поколения сами подвергаются сильному влиянию технологии объект-но-ориентированного программирования и включают в себя прикладные интер-фейсы (API) для объектноориентированных языков типа C++.

Такую же стратегию можно использовать и при реализации диалога пользо-вателя с системой. Написание программ для модального и немодального диалог скучно, поскольку мы должны охватить массу мелких деталей. Лучше не писать такой код вручную 38, а использовать GUIконструкторы, позволяющие "рисовать окна диалога. После получения готового кода мы заворачиваем его в объектную оболочку, включаем в наше приложение и получаем систему с четким разделением обязанностей.

10.4. Сопровождение

Системы клиент/сервер редко бывают окончательно завершенными. Не то чтоб мы никогда не могли сказать про систему, что она уже стабильна.

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

Можно указать некоторые направления модернизации, которые вероятны для системы складского учета:

• Предоставить возможность клиентам работать с системой по каналам

связи.

Автоматически генерировать индивидуальные каталоги товаров для потре-бительских групп или даже отдельных клиентов.

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

Анализ показывает, что все перечисленные модификации связаны скорее с со циалъным и политическим риском, чем с техническим. Гибкая объектно-ориенти-рованная архитектура системы позволяет заказчику использовать все степени сво-боды, чтобы адаптироваться к постоянно меняющемуся рынку.

Дополнительная литература

Об архитектуре клиент/сервер написано больше, чем большинство смертных способно прочесть за всю жизнь. Две наиболее полезные ссылки - это Девайр (Dewire) [H 1992] и Берсон (Berson) [H 1992], которые предложили исчерпывающие и хорошо читаемые обзоры по всему спектру проблем технологии клиент/сервер. Блум (Bloom) [H 1993] дал короткое, но интересное перечисление базовых понятий и проблем архитектуры клиент/сервер.

Децентрализация - это не то же самое, что вычисления в архитектуре клиент/сервер, хотя она и предусматривает вычисления в архитектуре клиент/сервер в корпоративных информационно-управляющих системах. Все мотивировки за и против децентрализации можно найти в работе Гвенджерича

(Guengerich) [H 1992].

Исчерпывающее обсуждение технологии реляционных баз данных можно найти у Дэйта (Date) [Е 1981,1983,1986]. Вдобавок к этому, Дэйт (Date) [E 1987] предложил описание стандарта SQL. Разные подходы к анализу данных могут быть найдены у Вериярда (Veryarcl) [В 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].

Глава 11

Искусственный интеллект: криптоанализ

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

Эти и подобные им проблемы привлекают внимание исследователей в области искусственного интеллекта, которые стремятся улучшить наши представления о разуме человека. В частности, создаются интеллектуальные системы, которые подражают некоторым аспектам поведения человека. Ерман, Ларк и Хайес-Рот указывали, что "интеллектуальные системы отличаются от традиционных рядом признаков (не все из них обяэательны):

способностью достигать целей, меняющихся во времени;

способностью усваивать, использовать и преобразовывать знания;

способностью оперировать с разнообразными подсистемами, варьируя используемые методы;

интеллектуальным взаимодействием с пользователями и другими системами;

самостоятельным распределением ресурсов и концентрацией внимания" [1 ]. Реализация в системе хотя бы одного из этих требований уже является непростой задачей. Еще сложнее сделать интеллектуальную систему для использования в некоторых специфических прикладных областях, например, в медицинской диагностике и диспетчеризации авиарейсов: такие системы должны, как минимум, не причинять вреда, а искусственный интеллект практически ничего не знает о здравом смысле. Успехи энтузиастов в этой области несколько преувеличены; но, тем не менее, искусственный интеллект дал немало хороших практических идей, в частности представление знаний, концепция информационной доски и экспертные системы [2]. В данной главе рассматриваются подходы к созданию интеллектуальной системы расшифровки криптограмм на основе метода информационной доски, в достаточной степени моделирующего человеческий способ решения задачи. Как мы увидим, методы объектно-ориентированного проектирования очень хорошо работают в этой области.

11.1. Анализ

Определение границ предметной области

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

В качестве первого шага анализа попробуйте решить (только честно, не заглядывая вперед!) следующую криптограмму записывая, каждый ваш шаг:

Q AZWS DSSC KAS DXZNN DASNN

Подсказка: буква w соответствует букве v исходного текста. Перебор всех возможных вариантов совершенно лишен смысла. Предполагая, что алфавит содержит 26 прописных английских букв, получим 26! (около 4.03х1026) возможных комбинаций. Следовательно, нужно искать другой метод решения, например, использовать знания о структуре слов и предложений и делать правдоподобные допущения. Как только мы исчерпаем явные решения, мы сделаем наиболее вероятное предположение и будем продвигаться дальше. Если обнаружится, что предположение приводит к противоречию или заводит в тупик, мы вернемся назад и сделаем другую попытку.

Вот наше решение, шаг за шагом:

1. Используя подсказку, заменим w на v.

Требования к системе криптоанализа

Криптография "изучает методы сокрытия данных от посторонних" [З]. Криптографические алгоритмы преобразовывают сообщения (исходный текст) в зашифрованный текст (криптограмму) и наоборот.

Одним из наиболее общеупотребительных (еще со времен Древнего Рима) криптографических алгоритмов является подстановка. Каждая буква в алфавите исходного текста заменяется другой буквой. Например, можно циклически сдвинуть все буквы алфавита: буква А заменяется на B, B на C, a Z на А. Тогда следующий исходный текст:

CLOS is an object-oriented programming language

превращается в криптограмму:

DMPT jt bo pckfdu-psjfoufe qsphsbnnjoh mbohvbhf

Чаще всего замена делается менее тривиальным образом. Например, А заменяется на G, B на J и т. д. Рассмотрим следующую криптограмму:

PDG TBCER CQ ТСК AL S NGELCH QZBBR SBAJG

Подсказка: буква C в этой криптограмме соответствует букве O исходного текста.

Существенно упрощает задачу предположение о том, что для шифрования текста использован алгоритм подстановки, поскольку в общем случае процесс дешифровки не будет столь тривиальным. В процессе расшифровки приходится использовать метод проб и ошибок, когда мы делаем предположение о замене и рассматриваем его следствия. Удобно, например, начать расшифровку с предположения о том, что одно- и двухбуквенные слова в криптограмме соответствуют наиболее употребительным словам английского языка (I, a, or, it, in, of. on). Подставляя эти предполагаемые буквы в другие слова, мы можем догадаться о вероятном значении других букв. Например, если трехбуквенное слово начинается с литеры O, то это могут быть слова one,our, off.

Знание фонетики и грамматики также может способствовать дешифровке. Например, следование подряд двух одинаковых литер с очень малой вероятностью может означать qq. Наличие в окончании слова буквы g позволяет сделать предположение о наличии суффикса ing. На еще более высоком уровне абстракции логично предположить, что словосочетание it ia более вероятно, чем if is. Необходимо учитывать и структуру предложения: существительные и глаголы. Если выясняется, что в предложении есть глагол, но нет существительного, которое с ним связано, то нужно отвергнуть сделанные ранее предположения н начать поиск заново.

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

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

Q AZVS DSSC KAS DXZNN DASNN

2. Первое слово из одной буквы, вероятна, А или I; предположим, что

это А:

A AZVS DSEC KAS DXZNN DASNN

3. В третьем слове должны быть гласные звуки и вероятно, что это двойные буквы. Это не могут быть UU или II, а также АА (буква А уже использована). Попробуем вариант ЕЕ.

A AZVE DEEC КАЕ DXZNN DAENN

4. Четвертое слово состоит из трех букв и оканчивается на Е, это очень похоже на слово THE.

A HZVE DEEC THE DXZNN DHENN

5.Во втором слове нужна гласная, и здесь подходят только I, O, U (буква А уже использована). Только вариант с буквой I дает осмысленное слово.

A HIVE DEEC THE DXINN DHENN

6.Можно найти несколько слов с двойной буквой E из четырех букв (DEER, BEER, SEEN). Грамматика требует, чтобы третье слово было глаголом, поэтому остановимся на SEEN.

A HIVE SEEN THE SXINN SHENN

7. Смысл в полученном предложении отсутствует, поскольку улей (HIVE) не может видеть (SEEN), значит, где-то по дороге мы сделали ошибку. Похоже, что выбор гласной буквы во втором слове был неверен, и приходится вернуться назад, отменив самое первое предположение - первым словом должно быть I. Повторяя все остальные наши рассуждения практически без изменений мы получаем:

I HAVE SEEN THE SXANN SHENN

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

I HAVE SEEN THE SXALL SHELL

9.Из грамматических соображений очевидно, что оставшееся слово - прилагательное. Анализируя шаблон S?ALL, находим SMALL.

I HAVE SEEN THE SMALL SHELL

Таким образом, решение найдено. Анализируя процесс решения, мы можем сделать три наблюдения:

Для решения применялись разнообразные знания: о грамматике, о составе слов, о чередовании согласных и гласных.

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

Мы подходили к делу наугад, приспосабливаясь к обстановке. Иногда делались выводы от общего к частному (словом из трех букв, оканчивающимся на Е будет, вероятно, THE), а иногда от частного к общему (?ЕЕ? может соответствовать DEER, BEER, SEEN, но глаголом из них является только SEEN).

Соседние файлы в предмете Программирование на C++