ох вопрос наверное детский и сто раз обсужден, ткните если че
накидайте названия паттернов обеспечивающих красивое взаимодействие модулей/объектов между собой
итак, задача.
дано:
1) некий объект хранящий состояние
2) интерфейс/другой объект меняющий состояние объекта 1)
3) другие объекты реагирующие на изменение состояния объекта 1)
Решения
1) в интерфейсе/объекте 2) берем ссылку на объект 1) меняем состояние и оповещаем объекты 3) паттерном наблюдатель. минусы — прямой доступ к объекту 1) из 2) т.е. связность
2) делаем некую команду, бросаем ее из интерфейса/объекта 2) в некий глобальный диспетчер, она ловится в объекте 1) меняет свое состояние и дальше наблюдателем всех оповещает. вроде как то красивее, типа ввели уровень абстракции в виде команды, бла бла бла, или нет?
на каждый чих заводить эту самую команду — боюсь расплодится их, или нет?
3)
Здравствуйте, Quadri, Вы писали:
Q>накидайте названия паттернов обеспечивающих красивое взаимодействие модулей/объектов между собой
It depends. Без знания конкретного языка и решаемой проблемы ничего полезного посоветовать нельзя. Команды и глобальный диспетчер — это уже перебор по-моему
Более-менее распространённое решение — объекты из (3) подписываются на изменение значения (1), объекты из (2) просто изменяют значения (1).
Здравствуйте, Quadri, Вы писали:
Q>ох вопрос наверное детский и сто раз обсужден, ткните если че
Q>накидайте названия паттернов обеспечивающих красивое взаимодействие модулей/объектов между собой
Q>итак, задача. Q>дано: Q>1) некий объект хранящий состояние Q>2) интерфейс/другой объект меняющий состояние объекта 1) Q>3) другие объекты реагирующие на изменение состояния объекта 1)
Q>Решения Q>1) в интерфейсе/объекте 2) берем ссылку на объект 1) меняем состояние и оповещаем объекты 3) паттерном наблюдатель. минусы — прямой доступ к объекту 1) из 2) т.е. связность Q>2) делаем некую команду, бросаем ее из интерфейса/объекта 2) в некий глобальный диспетчер, она ловится в объекте 1) меняет свое состояние и дальше наблюдателем всех оповещает. вроде как то красивее, типа ввели уровень абстракции в виде команды, бла бла бла, или нет? Q>на каждый чих заводить эту самую команду — боюсь расплодится их, или нет? Q>3)
Ваша идея с командами это та же сообщения на общей шине, нафиг так делать непонятно.
Ваш дизайн и паттернизация исключительно зависят от объемов кода, на каком уровне это все делается и т.д.
В вашей задаче все просто, исходя из вашего описания.
1. Есть объект который хранит И! меняет свое состояние, в соответствии со своими правилами (контрактом). И упаси вас сразу применять к нему паттерн стейт Model
2. Есть некоторый объект который вызывает методы у Model, это например Controller/Manager.
3. Есть клиенты у объекта Model которые слушают его изменение, более того детальность оповещения целиком и полностью зависит от задачи, может быть одно общее событие Changed, также могут быть более детальные.
Обзервер здесь нужен тогда и только тогда, когда число подписчиков динамически меняется и заранее не известно. А так достаточно передетать CallBack
Уменьшение связанности можно достичь за счет выделения абстракций.
Например есть интерфейс IModel и IModelNotifier , их реализует один класс Model:IModel, IModelNotifier. Controller/Manager работает только с IModel и ничего не знает про события. LIstener'у передается IModelNotifier и IModel, он подписывается на события от IModelNotifier и по событию опрашивает модель.
может быть по другому
Controller по прежнему работает с IModel. Делается обертка над IModel типа ModelWrapper которая в конструкторе принимает интерфейс CallBack'ов ICallback и сам интерфейс IModel и по изменениям вызывает у себя ICallback.Changed(), LIstener реализует ICallback и в колбеке также опрашивает IModel на нужные значения.
Но если кода мало, и нет встроенных механизмов подписки отписки, то я бы ограничился колбеками и выкинул бы все интерфейсы, работал бы напряму с типами.
Связанность это не когда каждый тип знает о типе другого, а когда невозможно понять что за абстрактный тип данных (в нем мешанина), какой он реализует интерфейс, и чем у него определяется состояние.
Если код написан хорошо, выделить интерфейсы особых проблем не составляет, если код говно, то мнимое стремление к слабой связанности еще и ухудшит этот код избыточными сущностями, как в вашем примере команда.
Я применял команду только в рамках UI когда одно и тоже действие может быть и в тул баре и в меню и на кнопке и вообще где угодно, в других случаях я не считал что паттерн комнада будлет уместным.
И вообще на начальном этапе забудьте о паттернах. Они нужны в сложном коде и возникают как правило либо в ходе рефакторинга либо в ревью дизайна и прототипе.
Здравствуйте, Quadri, Вы писали:
Q>накидайте названия паттернов обеспечивающих красивое взаимодействие модулей/объектов между собой
В добавление по ответам ув. Sharov и diez_p. Из печального опыта — не пытайтесь подогнать проблему под какой-то паттерн/набор паттернов. Да, при известном везении на выходе получается прекрасный сфероконический код, только пользоваться им будет практически нереально.
В том же дотнете оповещение о событиях можно реализовать навскидку 3-5 способами (события, IObservable, передача callback-а (интерфейса), команды, DependencyProperty, что ещё?). В большинстве случаев хватит первых двух, в редких исключениях — вреда от них будет больше чем пользы. И да, все эти способы вполне можно обозвать реализацией обсервера и годами холиварить что из них правильнее. Только саму проблему это решить не поможет никак.
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, Quadri, Вы писали:
Q>>накидайте названия паттернов обеспечивающих красивое взаимодействие модулей/объектов между собой
S>В добавление по ответам ув. Sharov и diez_p. Из печального опыта — не пытайтесь подогнать проблему под какой-то паттерн/набор паттернов.
Да нее, не переживайте, я не паттерно-интерфейсо-абстрагирования-дрочер))))) скорее наоборот. просто паттерны имеют названия — удобно общаться, и каждый паттерн обнажает проблему которую решает — этим он и ценен
Здравствуйте, diez_p, Вы писали:
_>Ваш дизайн и паттернизация исключительно зависят от объемов кода, на каком уровне это все делается и т.д.
Да, согласен. Проблема в том что опять хочется запедалить универсальный механизм, стремление к универсализации — комплекс что ли какой-то, борюсь с ним постоянно
_>И вообще на начальном этапе забудьте о паттернах. Они нужны в сложном коде и возникают как правило либо в ходе рефакторинга либо в ревью дизайна и прототипе.
Здравствуйте, Quadri, Вы писали:
Q>Здравствуйте, diez_p, Вы писали:
_>>Ваш дизайн и паттернизация исключительно зависят от объемов кода, на каком уровне это все делается и т.д.
Q>Да, согласен. Проблема в том что опять хочется запедалить универсальный механизм, стремление к универсализации — комплекс что ли какой-то, борюсь с ним постоянно
_>>И вообще на начальном этапе забудьте о паттернах. Они нужны в сложном коде и возникают как правило либо в ходе рефакторинга либо в ревью дизайна и прототипе.
Q>Сейчас как раз типа такой этап)
Вот на этом этапе следует сильно задуматься на базовыми абстракциями(по моему чем меньше набор базовых абстракций, тем стройнее получается система), их обязанностями и интрефейсами(набор методов, полей и т.д.) Сделать прототип если надо, набросать UML схему (в примитивном виде) и посмотреть как оно вообще смотрится(логично не логично, избыточно или нет ну и т.д.).
Здравствуйте, Quadri, Вы писали:
Q>Да, согласен. Проблема в том что опять хочется запедалить универсальный механизм, стремление к универсализации — комплекс что ли какой-то, борюсь с ним постоянно
Тогда важен язык+фреймворк+задача. В большинстве случаев велосипеды уже изобретены и вокруг них накручена куча хелперов.
Если задача неизвестна — надо начинать с сценариев использования.
Представьте что ваша механика уже готова и напишите код, который будет её использовать. Плюсы:
1. Сразу вылазят логические и концептуальные несостыковки. Если программировать "от паттерна", то косяки в API вылазят когда уже поздно что-либо менять.
2. При написании собственно кода в голове уже будут держаться спорные и сложные моменты, будет понятно на что надо обращать внимание.
3. Готовые тесты + документация для типовых сценариев использования.
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, Quadri, Вы писали:
Q>>Да, согласен. Проблема в том что опять хочется запедалить универсальный механизм, стремление к универсализации — комплекс что ли какой-то, борюсь с ним постоянно
S>Тогда важен язык+фреймворк+задача. В большинстве случаев велосипеды уже изобретены и вокруг них накручена куча хелперов.
Здравствуйте, Quadri, Вы писали:
S>>Тогда важен язык+фреймворк+задача. В большинстве случаев велосипеды уже изобретены и вокруг них накручена куча хелперов. Q>Java+Android
С явой практически не работал, так что ничего полезного не предложу
1. практически все приложения, которые я видел и в которых одни части системы общались с другими через события (типа "состояние изменилось") были странными, если вы заранее знаете что должно выполняться после чего просто закодируйте это в классах с бизнес-логикой, так чтобы все вызовы были явными
2. одно из приложений, на которых я работал (фактически торговый робот), имело большое количество вычислений, и возможно в таких приложениях сеть классов с бизнес-логикой оказалось бы слишком большой, сложной и плохо перевариваемой,
для этого приложения (и, если я правильно понимаю, это типовое решение) был разработан фреймворк на джаве, который по сути является экселем, все данные обернуты в ячейки, весь код содержится в классах-формулах, приложение конфигурируется — каждой формуле прописываются ячейки как инпуты и аутпуты, таким образом программно очень просто получить список ячеек которые необходимо пересчитать и с помощью каких формул, что является достаточно чистой заменой всей этой суматохи с событиями для каждого объекта
несмотря на огромную кодовую базу (порядка 100мб кода), 10 лет работы в продакшене, 3 поколоения разработчиков со своими идиосинкразиями, с этим приложением до сих пор вполне можно работать (код, конечно, такое же г***о как и везде, но как-то так получается что формулы достаточно независимы и особо не аффектят друг друга)
но тем не менее было бы интересно попробывать переписать это приложение более традиционными способом (п.1) и сравнить