Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Сильный искусственный интеллект и объектно-ориентированное программирование синтез парадигм
.pdf
тельно может показаться, что ПК при использовании различных
своих методов буквально меняет ипостась (классовую принадлежность). Для управления системой в подобных ситуациях
и координации ее действий и служит поведенческий паттерн
«Состояние».
Проблема. Представим, что наличествует некоторая система, состоящая из множества сложных ПК. Каждый из компонентов реализует достаточно большое количество вариантов
своего поведения, т. е. совершенно по-разному самореализуется
в зависимости от актуальной ситуации в рамках программной
системы. При смене вариантов поведения ПК претерпевают
серьезные внешние и внутренние изменения и становятся «на
себя не похожи». Связь между данными компонентами в рам ках
системы вариабельна. Соответственно, компоненты такой системы близки к тому, чтобы в полной мере нарушить и принцип
сильной связности, и принципы единственной ответственности
и разделения интерфейсов из SOLID. При комплексном нарушении этих принципов имеет место такая ситуация, при которой
ПК попадает под соответствие метафоре god-object, т. е. божественный объект, ответственность которого далеко переходит
все допустимые границы. Такой ПК невозможно повторно использовать, его крайне сложно трансформировать, более того –
его опасно трансформировать, так как, скорее всего, нарушится
функционирование системы в целом. В том же случае, если ответственности подобных компонентов еще и могут где-либо пересекаться, функционирование системы становится откровенно
некорректным. Собственно, проблема заключается в том, что
необходимо каким-то образом переосмысливать струк туру системы, и начать следует с переосмысления и трансформирования
структуры подобных ПК.
Концептуальное решение. ПК, которые реализуют множество вариантов разнообразного функционала, при каждом из которых их поведение уникально и существенно отлично от иных
вариантов, разделяются на части (разделение интерфейса и инкапсуляция логики). Определяется некоторый интерфейс для
связи ПК с другими ПК. Этот интерфейс и есть контекст (как
181

классический элемент паттерна «Состояние»). Далее определяется второй ПК, который, по сути, представляет собой менеджера состояний и является следующим классическим элементом
паттерна – состоянием. Этот второй ПК определяет в себе некоторое количество своих подкомпонентов (подклассов), каждый
из которых представляет собой отдельную ипостась базового компонента, т. е. инкапсулирует определенное состояние и некоторое поведение, зависящее от этого состояния. Подкомпоненты
базового компонента могут быть абсолютно никак не связаны
друг с другом и даже не подозревать о существовании друг друга.
И к слову, это и есть пример хорошей реализации, так как подобные подкомпоненты легки в плане повторного использования по
причине высокого уровня автономности и слабого зацепления.
Далее менеджер состояний тесно взаимодействует с контекстом
и предоставляет ему для использования свои подкомпоненты,
подбирая их в зависимости от текущей системной ситуации, резюмированной в запросе со стороны контекста. В общем смысле
примерно таким образом и функционирует паттерн «Состояние».
Предполагаемые результаты и преимущества. В результате корректного применения паттерна «Состояние» не нарушаются принципы сильной связности и слабого зацепления,
реализуются на практике два принципа SOLID – принцип единственной ответственности и принцип разделения интерфейса.
Сложный функционал базового ПК оказывается разделен и инкапсулирован в некоторое количество подкомпонентов, что существенно упрощает как непосредственно функционирование
системы, так и взаимодействие с ней со стороны пользователя.
Очерчивается четкая линия демаркации между различными ипостасями базового ПК, что упрощает понимание происходящего
со стороны того же пользователя. Целесообразно будет дополнительно указать на особенности повторного использования
подкомпонентов базового ПК, которые можно охарактеризовать
как подсостояния. В том случае, если различные базовые ПК реализуют схожую логику поведения в разных контекстах, одни
и те же подсостояния также можно дополнительно использовать
в разных ситуациях.
182

Гипотетический пример реализации паттерна. Вообще
говоря, сущность паттерна «Состояние» является чуть ли не злободневно естественной. Абсолютно любой человек ведет себя
по-разному в различных состояниях. Здесь не вполне уместно
замечание о том, что бывают «люди слова» и «люди настроения», по той причине, что при смене состояния у любого человека
изменится и поведение. Просто у «людей слова» его, возможно,
сложнее трансформировать извне, чем у «людей настроения».
В этой точке дискурса можно даже утрировать смысл и сказать,
что любой человек, будучи у него сломана рука или нога, не
сможет вести себя так, как смог бы, будь они не сломаны. Т. е. абсолютно естественной является смена поведения при смене
состояния и человек – просто пример. На самом же деле вся природа функционирует точно таким же образом: периоды размножения, циклы миграции и т. д. И тем не менее, как следует из
специфики описываемых ситуаций применения паттерна в рамках разработки программного обеспечения, все эти примеры,
сколько их ни приводи, все же будут не в полной мере соответствовать специфике реализации поведенческого паттерна «Состояние». Соответствие не достигается по той причине, что
человек не обязательно должен чувствовать себя совершенно
другим человеком при реализации различных поведенческих
действий в разнообразных состояниях, а паттерн подразумевает
(в идеале) воплощение именно такой ситуации. Также человек
в одном состоянии обычно знает, что оно у него не одно, а иногда случаются и другие. В рамках же паттерна подкомпоненты
совершенно не обязаны знать (в идеале) о наличии других подкомпонентов. Именно поэтому вышеприведенные ситуации в общем смысле схожи, но все же не полностью соответствуют друг
дру г у.
Соответствовать будут несколько иные примеры. А именно:
случаи серьезных психических отклонений психотического типа. Находясь в рамках психотического контекста, субъект способен, пребывая в некотором состоянии, не подозревать о других
своих состояниях и в каждом отдельном состоянии реализовывать совершенно различный функционал. Наиболее знаменитым
183

(художественным) примером наглядной демонстрации подобной ситуации является известный фильм Дэвида Финчера, снятый по роману Чака Паланика, «Бойцовский клуб». У главного
героя произведения шизофрения, которая выражается в разделении личности на две ипостаси: невзрачного офисного клерка,
озабоченного обустройством и декорированием собственного жилища, и брутального харизматичного торговца мылом, подрабатывающего по ночам на различных позициях. Герой, который
большую часть фильма находится в первой ипостаси, не подозревает о наличии у себя второй личности, которая активно действует. Каждая из ипостасей героя обладает своими собственными состояниями, системой реализуемых образов действия,
уникальными системами ценностей и отдельным экзистенциальным статусом, т. е. вся логика их функционирования является
инкапсулированной. И в то же время обе ипостаси – это «две
стороны одной монеты», так как они обе все же являются одним
и тем же человеком, что и выясняется к концу произведения.
Причем в случае с данным примером наличествует еще одно
крайне интересное замечание, а именно – вторая личность знает
о наличии у себя первой личности и владеет всей информацией
о ней. Т. е. мы видим, по сути, нарушение принципа слабого
зацепления. А интересным тут является то, что именно за нарушение этого принципа вторая личность, в конце концов, и поплатилась. Причина тут простая: первая личность была связана
со второй по типу агрегирования, т. е. вполне могла автономно
существовать, а вот вторая личность была связана с первой по
типу композиции, т. е. без нее существовать не могла.
Осмысление структуры паттерна. Структура паттерна заключается в том, что все ПК, его составляющие, связаны с кон-
текстом. ПК, который представляет собой состояние, инкапсу-
лирует логику своих ипостасей в виде подклассов и отношения
здесь сразу видны – это, разумеется, наследование. Состояние
связано с контекстом по типу композиции, т. е. состояние
не способно существовать без контекста, а контекст связан
с состоянием по типу агрегации, так как сам контекст существовать все равно сможет, просто в случае его существования
184

без всей остальной структуры паттерна он превращается в godobject и нарушает сразу несколько фундаментальных принципов ООП.
Значимость паттерна в контексте разработки систем
сильного ИИ. На первый взгляд может показаться, что поведен-
ческий ПП систем, функциональная и структурная суть которого нагляднее всего демонстрируется на примере шизофрении, не
может быть полезен в качестве основы для разработки интеллектуальных систем. Но это, как водится, только на первый взгляд.
Мы помним, что не имеем права судить о сильном искусственном интеллекте, основываясь на информации о человеке, так как
не имеем логически обоснованного права вообще предполагать
о нем излишнюю конкретику, которая оставляется нами на откуп сфере научной фантастики и области паранауки. Мы же
подходим к разработке систем сильного ИИ с (если можно так
выразиться) максимально «ленивой» позиции. Т. е. мы стараемся сделать как можно меньше, чтобы затем сама система сделала
как можно больше. Но сделать это «меньше» мы должны максимально качественным образом – образом, наиболее соответствующим тем необходимостям построения систем сильного
ИИ, которые нам представляются наиболее значимыми. К тому
же следует заметить, что, предположительно, сам факт наличия
сознания у субъекта способен обуславливать некоторые побочные эффекты присутствия сознания. Т. е. мы можем предположить, что если бы в контексте не подразумевалась возможность
возникновения шизофрении, то наличие возможности существования такого феномена, как сознание, также было бы под вопросом. Конечно, это звучит несколько софистически, но тем не менее предположение о том, что психические заболевания являют
собой побочный эффект наличия сознания, выглядит непротиворечиво хотя бы потому, что психические заболевания фиксируются только лишь у человека и сознание также замечено только у человека (если признать факт его существования, с чем не
все согласны).
Таким образом, мы не имеем права ограничивать когнитив-
ные способности интеллектуальной системы и должны следо-
185

вать этому правилу с самого начала. К тому же возможно, что
именно психотичный тип мышления и покажется системе сильного ИИ наиболее продуктивным: пример Джона Форбса Нэша –
младшего с шизофренией или примеры Винсента Ван Гога,
Стэнли Кубрика или Чарльза Дарвина с расстройствами аутического спектра показывают, что психические отклонения иногда
не только не мешают, но и, возможно, способствуют развитию
интеллектуальных способностей высокого уровня. К тому же
в психоанализе, в рамках теории защитных механизмов, также
наличествует один из механизмов защиты субъекта от негативного опыта путем изоляции оного от всей остальной системы
психической деятельности. Учитывая все противоречия, можно,
по меньшей мере, постулировать, что поведенческие ПП, которые потенциально способны оказывать негативный эффект, также
могут быть использованы в контексте разработки систем сильного ИИ при наличии у них иных значимых качеств и свойств.
В случае с паттерном «Состояние» мы полагаем его полное
соответствие вышесказанному, так как паттерн способен обуславливать необходимую динамику состояний системы быстрым
и оптимизированным способом и, соответственно, способен обеспечивать надлежащую смену состояний ПК, опираясь на предъявляемые контекстом необходимости. Основной же его ценностью является как раз инкапсуляция функционала различных
состояний и самих этих состояний в некую общую форму, превращая тем самым «размазанную» по системе логику в полноценные, отдельные ПК, преобразуя части системы в иные феномены с качественно новым экзистенциальным статусом.
12.5. Поведенческий паттерн «Команда»
Идентификатор. Команда (Command).
Классические элементы. Команда, конкретная команда, кли-
ент, инициатор, получатель.
Назначение. Как указывается в Design patterns, «Команда»
«инкапсулирует запрос в объекте, предписывает единообразный интерфейс для выдачи запросов, с помощью которого мож-
186

но сконфигурировать клиенты для обработки разных запросов»
[114, с. 76]. Назначение данного паттерна, если сразу абстрагировать его суть, примерно следующее: преобразовывать некоторые данные из одного типа и вида в другой тип и вид для того,
чтобы системе было удобнее обрабатывать эти данные, и для
того, чтобы не иметь необходимости дублировать определенные
операции. Это самое преобразование должно позволить сделать
систему более компактной и оптимизированной, повторно использовать один и тот же интерфейс целого слоя ПК, а также
ослабить зацепление.
Проблема. В определенной системе присутствует некоторое
количество ПК, которые, для целей описательного прагматизма,
условно разделены на две большие группы: в первую группу
входят компоненты, которые посылают некоторые запросы компонентам второй группы. Каждый из компонентов первой группы
должен хранить ссылку на определенный компонент из второй
группы, что само по себе уже является нарушением фундаментального принципа слабого зацепления. Некоторые из компонентов первой группы могут быть схожи по функционалу и обращаться к одним и тем же компонентам второй группы. Также
при необходимости добавить какую-либо новую функциональность в систему ее приходится либо реализовывать с нуля, либо
подключать механизм наследования в тех случаях, когда можно
было бы обойтись делегированием, ввиду отсутствия возможности пользоваться некоторым общим интерфейсом для всех компонентов первой группы. Все эти аспекты в совокупности делают систему довольно ригидной, сложно расширяемой и чересчур
сцепленной. Отсутствует некоторый, если можно так выразиться, буферный слой между ПК первой и второй групп. Для решения комплекса подобных проблем и предназначен паттерн «Команда».
Концептуальное решение. Мы хотим сделать так, чтобы
клиент мог активировать инициатор, который затем перенапра-
вит запрос, инициированный клиентом, к получателю, который
обработает запрос клиента и вернет соответствующий ответ.
Собственно говоря, это может с внешней точки зрения довольно
187

неплохо работать, примерно так же, как в системе, которая описывалась нами выше. Но только некоторое время и только с внешней стороны. Со стороны структурной организации и оптимизации функционирования подобная система не особенно жизнеспособна. Однако есть возможность заставить систему работать
гораздо лучше. И это осуществляется непосредственно за счет
введения того самого буферного слоя логики, о котором мы говорили выше. Этот слой, соответственно, и представлен командой. Эта самая команда обычно представляет собой класс, который определяет некий общий интерфейс функционирования
всего слоя в целом. Непосредственно локально, на местах, этот
слой представлен подкомпонентами компонента команда – конкретными командами. В результате происходит примерно следующее. Клиент инициирует некий запрос (допустим, что нужно что-либо сделать) и, соответственно, активирует инициатор:
например, нажимает кнопку, если представить, что клиентом
в данной ситуации является человек, или вызывает определенный
метод, если клиентом является другой класс. Каждый инициатор хранит у себя ссылку на соответствующий ему подкомпонент, и после своей активации инициатор вызывает определенный метод этого самого подкомпонента (к примеру: execute, т. е.
«выполнить»). Здесь стоит заметить, что сам инициатор не владеет информацией о деталях реализации свойственного ему
подкомпонента и, соответственно, не знает и не может знать
о том, что именно подкомпонент будет делать дальше и к какому
именно получателю он будет обращаться, таким образом, принцип слабого зацепления соблюдается. Еще более конкретно это
может выглядеть как хранение инициатором ссылки на вызов
конструктора класса команда, который возвращает готовый подкомпонент (в данном случае объект) с полями, заполненными
соответствующим образом. В подкомпоненте существует ссылка на необходимого получателя, и именно ему и переадресуется
запрос для его дальнейшей обработки. В результате получается,
что в рамках системы наличествуют те же две группы компонентов, что и изначально, но за счет добавления третьей группы
и представления запроса в виде объекта с полями, заполненны-
188

ми соответствующим (уникальным) образом, мы делаем систему не только гибкой и эластичной, но и гораздо проще организованной со структурной и функциональной точек зрения. Стоит
отдельно отметить, что в рамках функционального программирования паттерн подобного рода также можно было бы реализовать: функция-инициатор через некую буферную функцию обращается к функции-обработчику – звенья цепочки примерно
схожи. Но дело в том, что у объектов есть некоторое преимущество перед функциями, а именно – они представляют собой не
просто последовательность алгоритмических действий, а феномен более высокого порядка – организованный ПК с инкапсулированной логикой и некой идентичностью. Например, состояния
объекта, как уже указывалось при исследовании поведенческого
паттерна «Хранитель», можно сохранять и затем повторно использовать, возвращаться к ним и так далее – то, о чем как раз
и говорится в вышеприведенной цитате из Design patterns.
Предполагаемые результаты и преимущества. К основным
результатам применения паттерна «Команда» обычно относят
реализацию на практике (со всеми вытекающими преимуществами) двух принципов SOLID: принципа открытости-закрытости (в виде определения метода execute для каждой конкретной
команды) и принципа разделения интерфейса (в виде отделения
части логики, отвечающей за инициацию запроса, от части логики, отвечающей за отправку запроса получателю). Также оче-
видно, что обеспечивается соблюдение принципа слабого зацепления за счет введения буферного слоя в систему. Помимо
этого, паттерн обеспечивает высокую эластичность системы
и отсутствие сопротивляемости изменениям.
Гипотетический пример реализации паттерна. Пусть
и не так очевидно, как с некоторыми иными паттернами, но в мире существуют практически буквальные реализации данного
паттерна. Но мы представим такой пример. Допустим, у нас есть
некоторая сумма денег, которую мы хотим куда-либо передать.
Разумеется, что ехать в место доставки очень далеко и мы хотим
совершить перевод. У нас имеются в наличии какие-то суммы
в разных валютах. Также нам готово предоставить свои услуги
189

определенное количество трансферных бюро, каждое из которых
специализируется на одной определенной валюте. У нас есть
возможность некоторое время походить по данным бюро, в каждую занеся тот тип валюты, с которым работает конкретное
трансферное бюро, и совершить некоторое количество переводов разных сумм в разной валюте на один и тот же адрес доставки. Это, конечно, очень неудобно, но если нет выбора, то будет
совершено. Но открывается новое трансферное бюро, которое
предлагает следующую услугу: перед переводом обменять все
деньги во всех валютах на их внутреннюю виртуальную валюту
TransferCoin. При осуществлении данного обмена все внесенные
деньги тщательно документируются и сохраняются в единую
структуру данных, функционирующую по принципу key – value,
где key – валюта, а value – сумма в этой валюте. Далее этой
структуре данных присваивается некий уникальный идентификатор (например, хэш-значение), который при расшифровке обозначит точную сумму наших TransferCoin. Далее эта структура
данных с ее идентификатором передается адресату, где она расшифровывается, структура данных открывается, и нашему адресату передают на месте ровно то, что мы ему отправили – суммы
в валютах. Предположим, что заработок конторы заключается
в разнице курсов TransferCoin при пересылке и получении. Вот
эта контора – приближенный пример реализации паттерна «Команда».
Осмысление структуры паттерна. В рамках структуры
данного паттерна отношения между компонентами сводятся
к следующим: команда и конкретные команды, само собой, взаимодействуют по типу наследования. Отношения клиента и ини-
циатора напоминают метафоричную ситуацию «пахнет ли роза,
если ее никто не нюхает». Т. е., с одной стороны, клиент полностью зависит от того, насколько успешно он достигнет своей
цели, которую он пытается достичь при помощи обращения
к получателю посредством инициатора. С другой стороны, если
нет клиента, вся система выглядит бессмысленной. Прямой связи инициатора с получателем обычно стараются избегать вовсе,
дабы излишне не зацеплять ПК друг с другом – их связь осу-
190
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
