Здравствуйте, AndrewVK, Вы писали:
AVK>>>Верно. И если все важные сценарии покрыты ...
L>>То это не гарантирует
AVK>А гарантии никто и не обещал. Когда мы имеем дело с багами , речь может идти только о вероятности.
L>>, что не поломались непокрытые сценарии. О чем собственно спор?
AVK>В том, что хорошие тесты дадут неплохую уверенность в том, что рефакторинг ничего в очередном релизе не поломает.
С такой формулировкой я согласен. Но она несколько отличается от того, что было написано несколькими постами выше.
AVK>>>Он так же гарантирует, что через некоторое время ты утонешь под ошибками, вызванными добавлением фич.
L>>Да, так и есть. Но это совсем другая история.
AVK>Это как раз та самая история.
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, gandjustas, Вы писали:
AN>>>>>А если инициализация может быть различной? G>>>>реализация зависит от интерфейса, если интерфейс может быть реализован как readonly и как mutable, то это плохой интерфейс. AN>>>Допустим логгированием ошибок занимается спец. библиотека, но она не подключилась при инициализации. Ну так и фиг с ней, можно сказать что логгирования не будет и продолжить работу. В чем проблема?
G>>Вообще-то про readonly неверно. Синглтон должен быть stateless, иначе надо инжектить экземпляр.
L>А можно подробнее описать почему синлтон должен быть stateless? L>Например, какой-нить CacheManager — отличный претендент на то, чтобы сделать его "синлтоном". Он тоже должен быть stateless?
нет, он не должен быть синглтоном. Посмотри на кеширование в asp.net, там нет синглтонов.
Причиной сложностям является злостное нарушение SRP синглтоном. С одной стороны он предоставляет функционал, с другой стороны является единственной точкой входа в этот функционал.
Если разделить эти обязанности по разным классам, то становится все просто. Для CacheManager надо сделать два класса: собственно CacheManager и CacheManagerFactory, который возвращает экземпляр. В случае IoC фабрика находится в контейнере. И никаких проблем с тестирование как у ТС не будет.
Здравствуйте, gandjustas, Вы писали:
G>>>Вообще-то про readonly неверно. Синглтон должен быть stateless, иначе надо инжектить экземпляр.
L>>А можно подробнее описать почему синлтон должен быть stateless? L>>Например, какой-нить CacheManager — отличный претендент на то, чтобы сделать его "синлтоном". Он тоже должен быть stateless?
G>нет, он не должен быть синглтоном. Посмотри на кеширование в asp.net, там нет синглтонов.
Это ответ на какой-то другой вопрос. Я спрашивал, почему "синлтон должен быть stateless", а не "может ли CacheManager быть не singleton-ом"
G>Причиной сложностям является злостное нарушение SRP синглтоном. С одной стороны он предоставляет функционал, с другой стороны является единственной точкой входа в этот функционал.
Мне кажется, тут идет смешение понятий 1) singlton-а как объекта, которые может существовать только в одном экземпляре 2) реализации singlton-а, предложеной в GoF.
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, gandjustas, Вы писали:
G>>нет, он не должен быть синглтоном. Посмотри на кеширование в asp.net, там нет синглтонов.
AVK>Там как раз таки есть синглтон.
Это не синглтон ни разу.
1) У HttpContext есть публичный конструктор. То есть не является единственной точкой входа.
2) HttpContext.Current не является глобальным объектом и предназначен именно для того чтобы получить текущий контекст, а не "единственный экземпляр глобального объекта".
AVK> А именно HttpContext.Current. И из-за этого самого синглтона МС пришлось изрядно поплясать с бубном несколько позже.
Ты о чем?
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, gandjustas, Вы писали:
G>>>>Вообще-то про readonly неверно. Синглтон должен быть stateless, иначе надо инжектить экземпляр.
L>>>А можно подробнее описать почему синлтон должен быть stateless? L>>>Например, какой-нить CacheManager — отличный претендент на то, чтобы сделать его "синлтоном". Он тоже должен быть stateless?
G>>нет, он не должен быть синглтоном. Посмотри на кеширование в asp.net, там нет синглтонов.
L>Это ответ на какой-то другой вопрос. Я спрашивал, почему "синлтон должен быть stateless", а не "может ли CacheManager быть не singleton-ом"
Ну так ты привел не подходящий для синглтона тип.
G>>Причиной сложностям является злостное нарушение SRP синглтоном. С одной стороны он предоставляет функционал, с другой стороны является единственной точкой входа в этот функционал.
L>Мне кажется, тут идет смешение понятий 1) singlton-а как объекта, которые может существовать только в одном экземпляре 2) реализации singlton-а, предложеной в GoF.
Чтобы объект существовал в единственном экземпляре надо
1) Не иметь публичного конструктора
2) Уметь получать экземпляр
Если попробовать сделать все в одном классе, то получится GoF-синглтон.
Я же говорю что нет смысла объединять решение этих двух задач.
Более того, применяя DIP и абстрагируясь от конкретного класса синглтона, нет необходимости неиметь публичного конструктора.
И все проблемы синглтона улетучиваются.
Здравствуйте, gandjustas, Вы писали:
AVK>>Там как раз таки есть синглтон.
G>Это не синглтон ни разу.
Ага, не верь глазам своим.
G>1) У HttpContext есть публичный конструктор. То есть не является единственной точкой входа.
Это не изначает, что это не синглтон.
G>2) HttpContext.Current не является глобальным объектом и предназначен именно для того чтобы получить текущий контекст, а не "единственный экземпляр глобального объекта".
Забавная софистика.
AVK>> А именно HttpContext.Current. И из-за этого самого синглтона МС пришлось изрядно поплясать с бубном несколько позже. G>Ты о чем?
К примеру, HttpApplicationStateBase, думаешь, от хорошей жизни пришлось добавить?
... << RSDN@Home 1.2.0 alpha 5 rev. 27 on Windows 7 6.1.7601.65536>>
Здравствуйте, gandjustas, Вы писали:
G>>>нет, он не должен быть синглтоном. Посмотри на кеширование в asp.net, там нет синглтонов.
L>>Это ответ на какой-то другой вопрос. Я спрашивал, почему "синлтон должен быть stateless", а не "может ли CacheManager быть не singleton-ом" G>Ну так ты привел не подходящий для синглтона тип.
Тип вполне подходящий, от того, что возможна другая реализация, вовсе не следует, что первоначальная реализация не подходит.
G>>>Причиной сложностям является злостное нарушение SRP синглтоном. С одной стороны он предоставляет функционал, с другой стороны является единственной точкой входа в этот функционал.
L>>Мне кажется, тут идет смешение понятий 1) singlton-а как объекта, которые может существовать только в одном экземпляре 2) реализации singlton-а, предложеной в GoF.
G>Чтобы объект существовал в единственном экземпляре надо G>1) Не иметь публичного конструктора G>2) Уметь получать экземпляр
G>Если попробовать сделать все в одном классе, то получится GoF-синглтон.
G>Я же говорю что нет смысла объединять решение этих двух задач.
Под singleton-ом я прежде всего имел в виду объект, которые может существовать исключительно в одном экземпляре.
Реализация, предложенная в GoF — одна из возможных, можно сделать так, можно и путем выноса функционала в фабрику.
Есть какие-нибудь причины, почему такой синглтон обязательно должен быть stateless?
O>>Скрипты вытаскивают из базы данных то, что им требуется, а затем эти временные переменные исчезают. O>>Почему бы всю программу не построить таким образом? Всё равно, на каком языке, и необязательно под Web.
L>И как все перечисленное связано с советом явно передавать контекст?
Никак. Я это написал к тому, что лучше доставать данные из базы, а не удерживать их в памяти постоянно.
Но т.к. откуда-то надо будет взять ID соединения с базой данных, то его надо будет хранить в общем дереве, а ссылку на корень этого дерева передавать от функции к функции.
Здравствуйте, os24ever, Вы писали:
L>>И как все перечисленное связано с советом явно передавать контекст?
O>Никак. Я это написал к тому, что лучше доставать данные из базы, а не удерживать их в памяти постоянно. O>Но т.к. откуда-то надо будет взять ID соединения с базой данных, то его надо будет хранить в общем дереве, а ссылку на корень этого дерева передавать от функции к функции.
Здравствуйте, Lloyd, Вы писали:
L> AVK>В том, что хорошие тесты дадут неплохую уверенность в том, что рефакторинг ничего в очередном релизе не поломает. L> С такой формулировкой я согласен. Но она несколько отличается от того, что было написано несколькими постами выше.
Да то же и было написано, но ты под "гарантией" понял не "обоснованную уверенность", а "наличие доказательства".
L> AVK>Это как раз та самая история. L> Нет, это совсем другая история.
Я с AVK согласен. А ты что имеешь в виду?
Здравствуйте, os24ever, Вы писали:
o> Взять хотя бы любой форум. Ведь он не хранит состояние.
Как минимум — авторизованный аккаунт.
И вообще вся http-сессия, а если вдруг понадобится некий многошаговый визард из нескольких страниц...
В общем, в подавляющем случае состояние есть, оно не может не есть.
Здравствуйте, ., Вы писали:
L>> AVK>В том, что хорошие тесты дадут неплохую уверенность в том, что рефакторинг ничего в очередном релизе не поломает. L>> С такой формулировкой я согласен. Но она несколько отличается от того, что было написано несколькими постами выше. .>Да то же и было написано, но ты под "гарантией" понял не "обоснованную уверенность", а "наличие доказательства".
Все-таки не совсем то же:
Тесты — как раз такое доказательство
L>> AVK>Это как раз та самая история. L>> Нет, это совсем другая история. .>Я с AVK согласен. А ты что имеешь в виду?
По поводу чего? По поводу того, что "наличие тестов не гарантирует отсутствие поломок при рефакторинге" и "без рефакторинга рано или поздно утонешь под ошибками" — мало связаные друг с другом "истории"?
Здравствуйте, ., Вы писали:
o>> Взять хотя бы любой форум. Ведь он не хранит состояние. .>Как минимум — авторизованный аккаунт. .>И вообще вся http-сессия, а если вдруг понадобится некий многошаговый визард из нескольких страниц...
Не совсем. Сессия вытаскивается из session store по ключу, который приходит от клиента. Отличий от базы практически нет.
.>В общем, в подавляющем случае состояние есть, оно не может не есть.
o>> Взять хотя бы любой форум. Ведь он не хранит состояние. .>Как минимум — авторизованный аккаунт. .>И вообще вся http-сессия, а если вдруг понадобится некий многошаговый визард из нескольких страниц...
.>В общем, в подавляющем случае состояние есть, оно не может не есть.
Данные в базе — это "внешняя среда", её менять можно
На самом деле, я понятия не имею, где проходит граница между внутренним состоянием программы и её внешней средой (ведь можно сказать, что и SQL-сервер — это такой объект, существующий в единственном числе, синглтон — и что он часть программы). Если есть какие-то статьи на эту тему, бросайте ссылки!
Здравствуйте, AlexNek, Вы писали:
AN> .>Такой код быть не может, скорее всего это фрагмент какой-то. AN> А что это меняет?
Появляется смысл в приведённом примере. Ладно, не важно в данном случае.
AN> Каким образом, где и когда? Как достучаться до контейнера?
До контейнера не надо стучаться, принцип IoC как раз и говорит, что его не зовут, а он сам приходит когда надо.
AN> Кто дасть гарантию правильной инициализации errorManager?
Контейнер. Уж явно это не дело это errorManager-а.
AN> Что делать если он не иницилизирован по какой либо причине?
Падать с громким грохотом.
AN> .>Для тестов можно их создавать несинглтонно. AN> .>Ведь самому FileImporter совершенно по барабану сколько реально экземпляров ErrorManager существует, вот и не надо заставлять класс делать то, что ему делать не положено. AN> Он всего лишь вызывает "глобальную функцию".
Такие функции могут быть только чистыми. Им снова по барабану сколько экземпляров существует.
O>>Никак. Я это написал к тому, что лучше доставать данные из базы, а не удерживать их в памяти постоянно. O>>Но т.к. откуда-то надо будет взять ID соединения с базой данных, то его надо будет хранить в общем дереве, а ссылку на корень этого дерева передавать от функции к функции.
L>По-моему, это не дерево, а трава.
А как ещё передавать контекст выполнения, кроме как в виде указателя (ну или ссылки) на дерево структур данных (объектов, записей в именованном массиве, списке, хеше и т.д.)
IMHO, должно быть примерно так:
Общее дерево
+ Окна, созданные программой
+ Главное окно
+ Закладки
+ ...
+ Окно диалога
+ Окно диалога
+ Интегралы и дифференциалы, посчитанные программой
+ Настройки соединения с базой данных
+ Настройки логгера
+ ...
Если в каком-то месте программы нужен логгер — вызываем его со ссылкой на общее дерево, дальше он разбирается сам.
Настройки менять нельзя, у них флажки "final" и "protected".
Здравствуйте, os24ever, Вы писали:
L>>По-моему, это не дерево, а трава.
O>А как ещё передавать контекст выполнения, кроме как в виде указателя (ну или ссылки) на дерево структур данных (объектов, записей в именованном массиве, списке, хеше и т.д.)
O>IMHO, должно быть примерно так: O>
Всё, я сдаюсь! У меня больше нет идей
L>О чем вообще речь идет?
О переменных в программе...
O>>Если в каком-то месте программы нужен логгер — вызываем его со ссылкой на общее дерево, дальше он разбирается сам.
L>Зачем логгеру какое-то дерево?
Здравствуйте, AndrewVK, Вы писали:
AVK>Здравствуйте, AlexNek, Вы писали:
AN>>Мы не скатываемся случаем в спор "Goto да или нет"?
AVK>Это уж ты сам смотри.
По крайней мере навеяло.
AN>>Альтернатива создания дополнительного поля никак не прельщает.
AVK>Ну конечно, публичное статическое состояние куда лучше.
Обычно из двух зол выбирают наименьшее.
Что мы получаем в другом случае?
— Любой объект должен иметь дополнительное поле которое нужно вовремя и правильно инициализировать. Так как фиг знает когда именно понадобится ентот объект.
Раньше конструктора это не получится, значит статические поля с "классовыми" инициализаторами нужно также как то убирать. А в статические функции добавлять "лишний" параметр.
— наличие "указателя" подразумевает его проверку на ноль и какое то приемлимое поведение в этом случае.
Опять таки при каждом использовании желательно это делать.
Получается обычное "засорение кода".
AVK>>>Тут, как бы, большинство над коммерческими проектами работает. Так что не удивил. AN>>То бишь считаешь что полное изменение концепта работы программв не будет играть никакой роли и любое начальство будет всегда за?
AVK>Для истребления синглтонов не нужно "полное изменение концепта работы программв". Нужно всего лишь отрефакторить места вызова синглтона и обеспечить передачу контекста в нужные точки (что в любом случае будет очень полезно, не только для устранения синглтонов).
для меня это именно "полное изменение концепта работы программы". Вместо давно знакомого вызова в одну строку нужно делать кучу действий и протаскивать контектст во все дырки. Особенно много удовольствия можно будет получить в наших виртуальных функциях для сторонних библиотек.
Ты еще забыл о правке тестов. AVK>Синглтон — это злостная программерская халтура, проистекающая от нежелания совсем чуть чуть подумать, и оправдания этой халтуре за редчайшими исключениями нет.
Так микрософт схалтурил с settings или это редчайшее исключение?
А какие есть еще варианты кроме как везде таскать за собой "указатель"?
AN>>К этому, еще провокационный вопрос — отчего в "официальном Янусе" остались синглтоны?
AVK>От того, что их некому вычистить. Там, где я код правлю, я стараюсь их- убрать. Раньше их было намного больше.
Получается, что с ними все же можно жить и это не вопрос жизни или смерти, а всего лишь вопрос ресурсов и времени?
AN>> (Не смотрел последние версии, но не думаю что в этом направлении, что то изменилось).
AVK>Это не вопрос твоих дум, это факт — количество синглтонов со временем там уменьшается, новых не появляетсмя вовсе. Замечание было на тот случай, если бы в этом году были убраны последние.
У нас вроде также синглтоны не растут грибами. Специально не охотился на них, но точно знаю только о двух.