AVK Selected

Показавшиеся интересными, на мой вкус, посты

Синглетон: наследование от базового или пометить опцией?

Аноним Аноним
Добрый день. Создаю свою среду разработки, собственный ОРМ. И вот встала задача, нужен набор независимых классов, представляющих собой СИнглтон. Вот я могу сделать галочку, указывающий что мой класс Синглетон или сделать базовый системный класс, указав который разработчик показывает что данный класс является Синглтон. Как красивее с точки зрения дизайна?
itslave
itslave
17.09.2012 09:25
Здравствуйте, Аноним, Вы писали:

А>Добрый день. Создаю свою среду разработки, собственный ОРМ. И вот встала задача, нужен набор независимых классов, представляющих собой СИнглтон. Вот я могу сделать галочку, указывающий что мой класс Синглетон или сделать базовый системный класс, указав который разработчик показывает что данный класс является Синглтон. Как красивее с точки зрения дизайна?

С точки зрения дизайна красивее не использовать синглетон. Вместо него делать Dependency Injection.
dimgel
dimgel
17.09.2012 09:30
Здравствуйте, itslave, Вы писали:

I>С точки зрения дизайна красивее не использовать синглетон. Вместо него делать Dependency Injection.


Одно другому не противоречит.
itslave
itslave
17.09.2012 11:24
Здравствуйте, dimgel, Вы писали:

D>Здравствуйте, itslave, Вы писали:


I>>С точки зрения дизайна красивее не использовать синглетон. Вместо него делать Dependency Injection.


D>Одно другому не противоречит.

Ну в принципе контейнер инжектируемых обьектов можно рассматривать как реализацию синглтонов.
В классическом же виде обычно DI противопоставляют синглтонам.
Типичное тестовое задание:
void F()
{
 ......
Thread.Sleep(100);
....
}

Как написать тест, который проверяет что именно поток будет спать 100 милисекунд?
dimgel
dimgel
17.09.2012 11:58
Здравствуйте, itslave, Вы писали:

D>>Одно другому не противоречит.

I>Ну в принципе контейнер инжектируемых обьектов можно рассматривать как реализацию синглтонов.

Я имел в виду другое:

Scala:

// боевой код: инъекция зависимостей в параметры конструктора
class C(d: D, e: E) {
    def f = d.f + e.f
}
// синглтон с боевыми зависимостями
object C extends C(D, E)
val x = C.f

// тесты: тестируемый синглтон (или можно класс) с mock-зависимостями
class DMock extends D
class EMock extends E
object CT extends C(DMock, EMock)


PHP:

// боевой код
class C {
    static function instance() {
        static $x;
        if (!$x) {
            $x = new self(D::instance(), E::instance());
        }
        return $x;
    }
    protected function __construct(D $d, E $e) { ... }
    ...
}

// тесты
...
class CT extends C {
    function __construct() {
        parent::__construct(new DMock, new EMock);
    }
}


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

Эта идея изложена в "Programming in Scala" Одерски, там он впрочем чуть по-другому делает, там у него абстрактные поля (т.е. member injection), но по сути то же самое — прямо в коде собирает компоненты, очень похоже на xml-конфиг спринга.
itslave
itslave
17.09.2012 12:02
Здравствуйте, dimgel, Вы писали:

D>Таким образом, в боевом коде все контроллеры — синглтоны, содержащие зависимости по умолчанию, что не мешает в тестах инстанциировать эти же контроллеры с мок-зависимостями.


А если надо замокать вызовы методов самого контроллера?
dimgel
dimgel
17.09.2012 12:06
Здравствуйте, itslave, Вы писали:

I>А если надо замокать вызовы методов самого контроллера?


Наследуешь мок-класс (можно анонимный) из класса контроллера, если я правильно понял вопрос. В общем, всё решается: это полноценный DI, только статически типизированный.
itslave
itslave
17.09.2012 12:10
Здравствуйте, dimgel, Вы писали:

D>Здравствуйте, itslave, Вы писали:


I>>А если надо замокать вызовы методов самого контроллера?


D>Наследуешь мок-класс (можно анонимный) из класса контроллера, если я правильно понял вопрос. В общем, всё решается: это полноценный DI, только статически типизированный.

Т.е. в коде нет вызовов типа Controller.Instance() и доступ к контроллерам происходит тоже посредством внедрения зависимостей?
AndrewVK
AndrewVK
22.09.2012 12:52
Здравствуйте, dimgel, Вы писали:

D>Таким образом, в боевом коде все контроллеры — синглтоны, содержащие зависимости по умолчанию, что не мешает в тестах инстанциировать эти же контроллеры с мок-зависимостями.


Тесты это только часть проблемы. Синглтон, в том числе, не позволяет при необходимости размножить контекст. К примеру, писал ты десктопное приложение, насовал туда синглтонов. Потом пытаешься портировать это все в веб — и опаньки. Нужно копировать на каждый вызов свои экземпляры — куча говнокода. А тут нам еще и асинхронность понадобилась — и еще куча говнокода.
... << RSDN@Home 1.2.0 alpha 5 rev. 65 on Windows 8 6.2.9200.0>>
dimgel
dimgel
22.09.2012 12:58
Здравствуйте, AndrewVK, Вы писали:

AVK>Тесты это только часть проблемы. Синглтон, в том числе, не позволяет при необходимости размножить контекст. К примеру, писал ты десктопное приложение, насовал туда синглтонов. Потом пытаешься портировать это все в веб — и опаньки. Нужно копировать на каждый вызов свои экземпляры — куча говнокода. А тут нам еще и асинхронность понадобилась — и еще куча говнокода.


Интересно, сам я пока что видимо не сталкивался. Как столкнусь — выработаю более подходящий подход, через цепь рефакторингов придя ещё к какому-нибудь общеизвестному баззворду.
AndrewVK
AndrewVK
22.09.2012 01:01
Здравствуйте, dimgel, Вы писали:

D>Интересно, сам я пока что видимо не сталкивался. Как столкнусь — выработаю более подходящий подход, через цепь рефакторингов придя ещё к какому-нибудь общеизвестному баззворду.


Да не надо никаких баззвордов, надо просто контекст передавать явно. За счет совсем небольшого увеличения кода получаем полное решение подобных проблем. А DI (где I означает injection) нужно применять тогда и только тогда, когда динамическая сборка приложения из модулей фигурирует в исходных требованиях.
... << RSDN@Home 1.2.0 alpha 5 rev. 65 on Windows 8 6.2.9200.0>>
dimgel
dimgel
22.09.2012 01:01
Здравствуйте, AndrewVK, Вы писали:

AVK>А тут нам еще и асинхронность понадобилась — и еще куча говнокода.


Но кстати, если под асинхронностью понимается многопоточность — то синглтоны работают вполне: если их делать stateless-контроллерами, гоняющими данные между собой.
AndrewVK
AndrewVK
22.09.2012 01:09
Здравствуйте, dimgel, Вы писали:

D>Но кстати, если под асинхронностью понимается многопоточность — то синглтоны работают вполне: если их делать stateless-контроллерами, гоняющими данные между собой.


stateless синглтоны это оксюморон. Стейт все равно где то должен быть. Для многопоточных решений, конечно, можно static заменить на thread static, но это другие проблемы порождает.
... << RSDN@Home 1.2.0 alpha 5 rev. 65 on Windows 8 6.2.9200.0>>
gravatar
Аноним
17.09.2012 09:42
А>>Добрый день. Создаю свою среду разработки, собственный ОРМ. И вот встала задача, нужен набор независимых классов, представляющих собой СИнглтон. Вот я могу сделать галочку, указывающий что мой класс Синглетон или сделать базовый системный класс, указав который разработчик показывает что данный класс является Синглтон. Как красивее с точки зрения дизайна?
I>С точки зрения дизайна красивее не использовать синглетон. Вместо него делать Dependency Injection.

Хорошо, опишу по другому. Есть набор классов, которые должны существовать только в 1 экземпляре. Например, юзеру нужно вводить описание назначения программы (версию и проч), которое будет выводится при запуске. Гарантированно что будет только 1 описание. Вот мне надо в моей среде пометить что класс может иметь только 1 экз. Вот и вопрос как это с точки зрения архзитектуры? Сделать галочку Синглетон или сделать баз системный класс от которого какбы унасоледованы все синглетоны
dimgel
dimgel
17.09.2012 09:52
Здравствуйте, Аноним, Вы писали:

А>Сделать галочку Синглетон


100500 раз уже перетирали, что тупое текстовое редактирование программы сто крат удобнее, и никакими "галочками", "синтаксическими деревьями" и т.п. его не заменить. Что-то не гуглится, но помню, что последний раз это было с подачи Лаптева.
itslave
itslave
17.09.2012 11:25
Здравствуйте, Аноним, Вы писали:

А>Хорошо, опишу по другому. Есть набор классов, которые должны существовать только в 1 экземпляре. Например, юзеру нужно вводить описание назначения программы (версию и проч), которое будет выводится при запуске. Гарантированно что будет только 1 описание. Вот мне надо в моей среде пометить что класс может иметь только 1 экз. Вот и вопрос как это с точки зрения архзитектуры? Сделать галочку Синглетон или сделать баз системный класс от которого какбы унасоледованы все синглетоны

А что делать если обьект уже, до поставления галочки, существует более чем в одном экземпляре?
По хорошему тебе нужна фабрика и от же неявный синглтон через DI.
johny5
johny5
28.09.2012 06:37
Здравствуйте, Аноним, Вы писали:

А> Как красивее с точки зрения дизайна?


Помоему без разницы как там красивее, дизайн ведь определяется с точки зрения use cases? Оттого как будет класс использоваться и запращиваться пропертя, так и пляшите.
MaximVK
MaximVK
05.10.2012 05:51
Здравствуйте, johny5, Вы писали:

J>Помоему без разницы как там красивее, дизайн ведь определяется с точки зрения use cases? Оттого как будет класс использоваться и запращиваться пропертя, так и пляшите.

Есть же еще и инженерная красота. Насколько хорошо дизайн соответствует use cases, настолько красивым будет решение, разве нет? С опытом появляется и обратная связь — интуитивное чувство красоты инженерного решения, если угодно. «Некрасивые самолеты не летают» (с) А.Н.Туполев. Другое дело, что автор ничего про use cases не сказал, ну и да, синглтон и как виски то не очень, а как паттерн совсем бестолков.
johny5
johny5
05.10.2012 06:07
Здравствуйте, MaximVK, Вы писали:

MVK>Здравствуйте, johny5, Вы писали:


MVK>Есть же еще и инженерная красота. Насколько хорошо дизайн соответствует use cases, настолько красивым будет решение, разве нет? С опытом появляется и обратная связь — ...


ИМХО есть такое, что видя подобную задачу хочется применить готовое красивое решение, но как раз опыт показывает что это чревато. Весь демон как обычно в деталях. Сначала всё таки нужно разобрать use case-ы, а опыт, ака интуитивное чувство красоты, лишь поможет убыстрить процесс создания заточенного под задачу решения.
MaximVK
MaximVK
23.11.2012 01:55
Здравствуйте, johny5, Вы писали:

MVK>>Есть же еще и инженерная красота. Насколько хорошо дизайн соответствует use cases, настолько красивым будет решение, разве нет? С опытом появляется и обратная связь — ...


J> ИМХО есть такое, что видя подобную задачу хочется применить готовое красивое решение, но как раз опыт показывает что это чревато. Весь демон как обычно в деталях. Сначала всё таки нужно разобрать use case-ы, а опыт, ака интуитивное чувство красоты, лишь поможет убыстрить процесс создания заточенного под задачу решения.


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