Здравствуйте, Tom, Вы писали:
WH>>И тут тоже глобальная переменная. Tom>Ээээ, причём тут глобальные преременные. Tom>Я совсем про другую проблему вещаю.
DateTime.UtcNow обращается к статической переменной, которая постоянно меняется.
Например код который лезет в базу и в зависимости от значения в базе что то делается.
Код в базу может залезть только через некий глобальный контекст, который может лежать только в глобальной переменной.
Обе проблемы действительно лечатся через DI/IoC.
Ибо глобальный контекст заменяется на локальный.
Tom>Я про то что статические методы ставят крест на DI/IoC и убивают все прелести данных патернов
В качестве контр примера возьмём System.Linq.Enumerable.
Он состоит из статических методов чуть более чем полностью.
Скажи, какие проблемы вызывают эти статические методы.
И нахрена им DI/IoC?
... << RSDN@Home 1.2.0 alpha 5 rev. 62>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, Tom, Вы писали:
Tom>Ээээ? Реч идёт про статические функции? Я привёл пример, почему я должен другой давать — непонимаю.
Речь идет о детерминированных статических функциях без побочных эффектов.
Давай я тебе помогу. Допустим, мы используем некую библиотеку по решению СЛАУ. Библиотека представляет собой набор чистых статических функций. Используем мы ее напрямую в классах логики. И вот захотелась нам заменить библиотеку на другую (более оптимизированную и т.п.). Упс, придется менять наши классы, а можно было бы просто проинжектить другую реализацию, если бы было true DI...
Только к вопросу юнит-тестируемости это отношение не имеет. Зачем тебе тестировать случай "а что будет, если при данных входных параметрах функция вернет такой-то другой результат или выбросит исключение?". Функции чистые, никакой другой результат при данных параметрах они вернуть не могут. Единственная возможная проблема (для тестов) тут может возникнуть, если функции выполняются дооооолго. Тогда да, для юнит-тестов оно неприемлимо. Но это экзотика.
Tom>Хотя дать другой — вариантов куча. Например код который лезет в базу и в зависимости от значения в базе что то делается. Tom>Соответственно нам надо эмулировать различный результат...
Мы про чистые функции? Тогда о доступе к базе лучше не вспоминать. Или у нас вызывается хранимка, которая является (!) чистой функцией?
Не, конечно бывают и такие случаи. Тут да, неудобство — придется на билд-сервере ms sql ставить, настраивать и т.п. Но это ВАЩЕ экзотика.
Tom>Ключевое слово тут эмулировать. Если код написан в статическом методе — то он гвоздями прибит и никакими легитимными способами поменять его поведение нельзя. Tom>Под легитимными понимается применение DI патерна
public static TValue GetOrAdd<TKey, TValue>(this Dictionary<TKey, TValue> @this, TKey key, Func<TKey, TValue> valueFactory)
{
TValue value;
if (!@this.TryGetValue(key, out value))
@this.Add(key, value = valueFactory(key));
return value;
}
Нафига вот тут менять поведение? Причем эта функция даже "не совсем" чистая.
Re[10]: Статические методы в любом их обличии это зло!
H>DI/IoC нужен далеко не всегда, говорю как человек с диагнозом "ООП головного мозга".
DI/IoC кстате к ООП не имеет отношения никакого. особенно если учитывать что DI без SRP не работает нормально.
А SRP это уже совсем не ООП. Но это отступление.
В целом я стараюсь DI не использовать только там где это вообще не имеет смысла, например для создания POCO обьектов.
Хотелось бы услышать где это не имеет места ещё
Народная мудрось
всем все никому ничего(с).
Re[5]: Статические методы в любом их обличии это зло!
Здравствуйте, Tom, Вы писали:
Tom>Допустим у нас есть код некоего билинга который использует статические функции: Tom>Наша задача покрыть функцию тестами, в данном случае есть 2 ветвления логики. Tom>Прошу не стесняться и рассказать мне как вы напишете тесты в данной реализации функции с использованием статических методов...
Tom>
Tom>void MakePayment(int account, DateTime paymentDate)
Tom>{
Tom> var now = DateTime.UtcNow;
Tom> if (now > paymentDate)
Tom> {
Tom> // some logic
Tom> }
Tom> else
Tom> {
Tom> // another logic
Tom> }
Tom>}
Tom>
Здравствуйте, Tom, Вы писали:
J>>Элементарно: Tom>А если там будут более конкретные проверки. Tom>Например проверка даты, числа, часа...
Все то же самое Или ты имеешь в виду код типа DateTime.UtcNow.Hour < 15? Ну да, такое по-человечески не оттсетировать никак. Только хз, при чем тут статические методы
ЗЫ На самом деле это можно оттестировать, я это прямо сейчас на работе делаю — у нас просто время не дергается каждый раз системное, а зовется только один раз в начале цикла и сохраняется в переменную, которую уже все остальные используют. Так что записать в эту переменную что-то другое и потестировать разные моменты времени совершенно не проблема. Но, опять же, это все никак со статическими методами не связано — эта переменная может быть и статическим мполем класса, и обычным.
Здравствуйте, Tom, Вы писали:
Tom>Думаем что статические методы в любом их обличии это зло, будь то в классах и тем более в интерфейсах.
Статические методы — это по сути методы вложенного в класс (ассоциированного с классом) синглетона. Кстати, в Scala нет статических методов, но есть companion object (а object в Scala это singleton) с тем же именем , имеющий доступ к полям/методам класса.
От того, что в других языках так не сделано, суть не меняется. В scala просто довели эту концепцию до логического завершения.
Поэтому в некотором смысле статических методов нет, это методы синглетона. А статические поля — это его поля. И конструктор статический (где он есть) ту же роль играет.
Я не думаю, что ошибочна концепция синглетона.
Я не думаю, что один из основных принципов Scala ошибочен.
With best regards
Pavel Dvorkin
Re[7]: Статические методы в любом их обличии это зло!
Здравствуйте, Tom, Вы писали:
Tom>Т.е. если ты считаешь что в тестах никогда не надо подменять поведение даже строго детерминированной функции то можно считать что статические функции ок.
Ну, вот зачем, например, подменять поведение функции, вычисляющей синус?..
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[8]: Статические методы в любом их обличии это зло!
Здравствуйте, AlexRK, Вы писали:
ARK>А почему операция должна быть статической? Если только из-за кривизны конкретного языка, в котором она определяется только так и не иначе.
Ну по логике. Скажем вот + -- это должен быть метод левого аргумента или правого?..
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[13]: Статические методы в любом их обличии это зло!
Здравствуйте, AlexRK, Вы писали:
_NN>>А вот скажем пример типа Complex/BigInteger . _NN>>Получается им нельзя операции переопределять ? ARK>А почему операция должна быть статической? Если только из-за кривизны конкретного языка, в котором она определяется только так и не иначе.
Да, именно из-за кривизны. Как я понял, у ТС наезд вообще на любые non-member functions (которые скорей всего в его любимом языке недоступны).
Re[9]: Статические методы в любом их обличии это зло!
Tom>Я про то что статические методы ставят крест на DI/IoC и убивают все прелести данных патернов
Недавно смотрел презентацию Антон Кекса — "Как нам спасти Java?" (мне интересно было чем живут java разработчики и т.п.).
Так вот, он рекомендовал использовать статические методы как обычные регулярные non-member functions — то есть output параметры полностью зависят от input.
Эта естественно хорошая идея, и мне казалось что многие хорошие программисты это должны понимать.
Но меня очень удивил вопрос которые ему задали: http://tinyurl.com/oqg6qyy — "а как же тестировать такие статические методы? они усложнят на unit-тестирование".
То есть у людей настолько выедены мозги, что они не могут сообразить как тестировать простые регулярные функции
Re[14]: Статические методы в любом их обличии это зло!
Здравствуйте, AlexRK, Вы писали:
ARK>Здравствуйте, _NN_, Вы писали:
_NN>>А вот скажем пример типа Complex/BigInteger . _NN>>Получается им нельзя операции переопределять ?
ARK>А почему операция должна быть статической? Если только из-за кривизны конкретного языка, в котором она определяется только так и не иначе.
Такой подход вполне логичен в системах где классы закрыты.
Каким должен быть контекст в перегруженном операторе, левый или правый ?
Проще сказать, что его нет.
Можно пойти по принципу открытых классов, стиля Руби.
И тогда всегда контекстом будет левый операнд.
Идиллия — нет статических функций и все живы =)
Здравствуйте, Tom, Вы писали:
Tom>Прошу не стесняться и рассказать мне как вы напишете тесты в данной реализации функции с использованием статических методов...
Tom>
Без тени стеснения скажу в чем твоя ошибка. Она в типе возвращаемого значения. У тебя получилась процедура которая без побочного эффекта не имеет смысла. А вот если функция возвращает значение и не делает побочных эффектов, то ее тестирование становится элементарным занятием. Достаточно вызвать ее с граничными условиями.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: Статические методы в любом их обличии это зло!
Здравствуйте, Tom, Вы писали:
Tom>Ээээ, причём тут глобальные преременные. Tom>Я совсем про другую проблему вещаю. Tom>Я про то что статические методы ставят крест на DI/IoC и убивают все прелести данных патернов
Они при том, что тебе показывают, что бывают статические функции (да просто — функции) без описанных тобой проблем. Как раз огромное достоинство функций в том, что они могут быть чистыми, т.е. не иметь побочных эффектов. Такие функции, в отличии от процедур с побочными эффектами, которые тебе так не нравятся, очень легко тестируются и поддерживаются.
Я вот когда пишу функциональный код делаю ошибки в разы реже, чем когда пишу императивный.
Если уж искать вселенское зло в программировании, то это скорее будет побочные эффекты, работа с индексами и прочая мутотень. ООП — не плохой способ скрыть некузявость и кривость императивного мира за простыми интерфейсами. Но есть и другие способы. Функции без побочных эффектов, например.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.