Re[59]: Что такое Dependency Rejection
От: Sinclair Россия https://github.com/evilguest/
Дата: 31.01.24 06:51
Оценка:
Здравствуйте, ·, Вы писали:
·>Да, кстати, у его решения ещё один огромный недостаток. Его реализация неявно подразумевает, что передаваемый "DateTime dt" это DateTime.Now, т.е. плавно изменяющийся параметр, только тогда кеш будет пересчитываться раз в неделю. Кто-то видя сигнатуру nextFriday(DateTime dt) — запросто может позвать её с чем попало, выкашивая кеш в самые неожиданные моменты времени. Отличная такая грабля будущим поколениям, happy debugging. Более того, чтобы даже просто начать такую оптимизацию метода — надо будет исследовать все call sites и удостовериться что туда передаётся именно текущее время, иначе кеш может быть бессмысленным, а в большом проекте эта штука может жить в шаред либе и задача вообще практически неразрешимой становится.

Это работает не совсем так.
Смотрите, любая оптимизация начинается с профилирования и им же заканчивается.
То есть перед тем, как что-то на что-то менять, мы берём и снимаем профиль.
И вот когда мы по профилю видим, что эта функция становится bottleneck, тогда мы и начинаем её оптимизировать.
Когда мы её оптимизируем, мы, конечно же, смотрим на характер нагрузки. Если у нас там приходит небольшое количество одинаковых значений — мы оборачиваем функцию в memoize, проверяем результат, и едем разгребать следующую таску из джиры.
Если у нас вот такой вот монотонно меняющийся параметр — мы оборачиваем функцию вот в такой вот специализированный "memoize", проверяем результат, и едем разгребать следующую таску из джиры.

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

Сам подход работает совершенно независимо от выбранной архитектуры — ФП, ПП, или ООП. Но у вас, похоже, возникает иллюзия, что вы можете написать реализацию, которая будет не просто оптимальна, но и устойчива ко всем будущим изменениям характера нагрузки.
Нет, так не получится. Потому, к примеру, что у вас нет гарантий на монотонность применяемого источника времени. Если она есть у вас — то она есть и у вашего оппонента, и оптимизация сработает.
Если есть квазимонотонность — то сработает чуть более сложный алгоритм. Если монотонности нету — то ваш код точно так же встрянет, и будет работать ещё медленнее, чем без кэширования.
·>В моём же случае, nextFriday() явно запрещает туда передать что-то не то.
Это иллюзия. Вот у нас есть "фактическое время" клиента, "фактическое время" сервера. А есть ещё "время по документу клиента". Который в понедельник принёс платёжку за прошлый четверг.
Ну и всё — вы в свой алгоритм nextFriday вынуждены воткнуть зависимость от источника времени, который просто парсит переданный с клиента JSON и возвращает то, что там нашлось.
Отличная такая грабля будущим поколениям, happy debugging.

·>Знание об источнике времени тут есть явно. И такие оптимизации делать становится гораздо проще, с более предсказуемым импактом. Иными словами, мы знаем конкретный применённый аргумент ЧПФ и эту информацию фиксируем явно и можем использовать.

Ну так и мы знаем конкретный применённый аргумент, и явно фиксируем эту информацию. Только она не спрятана внутрь вашего класса с методом nextFriday, а применена по месту использования.
Поэтому в одном месте будет прямой вызов nextFriday, а в другом — вызов функции, полученной при помощи wrapAndCacheMonotonous(nextFriday).
При этом поведение wrapAndCacheMonotonous(nextFriday) мы тестируем тем же набором тестов, что и саму nextFriday (т.к. у них одинаковый контракт). И нам не нужны никакие моки, которые изображают поведение часов.

P>>·>"Снаружи" это откуда? А проблема в том, что множество мест связки nextFriday с Time.now ты протестировать никикак не можешь.

Положа руку на сердце: сколько таких мест вы ожидаете в крупном проекте? Три, пять?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.