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

Сильный искусственный интеллект и объектно-ориентированное программирование синтез парадигм

.pdf
Скачиваний:
0
Добавлен:
08.09.2026
Размер:
2 Мб
Скачать
☆
тельно может показаться, что ПК при использовании различных своих методов буквально меняет ипостась (классовую принад­лежность). Для управления системой в подобных ситуациях и координации ее действий и служит поведенческий паттерн «Состояние».
Проблема. Представим, что наличествует некоторая систе­ма, состоящая из множества сложных ПК. Каждый из компо­нентов реализует достаточно большое количество вариантов своего поведения, т. е. совершенно по-разному самореализуется в зависимости от актуальной ситуации в рамках программной системы. При смене вариантов поведения ПК претерпевают серьезные внешние и внутренние изменения и становятся «на себя не похожи». Связь между данными компонентами в рам ках системы вариабельна. Соответственно, компоненты такой си­стемы близки к тому, чтобы в полной мере нарушить и принцип сильной связности, и принципы единственной ответственности и разделения интерфейсов из SOLID. При комплексном наруше­нии этих принципов имеет место такая ситуация, при которой ПК попадает под соответствие метафоре god-object, т. е. боже­ственный объект, ответственность которого далеко переходит все допустимые границы. Такой ПК невозможно повторно ис­пользовать, его крайне сложно трансформировать, более того – его опасно трансформировать, так как, скорее всего, нарушится функционирование системы в целом. В том же случае, если от­ветственности подобных компонентов еще и могут где-либо пе­ресекаться, функционирование системы становится откровенно некорректным. Собственно, проблема заключается в том, что необходимо каким-то образом переосмысливать струк туру систе­мы, и начать следует с переосмысления и трансформирования структуры подобных ПК.
Концептуальное решение. ПК, которые реализуют множе­ство вариантов разнообразного функционала, при каждом из ко­торых их поведение уникально и существенно отлично от иных вариантов, разделяются на части (разделение интерфейса и ин­капсуляция логики). Определяется некоторый интерфейс для связи ПК с другими ПК. Этот интерфейс и есть контекст (как
181
классический элемент паттерна «Состояние»). Далее определя­ется второй ПК, который, по сути, представляет собой менедже­ра состояний и является следующим классическим элементом паттерна – состоянием. Этот второй ПК определяет в себе неко­торое количество своих подкомпонентов (подклассов), каждый из которых представляет собой отдельную ипостась базового ком­понента, т. е. инкапсулирует определенное состояние и некото­рое поведение, зависящее от этого состояния. Подкомпоненты базового компонента могут быть абсолютно никак не связаны друг с другом и даже не подозревать о существовании друг друга. И к слову, это и есть пример хорошей реализации, так как подоб­ные подкомпоненты легки в плане повторного использования по причине высокого уровня автономности и слабого зацепления. Далее менеджер состояний тесно взаимодействует с контекстом и предоставляет ему для использования свои подкомпоненты, подбирая их в зависимости от текущей системной ситуации, ре­зюмированной в запросе со стороны контекста. В общем смысле примерно таким образом и функционирует паттерн «Состояние».
Предполагаемые результаты и преимущества. В резуль­тате корректного применения паттерна «Состояние» не нару­шаются принципы сильной связности и слабого зацепления, реализуются на практике два принципа SOLID – принцип един­ственной ответственности и принцип разделения интерфейса. Сложный функционал базового ПК оказывается разделен и ин­капсулирован в некоторое количество подкомпонентов, что су­щественно упрощает как непосредственно функционирование системы, так и взаимодействие с ней со стороны пользователя. Очерчивается четкая линия демаркации между различными ипо­стасями базового ПК, что упрощает понимание происходящего со стороны того же пользователя. Целесообразно будет допол­нительно указать на особенности повторного использования подкомпонентов базового ПК, которые можно охарактеризовать как подсостояния. В том случае, если различные базовые ПК ре­ализуют схожую логику поведения в разных контекстах, одни и те же подсостояния также можно дополнительно использовать в разных ситуациях.
182
Гипотетический пример реализации паттерна. Вообще говоря, сущность паттерна «Состояние» является чуть ли не зло­бодневно естественной. Абсолютно любой человек ведет себя по-разному в различных состояниях. Здесь не вполне уместно замечание о том, что бывают «люди слова» и «люди настрое­ния», по той причине, что при смене состояния у любого человека изменится и поведение. Просто у «людей слова» его, возможно, сложнее трансформировать извне, чем у «людей настроения». В этой точке дискурса можно даже утрировать смысл и сказать, что любой человек, будучи у него сломана рука или нога, не сможет вести себя так, как смог бы, будь они не сломаны. Т. е. аб­солютно естественной является смена поведения при смене состояния и человек – просто пример. На самом же деле вся при­рода функционирует точно таким же образом: периоды размно­жения, циклы миграции и т. д. И тем не менее, как следует из специфики описываемых ситуаций применения паттерна в рам­ках разработки программного обеспечения, все эти примеры, сколько их ни приводи, все же будут не в полной мере соответ­ствовать специфике реализации поведенческого паттерна «Со­стояние». Соответствие не достигается по той причине, что человек не обязательно должен чувствовать себя совершенно другим человеком при реализации различных поведенческих действий в разнообразных состояниях, а паттерн подразумевает (в идеале) воплощение именно такой ситуации. Также человек в одном состоянии обычно знает, что оно у него не одно, а ино­гда случаются и другие. В рамках же паттерна подкомпоненты совершенно не обязаны знать (в идеале) о наличии других под­компонентов. Именно поэтому вышеприведенные ситуации в об­щем смысле схожи, но все же не полностью соответствуют друг дру г у.
Соответствовать будут несколько иные примеры. А именно: случаи серьезных психических отклонений психотического ти­па. Находясь в рамках психотического контекста, субъект спосо­бен, пребывая в некотором состоянии, не подозревать о других своих состояниях и в каждом отдельном состоянии реализовы­вать совершенно различный функционал. Наиболее знаменитым
183
(художественным) примером наглядной демонстрации подоб­ной ситуации является известный фильм Дэвида Финчера, сня­тый по роману Чака Паланика, «Бойцовский клуб». У главного героя произведения шизофрения, которая выражается в разделе­нии личности на две ипостаси: невзрачного офисного клерка, озабоченного обустройством и декорированием собственного жи­лища, и брутального харизматичного торговца мылом, подраба­тывающего по ночам на различных позициях. Герой, который большую часть фильма находится в первой ипостаси, не подо­зревает о наличии у себя второй личности, которая активно дей­ствует. Каждая из ипостасей героя обладает своими собствен­ными состояниями, системой реализуемых образов действия, уникальными системами ценностей и отдельным экзистенциаль­ным статусом, т. е. вся логика их функционирования является инкапсулированной. И в то же время обе ипостаси – это «две стороны одной монеты», так как они обе все же являются одним и тем же человеком, что и выясняется к концу произведения. Причем в случае с данным примером наличествует еще одно крайне интересное замечание, а именно – вторая личность знает о наличии у себя первой личности и владеет всей информацией о ней. Т. е. мы видим, по сути, нарушение принципа слабого зацепления. А интересным тут является то, что именно за нару­шение этого принципа вторая личность, в конце концов, и по­платилась. Причина тут простая: первая личность была связана со второй по типу агрегирования, т. е. вполне могла автономно существовать, а вот вторая личность была связана с первой по типу композиции, т. е. без нее существовать не могла.
Осмысление структуры паттерна. Структура паттерна за­ключается в том, что все ПК, его составляющие, связаны с кон- текстом. ПК, который представляет собой состояние, инкапсу- лирует логику своих ипостасей в виде подклассов и отношения здесь сразу видны – это, разумеется, наследование. Состояние связано с контекстом по типу композиции, т. е. состояние не способно существовать без контекста, а контекст связан с состоянием по типу агрегации, так как сам контекст суще­ствовать все равно сможет, просто в случае его существования
184
без всей остальной структуры паттерна он превращается в god­object и нарушает сразу несколько фундаментальных принци­пов ООП.
Значимость паттерна в контексте разработки систем
сильного ИИ. На первый взгляд может показаться, что поведен-
ческий ПП систем, функциональная и структурная суть которо­го нагляднее всего демонстрируется на примере шизофрении, не может быть полезен в качестве основы для разработки интел­лектуальных систем. Но это, как водится, только на первый взгляд. Мы помним, что не имеем права судить о сильном искусствен­ном интеллекте, основываясь на информации о человеке, так как не имеем логически обоснованного права вообще предполагать о нем излишнюю конкретику, которая оставляется нами на от­куп сфере научной фантастики и области паранауки. Мы же подходим к разработке систем сильного ИИ с (если можно так выразиться) максимально «ленивой» позиции. Т. е. мы стараем­ся сделать как можно меньше, чтобы затем сама система сделала как можно больше. Но сделать это «меньше» мы должны макси­мально качественным образом – образом, наиболее соответ­ствующим тем необходимостям построения систем сильного ИИ, которые нам представляются наиболее значимыми. К тому же следует заметить, что, предположительно, сам факт наличия сознания у субъекта способен обуславливать некоторые побоч­ные эффекты присутствия сознания. Т. е. мы можем предполо­жить, что если бы в контексте не подразумевалась возможность возникновения шизофрении, то наличие возможности существо­вания такого феномена, как сознание, также было бы под вопро­сом. Конечно, это звучит несколько софистически, но тем не ме­нее предположение о том, что психические заболевания являют собой побочный эффект наличия сознания, выглядит непроти­воречиво хотя бы потому, что психические заболевания фикси­руются только лишь у человека и сознание также замечено толь­ко у человека (если признать факт его существования, с чем не все согласны).
Таким образом, мы не имеем права ограничивать когнитив-
ные способности интеллектуальной системы и должны следо-
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
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]