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

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

.pdf
Скачиваний:
0
Добавлен:
08.09.2026
Размер:
2 Мб
Скачать
☆
терфейсом. Также адаптируемый связан с каждым конкретным
адаптером по типу композиции, так как каждый конкретный адаптер формируется под конкретного адаптируемого, возмож-
но не под одного.
Значимость паттерна в контексте разработки систем
сильного ИИ. Преобразование информации между различными
составляющими системы, осуществляемое с целью приведения этой информации в тот самый вид, в котором ее будет способен «усвоить» воспринимающий, настолько необходимо, что утверж­дение об этом выглядит абсолютно тривиально. Однако это пре­образование может быть осуществлено различными способами. Можно действительно по умолчанию оборудовать одну группу компонентов для взаимодействия с другой группой, если нам за­ранее известно, что ни с кем более им взаимодействовать не придется. Однако в случае с паттерном «Адаптер» сама природа взаимодействия инкапсулируется в некую отдельную сущность и априори подразумевается возможность одной группы ПК вза­имодействовать с абсолютно любой другой группой компонен­тов. Нам в контексте разработки систем сильного ИИ подобный подход представляется наиболее продуктивным, и на это есть причины. А именно – в самоорганизующейся системе, в которой сама возможность установления связей подразумевается не огра­ниченной локально, а, напротив, рассредоточенной по всей си­стеме, динамика установления этих связей и возможные успеш­ные соединения между компонентами выше, чем если бы связи были ограничены локально. К тому же, объективация самой природы, самой сути связи с последующим ее воплощением в отдельной сущности нам представляется не просто соблюде­нием принципов единственной ответственности и разделения интерфейса, а даже больше – приближением к утрированному воплощению принципа инверсии зависимостей, к той самой си­туации, когда все зависимости сводятся к абстракциям.
231
13.2. Структурный паттерн «Прокси»
Идентификатор. Прокси (Proxy).
Классические элементы. Прокси, субъект, реальный субъект.
Назначение. Как указывается в Design patterns, «Прокси»
«является суррогатом другого объекта и контролирует доступ к нему» [114, с. 203]. Собственно говоря, цитата из Design pat­terns практически исчерпывающе отражает суть данного пат­терна. Однако все же формализуем. «Прокси» представляет собой ПК, являющийся копией другого, связанного с ним ПК, и спосо­бен осуществлять предварительную обработку всех запросов к этому компоненту.
Проблема. На самом деле проблем, которые решает «Прок­си», довольно большое количество, и охватывать их все не пред­ставляется нам целесообразным. Поэтому мы выберем один ва­риант (с некоторыми минимальными оттенками вкрапления других) из этого множества, а именно – охранник (иногда еще обозначается как защищающий прокси). К примеру, у нас нали­чествует некий ПК. У него, соответственно, имеются некоторые свойства и качества. К этому ПК могут делать некие запросы другие ПК, которых имеется некоторое количество. Из этого ко­личества половина компонентов может только лишь получать ответы от нашего компонента. Другая половина тоже может по­лучать ответы, но еще может и устанавливать нашему компо­ненту некоторые блоки данных в виде пар key – value («ключ – значение»), делая эти самые блоки его частью. Еще добавим, что наш ПК довольно-таки тяжелый и большой в плане занимаемой памяти и постоянное его «дергание» по всем запросам оказыва­ется не вполне оптимальным. Нам необходимо сделать так, что­бы мы могли проверять полномочия каждого ПК, который обра­щается к нашему компоненту, на предмет того, на что он имеет право, и только после этого при необходимости переадресовы­вать запрос нашему компоненту. И это поможет осуществить структурный паттерн «Прокси».
Концептуальное решение. Опять же ввиду многочисленности вариантов воплощения, приведем один из вариантов реализации
232
данного паттерна. Мы можем создать базовый ПК (субъект), ко- торый затем формирует некоторую общую логику. От субъекта эту общую логику наследуют два других компонента, которые являются по отношению к субъекту его подкомпонентами: реальный субъект и прокси. Так как оба этих программных ком­понента являются дочерними по отношению к субъекту, то, со­ответственно, их интерфейс является одинаковым. Различия у них наличествуют только «под капотом». Еще стоит отдельно ска­зать о том, что субъект, по сути, прячет свое настоящее есте­ство в свой подкомпонент – реальный субъект. Теперь при лю­бом обращении к субъекту он делегирует дальнейшую работу
прокси. Тот в свою очередь является временной заменой реаль­ного субъекта, как бы его личным дворецким и по совмести-
тельству охранником-вышибалой. Он проверяет все те ПК, ко­торые хотят получить доступ к реальному субъекту, и сверяет их на предмет соответствия их запроса их полномочиям. И в слу­чае несовпадения – отказывает в доступе. За счет такой системы получается следующее: реального субъекта не «дергают» без достойной на то причины, а также он защищен от проведения над собой ненадлежащих действий. Причем, что является важным, за счет одинакового интерфейса реального субъекта и прокси «пользователь» всегда считает, что имеет дело именно с реаль­ным субъектом, а о существовании прокси он даже и не подо­зревает.
Предполагаемые результаты и преимущества. Отсутствие опасности некорректной трансформации ПК, оптимизирован­ный доступ к реальному субъекту. Кэширование ответов реаль­ного субъекта. Т. е. предположим, что некоторый пользователь обратился к реальному субъекту с запросом найти кое-что в его внутренней структуре данных. Так как с соответствием запроса полномочиям все было в порядке, то прокси переадресовал за­прос реальному субъекту. Реальный субъект нашел требуемое и вернул ответ на запрос. Ситуация закончилась. И вот через некоторое непродолжительное время тот же пользователь воз­вращается с тем же запросом, так как забыл ответ. Но такие си­туации предусмотрены заранее и именно для их разрешения
233
и применяется кэширование, т. е. сохранение ответа на некото­рый запрос в некоторой промежуточной структуре данных в виде пар key – value («ключ – значение»). И при наличии в та­кой структуре данных «ключа», совпадающего с некоторым за­просом конкретного пользователя, обращения к основному ПК не происходит, а просто сразу возвращается ответ из промежу­точной структуры данных. Это и есть кэширование.
Гипотетический пример реализации паттерна. В случае с данным паттерном очень даже корректным примером является теория о наличии двойников у некоторых высокопоставленных лиц. Один человек, прокси, замещает собой другого, реального человека, для того чтобы к реальному человеку пропускались только те запросы (в общем смысле слова), которые он не против удовлетворить (также в общем смысле). Единственное замеча­ние: в данном примере в роли субъекта находится реальный субъект, а в роли реального субъекта – также он сам. В осталь­ном пример почти идентичен тому, как реализуется паттерн.
Осмысление структуры паттерна. ПК, представляющие собой прокси и реального субъекта, связаны с компонентом
субъекта по типу наследования, а также прокси связан с реаль­ным субъектом по типу композиции, так как прокси не сможет существовать без реального субъекта.
Значимость паттерна в контексте разработки систем сильного ИИ. Если несколько отвлечься от сугубо утилитарной
значимости данного паттерна и сразу выйти на несколько аб­страктный уровень, то центральной абстракцией всего паттерна «Прокси» окажется реализация кажущегося замещения или, проще говоря, притворства. Может показаться, что это не осо­бенно значимо в контексте разработки систем сильного ИИ. Од­нако есть, как водится, некоторый нюанс. К примеру, человек одинаково себя ведет, если в темной комнате заметит змею или если в этой же комнате заметит веревку, которая покажется ему змеей. Т. е., по всей видимости, реальное положение дел не всег­да адекватно отражается внутренним миром. Можно попробо­вать продолжить эту идею тем, что также для человека далеко не всегда важно то, кто он есть, а важно то, кем он себя считает
234
и кем притворяется. Также в произведении «Государство» у Пла­тона указано притворство в качестве одного из основных средств воспитания [120]. У Йохана Хёйзинги в трактате «Человек игра­ющий» было указано, что все сложные формы человеческой дея­тельности изначально осваивались в игровой форме [94]. Причем человеческое притворство – это довольно сложный с психиче­ской точки зрения процесс, подразумевающий наличие само­сознания и высокую лабильность Я-концепции. Т. е. интеллек­туальная система без наличия техноропного сознания не будет способна на реализацию столь сложных феноменов. Однако можно пойти как раз от обратного и попытаться приблизить ве­роятность возникновения самого технотропного сознания при помощи реализации феноменов его уровня. И на наш взгляд именно абстракция, лежащая в основе данного паттерна, выгля­дит наиболее перспективно для реализации этой концепции. Собственно говоря, это именно то, что и пытаются сделать в рамках разработки систем слабого ИИ: пытаются сформиро­вать некий суррогат какого-либо человеческого аспекта для того, чтобы «остальной человек» сформировался сам. Т. е. прин­цип, лежащий в основе, подобран верно, однако его реализа­ция – нет. Для того чтобы феномен такого рода смог привести к качественным преобразованиям в системе, опыт реализации данного феномена должен быть затем органично интегрирован в общий опыт системы и «осознан» ею. А подобное возможно только в контексте систем, способных к самоорганизации, кото­рые мы и предлагаем формировать для дальнейшего продвиже­ния на пути к сильному ИИ.
13.3. Структурный паттерн «Мост»
Идентификатор. Мост (Bridge). Классические элементы. Абстракция, конкретная абстрак-
ция, реализатор, конкретный реализатор.
Назначение. В Design patterns указано, что «Мост» «связы­вает абстракцию с ее, возможно, многочисленными реализация­ми. Данный паттерн предоставляет клиентам стабильный ин-
235
терфейс, позволяя в то же время изменять классы, которые его реализуют. Мост также подстраивается под новые реализации, появляющиеся в процессе развития системы» [114, с. 214]. Дан­ный паттерн предназначен для того, чтобы в рамках какой-либо системы все включенные в нее ПК были иерархически разделе­ны на две большие (не обязательно равные) группы, причем та­ким образом, чтобы компоненты одной группы могли трансфор­мироваться вне зависимости от состояния компонентов другой группы (как и наоборот), но в то же время чтобы компоненты обеих групп могли эффективно взаимодействовать для решения общих задач. Также можно определить, что паттерн «Мост» предназначен для разделения сложного, динамически трансфор­мирующегося функционала в рамках системы на два различных функционала: высокоуровневый и низкоуровневый. Данные функ­ционалы способны как трансформировать свое состояние вне зависимости от состояния другого, так и успешно решать со­вместные задачи.
Проблема. Представим себе некую систему, в рамках кото­рой наличествует определенное количество ПК. Компоненты подразделяются на некоторые группы, объединенные общими ответственностями. И если, в данном конкретном случае, по­смотреть на такую систему, то мы можем обнаружить, что она, по большому счету, выполняет обязанности, подразделяемые на две большие группы. К примеру, одна из этих групп обязанно­стей сводится к получению извне некой информации, а другая же группа ее преобразует и хранит. Дополним также, что в рам­ках данной системы специфика самой информации зависит от способа ее получения, а также от способа обработки и хранения. С другой стороны, программным компонентам первой группы нет дела до того, каким именно образом хранится и обрабатыва­ется информация, а компонентам второй группы нет дела до того, как она получена. Однако специфика информации застав­ляет подстраиваться всю систему. К примеру, если попробовать добавить некую обязанность к первой группе, скажем добавить новый способ получения информации, то вынуждена будет транс­формироваться вся система в целом, так как ПК второй группы
236
будут вынуждены определять для себя новую функциональ­ность, которая заключается в преобразовании и хранении ин­формации, полученной неизвестным ранее способом. Точно так же, если добавится новый способ хранения или преобразования информации, то компонентам первой группы придется опреде­лять для себя способ ее получения вне зависимости от того, бу­дут они ее получать или нет. В общем случае получается, что система чересчур связана между собой, нарушая тем самым фундаментальный принцип слабого зацепления, также в такую систему крайне тяжело вносить изменения, так как они слиш­ком быстро накапливаются, делая систему неудобной в плане поддержки. Для интенсификации наглядности можно просто представить, что все ПК в такого рода системе наследуются от одного и того же базового компонента и все изменения, необхо­димые какому-либо из подклассов, вносятся сразу в базовый класс («на всякий случай»).
Концептуальное решение. Мы могли бы разделить систему вышеприведенного типа на две структурно обособленные функ­ционально различающиеся части. Часть первую – ответственную за получение информации откуда-то извне, а соответственно, и за UI (User Interface – пользовательский интерфейс) – мы обо­значим как абстракцию, а часть вторую – как реализатор. ПК, относящиеся к первой части, мы обозначим как конкретные аб-
стракции, а относящиеся ко второй части – конкретные реали­заторы. Абстракция содержит в себе ссылку на самого реализа­тора. Этим их связи пока и ограничиваются (мост, как суть паттерна). Теперь при получении какой-либо информации аб­стракция просто вызывает метод реализатора, который затем
передает запрос конкретным реализаторам, подходящим под актуальную ситуацию. Конкретные реализаторы на месте осу­ществляют преобразование и хранение информации. Если мы теперь захотим добавить какой-либо новый способ получения информации, то мы изменим только либо какие-то конкретные абстракции, либо саму абстракцию, и больше изменений в си­стему вносить не нужно. Если же мы решим добавить некий но­вый способ преобразования и хранения информации, то нам
237
нужно будет изменить только, опять же, либо некоторые кон­кретные реализаторы, либо сам реализатор.
Предполагаемые результаты и преимущества. Ожидаемы­ми результатами применения паттерна «Мост» является легкость внесения изменений в систему, гибкость в плане возможности реализации функционала системы на различных платформах, четкое разделение функционала системы, за счет чего с ней ста­новится удобнее работать и легче ее поддерживать, инкапсуля­ция функционала.
Гипотетический пример реализации паттерна. В случае с данным паттерном неплохо подходит приближенный пример какого-либо крупного предприятия. Представим себе его разде­ление на администрацию (абстракцию) с ее сотрудниками (кон- кретные абстракции) и рабочих (конкретные реализаторы), над которыми главенствует начальник производства (реализатор). Администрации приходит некоторый заказ на определенную продукцию, а рабочие его выполняют. Причем непосредственно в рабочий процесс никто из администрации не вникает – этим занят начальник производства. При освоении на производстве какой-либо новой технологии у администрации ничего не изме­няется, а при выходе какого-либо постановления правительства о дополнительной отчетности по налогам у рабочих также ниче­го не меняется.
Осмысление структуры паттерна. Абстракция связана с реализатором двусторонними отношениями. Причем в случае с данным паттерном со стороны абстракции – агрегация, а со стороны реализатора – композиция. Конкретные реализаторы связаны с реализатором отношениями зависимости, а конкрет- ные абстракции связаны с абстракцией специфическими отно­шениями дополнительного определения функционала абстрак- ции (в классическом понимании паттерна – не наследование).
Значимость паттерна в контексте разработки систем сильного ИИ. Данный паттерн представляет определенный ин-
терес для сферы разработки систем сильного ИИ. Однако ввиду того, что сам паттерн несколько узкоспецифичен и, в общем-то, в своих конкретных воплощениях довольно-таки сильно привя-
238
зан к контексту разработки программного обеспечения, то его, соответственно, необходимо существенно абстрагировать. Сама идея разделения абстракции и конкретики лежит в основе как нашего подхода к разработке систем сильного ИИ, так и акту­ального исследования. Так что будет явным преуменьшением постулировать, что данная идея нам близка. Более того, нам представляется, что принцип взаимно независимой трансформа­ции абстрактного и конкретного не отражает всей полноты кар­тины. Нам представляется непротиворечивой возможность, при которой, если приводить в пример вышеописанную ситуацию с надвое разделенной системой с множеством ПК, то, согласно нашему предположению, к феномену независимой трансформа­ции должны быть способны вообще все ПК системы. И в дан­ном случае не представляется существенным, ответственность какого рода лежит на этих компонентах – абстрактная или кон­кретная. Другое дело, сколько данных изменений будут затем органично встроено в новый контекст системы, а скольким бу­дет уготовано закончиться без принятия в контекст.
Это несколько напоминает первый этап методологии автома­тизации развертывания программных проектов – CI/CD (contin­uous integration / continuous delivery / continuous deployment, т. е. непрерывная интеграция / непрерывная доставка / непрерывное развертывание). В рамках данной методологии происходит при­близительно следующее. Разработчики относительно независи­мо друг от друга вносят в целостную систему некоторые изме­нения. Разумеется, что каждый из них старается, чтобы с теми изменениями, которые внес в систему именно он, никаких про­блем не возникло, и они были органично интегрированы. Т. е. никто специально не будет делать так, чтобы быть отвергнутым контекстом. Далее все изменения, внесенные в систему, нака­пливаются в центральном узле – репозитории. После этого на­чинается тестирование внесенных изменений. И если где-либо обнаруживается какая-то проблема, то затем ее, при помощи регрессионных тестов, будут искать, эмулировать и затем устра­нять. Примерно тот же процесс видится нам наиболее естествен­ным и целесообразным при самоорганизации сложной интел-
239
лектуальной системы. Т. е., в соответствии с нашим подходом к формированию систем сильного ИИ, к независимой и авто­номной трансформации должны быть способны не только аб­стракция и реализация, а все ПК системы без исключения.
13.4. Структурный паттерн «Компоновщик»
Идентификатор. Компоновщик (Composite). Классические элементы. Компонент, лист, узел. Назначение. В Design patterns указано, что предназначение
«Компоновщика» сводится к тому, что он «должен так структу­рировать классы, чтобы различные взаимосвязанные объекты удавалось трактовать единообразно, а несколько объектов рас­сматривать как один» [114, с. 214]. Таким образом, данный пат­терн применяется в качестве конструктора для того, чтобы сфор­мировать структуру данных, внешне напоминающую дерево, для тех ПК, которые реализовывают схожее поведение как буду­чи в одиночестве, так и находясь в составе группы других ком­понентов. Т. е. паттерн облегчает работу с некой системой за счет объединения и унификации всех компонентов данной си­стемы.
Проблема. Можно представить себе программную систему, состоящую из некоторого количества частей, т. е. компонентов. Компоненты, принадлежащие данной системе, реализуют схо­жее поведение, но являются в некотором роде разрозненными и разобщенными, можно сказать «разбросанными». Причем этих самых компонентов очень много и они могут различаться по размеру. Далее нам необходимо каким-то образом взаимодей­ствовать с этими компонентами, узнавать о них некоторую ин­формацию, считать их количество, перемещать их из одного места в другое и т. д. Т. е., допустим, нам в рамках системы не­обходимо переместить некоторое количество компонентов из точки А в точку В. И мы направляемся в точку А, берем один компонент и перемещаем его в точку В. Затем идем обратно, бе­рем следующий компонент и его тоже перемещаем в точку В. И так далее, возможно очень много раз. Само собой разумеется,
240
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]