четверг, ноября 29, 2007

Объект с глобальным доступом. Полезные свойства.

Работая с паттерном Singleton в применении к реализации объекта с глобальным доступом, неожиданно наткнулся на полезное его свойство - возможность легко передавать данные между совершенно несвязанными и далеко друг от друга располагающимися объектами.

* * *

И синхронизировать!

* * * UPDATE * * *
Изменение заголовка:
Старый - "Singleton как средство передачи данных между объектами"
Новый - "Объект с глобальным доступом. Полезные свойства."
Причина - неверное использование термина "Singleton"

9 комментариев:

Azar комментирует...

вобщето это свойство побочное
и преимуществом глобальный доступ к экземплеру по сути не является... и при правильной организации архитектуры приложения - не требуется.
Назначение же паттерна строго контроль единственности существования экземпляра.

Racer комментирует...

Да, пожалуй нельзя говорить именно о паттерне Одиночка в таком применении. Скорее это особенность объекта с глобальным доступом.

Честно говоря, у метода, который озаглавливается как реализация паттерна Одиночка (по-видимому как пример реализации) в вышеприведенных статьях, основная цель - определение глобального доступа в объекту с использованием Lazy loading, и контролем единственности от Singleton.

Насчет не требуется - на мой взгляд глобальный доступ многое упрощает, но, безусловно, с оговорками.

alexander nemtsov комментирует...

вообще-то синглтон совсем не предназначен для глобального доступа и такой подход нарушает внутреннюю иерархию.

те, кто рекомендуют синглтон для первого - дают вам очень-очень плохой совет.

Racer комментирует...

Безусловно. Об этом я и говорю.
Слово "ОЗАГЛАВЛИВАЕТСЯ" в моей предыдущей фразе ключевое.
Еще раз напомню статью, в которой идет речь о применении паттерна Одиночка на примере определения глобального доступа к объекту.

Еще момент - можешь перечислить аргументы против использования глобального доступа к объектам?

alexander nemtsov комментирует...

Добрался до обеда и имею немного времени более обстоятельно прокомментировать :)

По порядку. Давайте определимся в терминах.
По моему мнению Синглтон - это порождающий паттерн и частный случай паттерна Фабрика. Его задача - создание гарантированно единственного экземпляра класса. Юрий в своей статье дал целую кучу вариантов реализации синглтона, но по-моему очень мало внимания уделил области его применения и совершенно зря обошел стороной опасность заболеть Синглотонизмом :)

Минусов у глобальных переменных вполне достаточно.

Во-первых, при групповой разработке использование глобальных переменных слишком сильно нагружает ненужными коммуникациями разработчиков. Для того, чтобы не потерять спокойный сон, вам понадобится постоянно спрашивать у каждого участника команды разрешения на использование такой переменной.

Во-вторых, такой подход ведет к огромной головной боли при отладке приложения - нет возможности отследить какой модуль приложения и как меняет глобальную переменную. И какой уж тут спокойный сон!
На самом деле уже одного этого достаточно чтобы отказаться от использования глобала, но я продолжу :)

В-трехих, в контексте проектирования использование глобальных переменных нарушает иерархию приложения. Эдсгер Дейкстра вообще считал использование глобальных переменных одним из самых страшных нарушений дисциплины программирования. И инкапсуляцию придумали вовсе не трусы, а вполне разумные параноики :)

Каждая эта проблема сама по себе - контрольный выстрел в голову глобальной переменной и причина раннего появления седых волос у разработчика :)

Racer комментирует...

Убедительно.
Конечно же глобальные переменные - это пережитки процедурного прошлого.
Однако, хочу заметить, что любой инструмент можно использовать по-разному. Лопата тоже может быть как орудием копания так и оружием пролетариата.

На мой взгляд, вполне допустимо и даже полезно использование глобальных классов для:
- предоставления сервисных функций,
- хранения констант,
- предоставления интерфейса к каким-либо немножественным функциональным модулям.

Вышеприведенные применения, собственно, взяты мной из структуры AS.

В AS3 заметно снизилось число глобальных объектов. Но как от них отказаться совсем? Практика показывает, что никто и не собирается.

К дурацкому примеру, модуль Math. Как отдельно взятому объекту дать возможность использовать его методы? Наследоваться от него? Создавать внутри экземпляр или давать на него ссылку извне?
Ради чего?

Кроме того, если глобальный объект самодостаточен и выполняет строго определенные задачи первые два пункта не являются проблемой.

Про третий пункт спорить не приходится. Всё зависит от сложности проекта и его сроков.

alexander nemtsov комментирует...

Вы слишком контрастно меня трактуете :)

Я совсем не ратую за полный и тотальный запрет статических методов и глобальных переменных. Я и сам с удовольствием использую статичные методы, например для Фабрик :)

Я, как и вы, ратую за взвешенное использование имеющейся лопаты. И, конечно же, я знаю о существовании ситуаций в которых бенефиции, получаемые от непопулярного архитектурного решения перевешивают возможные проблемы.

А для принятия адекватного решения нужно знать не только о плюсах, но и о минусах.

Dan комментирует...

Имел неприятный опыт с глобальным синглтоном.

Делал игру. Решил, что самый главный объект (что-то вроде Application, только называется иначе) будет у меня только один, а к некоторым его свойствам нужно обращаться и из других классов.
Ну и сделал его как синглтон с глобальным доступом.

В некоторых мелких классах, описывающих какие-то какие-то конкретные игровые объекты (например, power-up'ы) обращался к нему.

Затем понадобилось сделать редактор уровней для игры.
Решил перекинуть многие классы из игры в редактор, благо кое-какой функционал должен быть такой же.

А главный-то класс у меня теперь другой! И называется он теперь иначе.
И все эти завязки на глобальный класс встали мне боком.

Racer комментирует...

Спасибо за опыт-сын ошибок трудных.
Теперь будем еще осторожнее!
Еще раз убеждаемся - на глобальные объекты нельзя вешать основной функционал.

Кстати, мой пример успешного пользования глобальных классов - модификация ASBroadcaster (AS2). Любой объект регистрируется в нем и после этого может рассылать сообщения всем остальным зарегистрированным и также принимать от них.
Большинство моих проектов пользовало этот подход и я ниразу не столкнулся с проблемами. Думаю что перенесу его в AS3.