пятница, 13 апреля 2012 г.

История одного синглтона

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

Моё отношение к паттернам проектирования можно описать так.

Вещь, приносящая пользу исключительно на уровне коммуникаций с коллегами. Разговор "на одном языке" значительно упрощает общение и плодотворно влияет на сроки исполнения проектов. Проще употребить слово "синглтон" (простите, я против употребления в русском языке слова "синглетон"), чем три минуты пояснять особенности создания объектов такого класса и не быть полностью уверенным, что тебя поняли правильно.

Представить себе, что изучение паттернов проектирования принесла пользу в индивидуальном программотворчестве мне тяжело. Мне не думается, что какой-то толковый программист, не знакомый с этими самыми паттернами затруднится решить возникшую перед ним задачу, если для её реализации ему понадобится придумать некоторую программную конструкцию, соответствующую одному из паттернов проектирования. Просто решив задачу он не будет знать, что кроме прочего, он написал то, что имеет название в некой классификации программных идей.

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

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

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

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

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

Так как решение это становится все более общим, то и его использование распространяется на все большее количество разного типа программ. Теперь, фактически, я использую его во всех проектах, как в консольных, так и в проектах с GUI. Поэтому код всех других своих библиотек классов, подготовленных для повторного использования, я стал привязывать к этой схеме журналирования.

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

Ход мыслей, который привел к такому решению был, примерно, следующий.

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

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

3. Разместить такой глобальный указатель удобно в заголовочном файле журнала, так как этот файл, так или иначе, подключается к тем файлам библиотеки, которые используют код журнала.

4. Теперь, желательно придумать ход, по которому создание экземпляра журнала автоматически инициализировало бы данный указатель. Можно сделать это в конструкторе, инициализируя глобальный указатель по значению this. Однако это может привести к тому, что, при случайном создании второго объекта журнала, размер неприятностей будет зависеть от схем использования журнала и, хочется подумать над тем, как избежать такой случайной ошибки. Следовательно надо запретить конструктор и создавать объект журнала в отдельной функции (или, что более правильно, в статическом методе) с проверкой на существование экземпляра.

4.1. Надо заметить, что, вообще, повторное использование кода тема особенная и даже делая для себя надо делать "для дураков" при всем уважении к себе любимому.

Вот, собственно, и весь синглтон, без претензии на знание соответствующего паттерна.

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


1 комментарий:

Дмитрий Новиков комментирует...

Пишу на Java Android-приложение для заказа такси фирмы, уже почти завершил работу. Так же понадобилось применение синглтона для инкапсуляции общих данных программы, таких как данные профиля пользователя и некоторые другие. Даже советовался на форуме, так как общие данные в программах на Java использовать не приходилось, а на C++ я обходился глобальными переменными (ну а Delphi - это отдельный разговор, там для этого есть DataModule). Единственный объект с этими данными создается при входе в программу под конкретным аккаунтом и ссылка на него пишется в закрытую статическую переменную класса. Для получения его в любом классе программы используется статический же метода класса getInstance() (естественно, уже после того, как объект создан). Каких-то дополнительных проверок не делается, так как здесь все однозначно: зашел в программу под аккаунтом - объект с общими данными создан.

Вообще, считаю, что паттерны - это несколько громкое слово, тем более для синглтона.