![]() |
Модераторы: LSD, AntonSaburov |
![]() ![]() ![]() |
|
Се ля ви |
|
||||
![]() Java/SOAрхитектор ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 2016 Регистрация: 5.6.2004 Где: place without tim e and space Репутация: 8 Всего: 127 |
ParamsBean - альтернативный механизм вызова методов или как реализовать системный подход при построении архитектуры ИС Первая редакция 1. Каждый может принять решение, располагая достаточной информацией 2. Хороший руководитель принимает решение и при её нехватке 3. Идеальный - действует в абсолютном неведении Законы исходных данных Спенсера из "Законов Мёрфи" Предисловие В этой статье я скромно представляю на суд общественности своё решение (небольшое ноу-хау) в архитектуре приложений, написанных на Java, которое я назвал ParamsBean. Оно позволяет программировать логику, более приближенную к действительности, чем при классическом подходе, за счёт необязательных параметров методов, приближая, таким образом, вызов метода к постановке задачи. Подход уже опробован и в реальной (хотя и довольно редко возникающей) ситуации себя оправдал. Надеюсь, вам он так же сможет пригодиться. После того, как мне понадобился этот приём, я задался вопросом о том, как наиболее полно использовать его потенциал и в итоге пришёл к полному пересмотру сложившейся архитектуры построения программ на основе ООП-модели и в перспективе - пересмотр вообще сложившейся архитектуры Информационных Систем - поэтому запаситесь терпением, начну издалека. ![]() Архитектура: почему классический ООП-подход не эффективен при описании реальных ситуаций? Считается, что ООП гораздо ближе к реальному миру, к модели его восприятия человеком, нежели предшествующие подходы. Действительно, мы можем создать объект "собака" и реализовать методы "голос", "сидеть", "лежать" и "фас" - и их вызов будет по смыслу отдалённо напоминать поведение человека по отношению к собаке на прогулке. Всё вроде бы логично, да не совсем - чем на самом деле отличается окружающий мир от программы, так это обилием различных факторов. Собака получает команду "фас" не в отрыве от всей остальной реальности, а в условиях окружения множеством различных второстепенных факторов окружающей действительности и в совокупности эти факторы имеют порой гораздо большее влияние на реакцию собаки на нашу команду, чем сама эта команда. Очевидно, с методом объекта Dog этого не будет - он обработает лишь те параметры, которые ему передадут, коими может стать, пожалуй, лишь громкость голоса, измеренная в децибелах. Он может так же учесть параметры внутреннего состояния, инкапсулированные в нём, но не данные окружающей его среды. Рассмотрим другой пример. Специалист в какой-то области архитектурно предстаёт перед нами как ресурс, способный справиться с каким-то классом задач (соответствующих данной предметной области). Когда возникает задача, специалист сначала выясняет более узкий тип задачи, затем входит в курс дела, погружаясь в специфику задачи, затем более узко - в специфику конкретной ситуации, в которой возникла проблема, затем ищет похожие случаи в своей практике и решает задачу либо на основе опыта (архитектурно - кэша уже выполненных задач или не выполненных, про которые сделаны выводы) либо, в отсутствии такового - пытается решить творчески. Среда, в которой действуют объекты реальной действительности, обычно имеет фоновый характер и лишь косвенно влияет на процесс. Она состоит из множества разнообразных факторов. Соответственно, было бы логично передать её некоторым количеством переменных, редко изменяемых и имеющих значения по умолчанию для типичных ситуаций. Однако небольшой, ограниченный ряд свойств среды в контексте данного конкретного действия (работы метода) имеет первостепенную важность - очевидно, что эти-то свойства в меру возможностей мы и должны в первую очередь определять, передавая методу, остальные же, менее существенные можем считать равными значениям поумолчанию, если у нас нет достаточных ресурсов, что бы их уточнять. Брюс Эккель писал в "Философии Java" о том, что разработчиков удобно разделять на создателей и пользователей библиотек. Архитектурно задача программиста-пользователя - как можно точнее определить внешнюю среду (одним из ключевых факторов которой является само посылаемое объекту сообщение, т.е. вызываемый метод) объекта, которую и передать объекту, а задача программиста-разработчика библиотек - определить внутреннюю структуру объекта, что бы он как можно более адекватно работал в условиях, которые показывает ему программист-пользователь. Возвращаясь к примеру со специалистом, можно говорить о том, что если сопоставить специалиста классу, то у него есть: - данные (энциклопедического характера и накопленные с опытом), - методы (типы задач, с которыми он способен справиться). Методы описываются предметной областью и квалификацией, что программно соответствует интерфейсу класса (класс может реализовывать несколько таких интерфейсов, как человек может быть специалистом в разных областях). Соответственно, у этих методов есть параметры, количество и качество которых определяется с одной стороны - спецификой задачи, с другой - бонально тем, можем ли мы их предоставить в данный конкретный момент или нет (качество решения проблемы, естественно, зависит как от эффективности организации алгоритма, так и от полноты данных, которых в реальной ситуации часто может не хватать - отсюда возможность обоюдного тюненья программы - составителю библиотеки можно вылизывать алгоритм реализации, а программисту-клиенту - пытаться передать более точные данные объекту, позволяя ему лучше "войти в курс дела"). Т.е. для моделирования более реальных ситуаций, нам необходимо иметь возможность писать методы, которые имеют не обязательные параметры. Позволяют ли стандартные принятые подходы такое делать? Да, но очень не удобно, не эффективно и не гибко. Прикладные аспекты описания сигнатур методов или чем нам может помочь подход ParamsBean? Обычно когда мы планируем архитектуру приложения, мы закладываем в сигнатуры методов объектов в библиотеках какие-то параметры, которые играют для выполняемой задачи ключевую роль. Им необходимо их обработать и выдать приемлемый результат. Эти параметры имеют свои типы, имена и жёстко определённый порядок перечисления при вызове метода. Для того, что бы корректно работать с определённым таким образом методом, программист, который будет использовать нашу библиотеку, обязан считаться с этим. Порой возникают ситуации, когда один и тот же функционал удобнее сделать доступным с использованием разного количества параметров, некоторые удобнее задать по умолчанию и дать возможность пользователю библиотеки передать лишь те, которые важны для него. Для таких ситуаций принято пользоваться механизмом перегрузки - действительно, очень удобно написать метод с тем же именем, но с меньшим количеством параметров, из которого вызвать исходный, добавив к параметрам другие со значениями по умолчанию. Однако у этого метода есть ряд существенных недостатков, главным образом - он, очевидно, обладает очень низкой масштабируемостью. Он привносит элементы т.н. жесткого связывания обоих этих программистов по Эккелю (автора библиотек и клиента), а хорошо бы их разнести, что бы они не были вынуждены плотно общаться - особенно это может оказаться важно в больших проектах. Делать же перегруженные методы на все случаи жизни, очевидно, не разумно - количество возможных комбинаций растёт в геометрической прогрессии пропорционально количеству параметров. Как-то была у меня такая задача - надо было вытащить данные из базы и передать их в функцию, в которой очень-очень много параметров (около 30-ти). Реально нужны из них только 5, остальные - значения по умолчанию, но было известно, что этот метод понадобится ещё для реализации большого числа других функций и так же понадобится модифицировать некоторые из параметров вызова, какие - заранее сказать было сложно. Создавать конструктор с 30ю параметрами было не просто очень неудобно - было нужно иметь возможность задать некоторые параметры, а остальные что бы остались такими, какими должны быть по умолчанию. Создавать конструкторы для всех возможных комбинаций, естественно, я не стал ![]() Я создал JavaBean (точнее именно POJO - обрезанный лишь getter`ами и settter`ами JavaBean), в котором инкапсулировались все параметры по умолчанию, и его через промежуточную функцию стал передавать той самой с огромным числом параметров. Вроде бы всё хорошо, но не очень красиво выглядело наполнение параметрами этого бина, к тому же хотелось все параметры всё-таки аккуратно вложить в вызов функции - так оно как-то логичней было бы. Есть множество аспектов языков, о которых не все знают, поскольку на них не принято акцентировать внимание. Так, недавно я открыл для себя, что оператор вызова метода - "." - не обязательно должен сразу следовать за тем объектом, за которым он вызывается, как это обычно принято делать, а может вызываться и на другой строке - главное, что бы метод был рядом, т.е., кто не знает, конструкция:
- вполне валидная. Такая конструкция навешивания изменений свойств была бы идеальна для моей задачи и очень лаконична - если бы я при вызове метода создавал объект и передавал ему те параметры, которые отличаются от параметров по умолчанию, все же остальные оставались бы со значениями по умолчанию. ![]() И вот я подумал - а почему принято setter`ы делать без возвращаемого значения, т.е. "void"? А может быть, стоит заставить их выдавать ссылку на объект своего класса, в конце прописывая выражение "return this;"? Тогда приведённая выше конструкция будет вполне реальной! Сделал и всё отлично получилось! :-))) Выполнил задачу и остался очень собой доволен ![]()
Пока назвал я это ParamsBean - по-моему, очень удобная штука. Явные преимущества Теперь я могу каждый раз при вызове менять значения только тех параметров, которые мне нужно изменить по сравнению с параметрами по умолчанию. Кроме того, я всегда знаю их имена и не путаю их, ведь я вызываю специальные методы, содержащие их имена. Так же теперь я жестко не привязан к порядку их следования при вызове метода - порядок отныне произволен. Могу теперь и пользоваться преимуществами модели JavaBeans для параметров метода, т.е. вводить ограничения на данные и преобразовывать их для хранения в другой формат, вообще, реализуя причудливую логику, инкапсулировать в бине часть функций по обработке данных - например, можно задать методу, которому нужна в качестве параметра длина, ParamsBean, в разных setter`ах которого можно задавать длину в метрах, милях, футах или дюймах, а он уж с методом сам как-нибудь разберётся - это уже вешается на составителя библиотеки, а не на клиента. Кроме того, в сеттерах-геттерах можно инкапсулировать логику прямого или косвенного влияния одних факторов на другие, таким образом, пользователь такого бина получает возможность задавать одним методом несколько факторов. Это возможность распараллелить работу программистов, выполняющих разные роли по Эккелю. Например, они договорились о каком-то методе, которому в качестве параметров передаётся объект "pBean", метод реализует какую-то функциональность. Потом понадобилось изменить метод, передавая ему дополнительные параметры, который в зависимости от них будет менять поведение - для того, что бы старый код работал, просто в этот pBean добавляется новое поле и оно передаётся методу - не надо перегружать метод. Зато программист-пользователь сможет гибче использовать метод и не заморачиваться с теми параметрами, которые ему не известны, при этом не должен будет клянчить каждый раз у разработчика библиотеки специальный перегруженный метод для его ситуации. Т.е. фактически данный подход - это как бы конструктор всех возможных индивидуальных перегрузок метода. По сути, это просто альтернативный привычному нам механизм вызова методов объектов, гораздо более гибкий и более масштабируемый, чем стандартный механизм с перечислимыми параметрами. Если раньше для таких приёмов применялся механизм перегрузки, то c таким подходом он нам уже не нужен - мы сами решаем, какие параметры передавать изменёнными, а какие - оставить со значениями по умолчанию ![]() Для использования такого подхода нужно, что бы параметры по умолчанию обеспечивали хоть какую-то функциональность и служили как бы "заглушками". В ситуации, когда ряд параметров методу быть передан обязан, можно вызывать специальный Exception, но лучше не использовать данный подход вовсе. Он был оправдан именно в задачах с передачей большого количества параметров. Послесловие: архитектурные перспективы внедрения Этот подход позволяет архитектурно приблизить объектную модель к реальной действительности, делая вызов метода более похожим на постановку задачи человеку. Множество факторов, которые влияют на поведение системы, определяют, как система конкретно будет действовать, однако приоритет у этих факторов разный и, соответственно, если мы не знаем их все, но знаем лишь основные, мы можем передать объект состояния окружающей среды, который содержит усреднённые значения по умолчанию для второстепенных факторов и чётко замеренные для приоритетных. В дальнейшем, при тюнинге, для получения более качественной отдачи от метода, мы можем уточнять состояние среды при вызове метода, задавая более точно все параметры и делая систему тем самым более адекватной, видящей вокруг себя то, на что она может реагировать. В документации на библиотеки можно было бы обозначать приоритетную важность точности тех параметров, которые играют для данного конкретного выполняемого метода ключевые и побочные роли, тем самым позволяя лучше распределять ресурсы по уточнению параметров при вызове методов. Для разных состояний окружающей среды можно было бы передавать наследников от принимаемого объекта, которые бы содержали другой набор значений для тех же параметров - разработчик библиотеки был бы от этого дистанцирован. Данный подход позволяет ещё больше стереть разницу между человеком и программой, приближая управление компонентами программы к управлению людьми. Это ставит перед нами вопрос - а почему машина должна подчиняться пользователю, если они оба (и со временем всё большую роль играет компьютер) совместно выполняют одну задачу, которую ставит перед ними тот или иной управляющий? Современные архитектуры, основанные на UML, начинаются с диаграмм "Use Case" (анг. "Вариант использования"), на которых рисуется роль, которую выполняет человек и та функция, которую для него выполняет данная ИС, т.е. машина изначально воспринимается как инструмент. Подход, к которому может привести внедрение ParamsBean`ов будет обратным - у системы будет большое количество распределённых объектов со своими интерфейсами на основе ParamsBean, и за некоторыми объектами будут скрываться терминалы, за которыми сидят пользователи, выполняя творчески какую-то часть бизнес-логики (с которой машина справиться не в состоянии), а всё остальное, автоматизированное, будет выполнять терминал сам, в целом представляясь в виде web-сервиса или CORBA-объекта - на уровне архитектуры будет без разницы - человек за терминалом или голая программа. Реализация такого подхода уже даст возможность каждому отдельному сотруднику автоматизировать свою деятельность, если он не дурак в программировании, а программа, с другой стороны, сможет анализировать действия человека и пытаться учиться, т.е. самоавтоматизироваться - в итоге мы придём к системам уже не автоматизации деятельности персонала, а автоматизации автоматизации их деятельности, т.е. технологий, которые будут сами выискивать рутинные компоненты деятельности людей и от них эффективно людей избавлять, что откроет перед нами радужные перспективы, сделав весь наш труд - творческим. ![]() Это сообщение отредактировал(а) Се ля ви - 25.1.2006, 16:46 -------------------- |
||||
|
|||||
Domestic Cat |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5452 Регистрация: 3.5.2004 Где: Dallas, US Репутация: 50 Всего: 172 |
Есть несколько решений - например, бин содержит не 30 параметров, а мап, и методы getMap, setMap, getValue, setValue. Дальше как угодно - рефлекшном, перебором.
Более простой вариант - используется xml файл, в котором указаны типы геттеров/сеттеров и названия свойств, контейнер сам генерит класс. -------------------- |
|||
|
||||
Се ля ви |
|
|||
![]() Java/SOAрхитектор ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 2016 Регистрация: 5.6.2004 Где: place without tim e and space Репутация: 8 Всего: 127 |
Я довёл свой первоначальный пост до некоторой логической целостности, а выскзанной в нём мысли придал форму архитектурной идеи, обосновав её удобство для некоторых ситуаций и глубже проанализировав различные аспекты её применения.
Думаю, многим будет интересно почитать, хотя бы для сведения, ибо идея мной нигде не встречена и, надеюсь, покажется вам оригинальной. ![]() -------------------- |
|||
|
||||
Се ля ви |
|
|||
![]() Java/SOAрхитектор ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 2016 Регистрация: 5.6.2004 Где: place without tim e and space Репутация: 8 Всего: 127 |
Хоть бы мяукнул кто...
![]() -------------------- |
|||
|
||||
powerOn |
|
|||
![]() software saboteur ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 4367 Регистрация: 7.10.2005 Репутация: 47 Всего: 159 |
Мяу!!!
![]() Идея интерестная. Правда, есть некоторые вопросы... Например, как исключения перехватывать?
если вызов setForumID(5) повлечет исключение, то все остальные, я так понимаю не выполнятся??? |
|||
|
||||
batigoal |
|
|||
![]() Нелетучий Мыш ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6423 Регистрация: 28.12.2004 Где: Санктъ-Петербургъ Репутация: 24 Всего: 151 |
Я давно уже в букмарки занес, но прочитать времени нет. -------------------- "Чтобы правильно задать вопрос, нужно знать большую часть ответа" (Р. Шекли) ЖоржЖЖ |
|||
|
||||
Се ля ви |
|
||||||
![]() Java/SOAрхитектор ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 2016 Регистрация: 5.6.2004 Где: place without tim e and space Репутация: 8 Всего: 127 |
Тут элегантность кода пересекается с безопастностью - так что предпочтительней выбирать безопастность. Согласен, с исключениями нужно быть осторожным - если понадобится создавать такую логику, которая будет учитывать исключения, то приёмом
пользоваться не стоит. Вместо него лучше тогда добросовестно задавать параметры, отлавливать исключения и потом уже передавать параметр объёкту:
С другой стороны, можно подходы комбинировать - те методы, которые могут вызвать Exception, можно задавать отдельно, а остальные - при вызове метода:
Но это уже вопросы стиля. Главное же в ParamsBean - это архитектурная идея, не всегда, как видим, достяжимая элегантность кода - это уже уже постольку-поскольку... ![]() Буду ждать! ![]() ![]() Это сообщение отредактировал(а) Се ля ви - 19.1.2006, 17:01 -------------------- |
||||||
|
|||||||
COVD |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1655 Регистрация: 26.7.2005 Репутация: 17 Всего: 43 |
Оригинальным здесь, на мой взгляд, является то, что сеттеры у вас возвращают обьект. Благодаря этому удобно в одну строчку инициировать начальные значения. Похожий прием с успехом используется в StringBuffer : ..append(..).append(..).append(..)
Что касается удобства пересылки в метод одного бина вместо 30 параметров - да, это смотрится изящней. Но если в бин будет добавлено новое поле, то метод все равно надо переделывать, чтобы обеспечить обработку этого нового поля. В целом, интересно, и наверное это еще один паттерн или поход. Почему бы и нет. |
|||
|
||||
Се ля ви |
|
|||
![]() Java/SOAрхитектор ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 2016 Регистрация: 5.6.2004 Где: place without tim e and space Репутация: 8 Всего: 127 |
Да, но код, который взаимодействовал с этой библиотекой, использовал её - останется в неприкосновенности. Мне кажется, это актуально при написании больших распределённых систем, скажем, на Web-сервисах - им можно передавать параметры в таких бинах, что в ряде случаев было бы удобно.
Thanx ![]() -------------------- |
|||
|
||||
COVD |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1655 Регистрация: 26.7.2005 Репутация: 17 Всего: 43 |
Тут возникают ассоциации с мессаджинг архитектурой (уж не знаю, как это точно называется). Бин, несущий в себе параметры, путешествует через цепочку компонентов, и каждый компонент берет из бина то, что ему надо. В этом случае добавление нового параметра в бин затрагивает только компонент, в нем заинтересованный. |
|||
|
||||
batigoal |
|
|||
![]() Нелетучий Мыш ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6423 Регистрация: 28.12.2004 Где: Санктъ-Петербургъ Репутация: 24 Всего: 151 |
1. Статья - отличная, идея - тоже. Спасибо.
2. Ты говоришь о том, что нужно ослаблять связи между разработчиком класса и его пользователями. Честно говоря, я не совсем понял этой идеи. Ведь как не крути, для использования класса пользователю все равно придется знать и уметь использовать все возможные сеттеры-геттеры. 3. Возожно, ухудшается читабельность кода, но это спорный вопрос. Скорее, все-таки, нет. P.S. В свете статьи возможность инициализации передаваемых параметров с помощью нотации имен, как в PL/SQL, смотрится весьма привлекательно. -------------------- "Чтобы правильно задать вопрос, нужно знать большую часть ответа" (Р. Шекли) ЖоржЖЖ |
|||
|
||||
Platon |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1801 Регистрация: 25.4.2006 Репутация: 16 Всего: 40 |
Ничего себе! Так вот кто был автором цепочного стиля и у кого Hibernate переняли мысли! Здорово!
|
|||
|
||||
fixxer |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 672 Регистрация: 14.9.2006 Где: Саратов, Россия Репутация: 6 Всего: 27 |
Как всегда, все уже украдено до нас. http://martinfowler.com/dslwip/MethodChaining.html
-------------------- ![]() |
|||
|
||||
Shurr |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 112 Регистрация: 24.10.2006 Репутация: 5 Всего: 7 |
Статья Фаулера датирована августом 2006, а данный топик - февралем 2005-го. Так что неизвестно еще, кто у кого "придумал". ![]() |
|||
|
||||
Platon |
|
||||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1801 Регистрация: 25.4.2006 Репутация: 16 Всего: 40 |
Это всё клёво, но вот у нас случай:
Тут получается проблемка:
Как бы тут изящества не потерять? Пример с перестановкой сеттеров параметров не предлагать, это частный случай. |
||||
|
|||||
![]() ![]() ![]() |
Правила форума "Java" | |
|
Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic. |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Java: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |