Re[49]: Что такое Dependency Rejection
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 23.01.24 20:02
Оценка:
Здравствуйте, ·, Вы писали:

P>>Чего стесняться — я вам прямо говорю. Переносим код связывания из размытого dependency injection в контроллер

·>Именно. И по итогу получается, что издержек у тебя больше, строчек кода добавляется огромная куча.

Нету никакой огромной кучи

P>>Это я вам пример привожу, что функциональность приложения и функции в джаве это две большие разницы.

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

А нефункционые требования вы будете в виде нефункций выражать? Вы притягивает юзера к вашим тестам. Юзера можно притянуть только к функциональным тестам. Во всех остальных он не фигурирует.

P>>>>Его не раз в год нужно делать, а непрерывно — требования меняются постоянно

.
P>>·>Опять путаешь цель и средство. Рефакторинг — это средство.
P>>Именно что средство.
·>Дядя Петя... на какой вопрос ты сейчас ответил? Напомню вопрос который я задал: "инлайнинг и т.п. — это средство, а не цель. С какой целью что инлайнить-то?"

Я вам подсветил, что бы полегче прочесть было

P>>·>На какую константу? Значение length() зависит от того, что лежит в данном конкретном экземляре str:

P>>Length это интринсик,
·>Это где и с какого бодуна?

length cводится к
1 получению размера внутреннего массива символов что есть неизменная величина
2 гарантии иммутабельности соответсвующей ссылки. Т.е. никакой modify(str) не сможет легально изменить длину строки str
3 джит компилятор в курсе 1 и 2 и инлайнит метод length минуя все слои абстракции, включая сам массив и его свойство
Если вы запилите свой класс строк, нарушив или 1, или 2, компилятор ничего вам не сможет заинлайнить.

ваш провайдер времени не обладает свойствами навроде 1 или 2, потому не то что компилятор, а ИДЕ, а часто и разработчик не смогут просто так заинлайнить метод

P>>его сам компилятор заинлайнит, вам не надо заботиться

P>>Инлайнить самому нужно для оптимизации, изменения дизайна, итд
·>Противоречивые параграфы детектед.

Я вижу здесь другой кейс — вы так торопитесь, что обгоняете сами себя. Инлайнить методы нужно для оптимизации или изменения дизайна. В случае c Length инлайн в целях оптимизации выполнит компилятор.

P>>·>А у меня всё круто, т.к. реализация nextFriday() знает, что это отностися к следующей пятнице, то может кешировать одно и то же значение в течение недели и обновлять его по таймеру, например.

P>>Другими, вы здесь предложили наивную реализацию LRU кеша c контролем ттл по таймеру.
·>Угу. С нулевым изменением дизайна.

Ну да — добавить компонент с конфигом и сайд-эффектом это стало вдруг нулевым изменением дизайна

P>>Запрос из кеша это изменение того самого дизайна.

·>Твоего дизайна — да, моего — нет.

Т.е. вы не в курсе, что значение функции закешировать гораздо проще, чем мастырить LRU кеш? Более того — такую кеширующую функцию еще и протестировать проще.

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

·>Кеш — это отдельный компонент.

Вот-вот. Отдельный компонент. В том то и проблема. И вам все это придется мастырить и протаскивать. Только всегда "где то там"

P>>Смотрите выше — вы сами, безо всякой моей подсказки предложили "может кешировать одно и то же значение в течение недели и обновлять его по таймеру, например" что есть тот самый кеш.

·>Именно. А вот ты даже это не смог предложить какого-либо работающего решения, кешировать с ключом по now — это полный бред. И вот тебе придётся для введения кеша в твоём "более гибком коде" перелопатить весь дизайн и тесты, т.к. связывание now и nextFriday у тебя происходит во многих местах и везде надо будет проталкивать этот кеш и его настройки.

Ровно так же как и у вас, только дизайн не надо перелопачивать.

P>>Хотите гибкости — в тесты нужно выносить самый минимум. Как правило это параметры и возвращаемое значение. Вы почему то в этот минимум добавляете все зависимости с их собственным апи.

·>Я не вижу в этом проблему. Ничего не бетонируется. Всё так же рефакторится. Ещё раз напоминаю, что класс с зависимостями это технически та же функция "параметры и возвращаемое значение", но с ЧПФ. Просто некоторые параметры идут через первое "применение": f(p1, p2) <=> new F(p1).apply(p2).

Вы пока что инлайн обеспечить не можете, а замахиваетесь на чтото большее

P>>Вы регулярно приводите примеры лишних строчек, но почему то вам кажется, что у меня кода больше. Код системы это не только функциональная часть, но тестирующая.

·>Я не привожу лишние строчки. Я привожу полный код, а ты весь код просто не показываешь.

И где ваш код nextFriday и всех вариантов инжекции для разных кейсов — клиенское время, серверное, текущие, такое, сякое ?

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

·>Теперь определись — толи ты сейчас привираешь, что это тебе всё давно знакомо, толи ты просто словоблудил, выразив непонимание что я имею в виду под wiring.

wiring и есть связывание. Код связывания в dependency injection, который вы называете wiring, и код связывания в контроллере — выполняют одно и то же — интеграцию. Разница отражает подходы к дизайну. И то и другое wiring, и то и другое связывание. И задача решается одна и та же. Только свойства решения разные.


P>>

P>>By choosing to fulfill dependency contracts with functions rather than classes

·>За деревьями леса не видишь... ты код-то погляди, то же самое частичное применение функций для эмуляции "классов".

Похоже, что пример для Буравчика вы не поняли

P>>В 00х Фаулер сотоварищи топили за тот подход, за который вы топите 20 лет спустя.

·>Потому что тогда он показывал это на языках 00х, а сейчас ровно то же самое показывает на typescript. Та же ж, вид в профиль. Неужели ты до сих пор не въехал в ЧПФ?!

То же, да не то же. Посмотрите где связывание у него, а где связывание у вас.

P>>С тех пор ничего не изменилось.

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

Фремворки и у вас есть, только из 00х. Вы уже признавались в этом.

P>>У вас там написание кода начинается с деплоя на прод?

·>Это где я такое написал? Как вообще такое возможно?!

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

P>>А надо во время написания кода которые идут вперемешку с прогном быстрых тестов, и это все за день-неделю-месяц до самого деплоя!

·>Ну чтобы какой-либо тест прогнать — надо стартовать некий код... не? Вот до выполнения первого попавшегося @Test-метода оно и грохнется, где-нибудь в @SetUp.

Вы тестируете не @Setup а иерархию вызовов dependency injection, которая у вас появляется, появляется... на старте приложения. И фейлы ждете с этого момента. А надо гораздо раньше.
Смотрите тот вариант что у Фаулера — его окончательный дизайн позволяет вам фейлить многие вещи когда ничего другого вообще нет — его связывание в одном месте и покрывается тестами
У вас аналог этого связывания будет а хрен его знает когда

·>Не знаю где ты это увидел, имеется в виду мы тестируем прод окружение пытаясь деплоить на прод. Вы, кстати, тестируете уже после деплоя на прод.


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

P>>Ну вот вам и ответ.

·>Напомню вопрос: А как ты будешь такой и-тест писать, если у тебя будет Time.Now? Что ассертить-то будешь? Как отличать два разных вызова Time.Now — клиентский от серверного?
·>Вот пришло тебе в ответе в неком поле значение "2024-01-23". как ты в и-тесте отличишь, что это вычислилось от вызова Time.Now на серверной стороне, а не на клиентской?

Смотрите пример про Колю Петрова, там ответ на этот вопрос

P>>Нам нужны именно фичи, кейсы, сценарии. В строчках кода это не измеряется. Смотрите, как это делают QA.

·>Как ты убедишься, что некая фича покрыта тестами? Или что все фичи и разные corner cases описаны в бизнес-требованиях? Покрытие хоть и ничего не гарантирует, но часто помогает обнаружить пробелы.

Я ж говорю — смотрите, как это у QA делается.

P>>- зарезервировать столик на трех человек на имя Коля Петров на следующую пятницу 21.00

·>Этот пример совершенно никак не отностися к обсуждаемому нами методу nextFriday. Или у тебя в твоём дизайне будет семь методов nextMonday...nextSunday?

Примером по Колю Петрова вам показываю, что такое интеграционные тесты. Вы же в них хотите проверять "а должно вот там вызываться!"

P>>Остальных — от 1000 до 5000 и они занимают 99% времени.

·>Ну вот и говорю хоупейдж. По acc-тестам (селениум, сеть, многопоток, полный фарш) у нас было на порядок больше, выполнялось за 20 минут, правда на небольшом кластере.

Подозреваю, вы их просто подробили, "проверим, что время вон то"

P>>Не нравится метапрограммирование — можете придумать что угодно.

·>И что? Причём тут тесты-то?

Тесты где сравнивается выхлоп из базы не решают проблемы data complexity. Отсюда ясно — что нужно добавлять нечто большее.

P>>Вы там ногой читаете? Запрос не человек, сказать не может. А вот ревьюер может сказать "у нас такого индекса нет, тут будет фуллскан по таблице из десятков миллионов записей с выполнением регекспа и время работы на проде надо ждать десятки минут"

·>Или у вас неимоверно крутые ревьюверы, помнят наизусть сотни таблиц и тысячи индексов, или у вас хоумпейдж. Не все могут себе такое позволить.

Зато сразу ясно, где именно хоум пейдж, и почему ваши тесты работают ажно 20 минут.

P>>Это ж вы сунете тесты туда, где они не работают.

·>Это ты словоблудием занимаешься. Мы обсуждаем именно тесты, а ты тут в сторону доказательного программирования и мета уходишь.

Я вам о том, какие гарантии можно получить вашими тестами, а какие — нельзя.
В вашем случае вы ничего не гарантируете на тех данных, что у вас нет.

P>>Как гарантировать — см пример номер 100500 чуть выше

·>Где чуть выше?

Я вам одно и то же пишу второй год.

P>>У вас данных нет. Или вы щас скажете, что у вас уже есть все данные всех юзеров на будущее тысячелетие?

·>И как тобой предложенное "in: [fn1]" решает эту проблему? Или ты опять в сторону разговор уводишь?

Примерно так же, как assert.notnull(parameter) в начале метода или return assert.notEmpty(value) в конце

P>>Наоборот.

·>Ваша цитата: Ага, тесты "как написано" Вам придется написать много больше, чем один тест — как минимум, пространство входов более-менее покрыть. Моками вы вспотеете это покрывать.

Ну ок, значит ничья в этом вопросе

P>>·>Зато есть возможность покрыть известные данные и комбинации тестами. Вы и этого не делаете, а просто имена приватных функций ассертите и буковки сравниваете (тоже, кстати известные). Вот и приходится часами билдить и в проде тесты гонять чтобы хоть что-то как-то обнаружилось.

P>>Зачем вам собеседник, если у вас отличный дуэт с вашей телепатией?
·>В каком месте тут телепатия? Билд занимающий часы — это твои слова. И тесты в проде — тоже.

Вы всё знаете — и сложность проекта, и объемы кода, и начинку тестов, и частоту тех или иных тестов. Просто удивительно, как тонкая телепатия.

P>>Такой тест гарантирует, что всё множество данных будет проходить именно через эту функцию.

·>Не гарантирует. В коде может быть написано "if(thursdayAfterRain())return {...in: [fn42]...}" и тест это не может обнаружить. Ещё раз — тесты ничего не могут гарантировать.

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

P>>Я вам привел пример про Колю Петрова. Надеюсь, справитесь

·>Опять врёшь. Это не код.

Почему ж не код? Это в кукумбер переводится практически один к одному.

·>Я это и сказал. Если тут всё равно серверное время, то да, не функциональное, и тесты не пострадают. Тесты сломаются и должны сломаться если ты заменишь источник серверного времени на источник клиентского времени.


А вы точно интеграционные пишите? Чтото мне кажется, вы пишете высокоуровневые юнит-тесты.

·>Я не понимаю какое отношение метапрограммирование имеет к бизнес-требованиям и к тому как писать тесты.

Такое же, как ваши классы, методы, dependency injection итд.

P>>Тесты дают гарантию, что пайплайн устроен нужным мне образом. А свойства результата, следовательно, будут определяться свойствами пайплайна. Тогда вам нужно сосредоточиться на выявлении этих свойств, а не писать одно и то же третий месяц кряду.

·>Тесты не могут давать гарантию.

Тесты именно ради гарантий и пишутся. Только чудес от них ждать не надо.

P>>Смотрите пример про Колю Петрова

·>Не нужен мне пример. Мне нужен код.

Бывает и хуже.

P>>Детали реализации нужно покрывать тестами, что бы первый залётный дятел не разрушил всю цивилизацию:

P>>- оптимизации
·>Это перф-тесты.

Это слишком долго. Фейлы перформанса в большинстве случаев можно обнаруживать прямо во время юнит-тестирования.

P>>- трудноуловимые баги

P>>- секюрити
P>>- всякие другие -ility
P>>- любой сложный код, где data complexity превышает ваше капасити
·>Это "за всё хорошее, против всего плохого". А секьюрити — это бизнес-требование и обязано быть покрыто фукнциональными тестами.

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

·>"Метапрограммирование тестируется" — зачем?


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

P>>Вы не просто утверждаете это, а идете дальше — утверждаете, что тесты прода это признак наличия багов, не той квалификации и тд.

·>Признак более позднего обнаружения багов.

Они показывают, выполнимы ли сценарии под нагрузкой(при изменениях сети, топологии, итд) или нет.

·>На это и придумали healthchecks (а конкретно liveness probe), проверка, что сервис — operational, явно проверяет себя и свои зависимости, что может отрабатывать трафик без фейлов ещё до того как пошли реальные запросы.


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

P>>Какой процесс вас застрахует от фейла на другой стороне которую вы не контролируте?

·>Большая тема. Начни отсюда: https://en.wikipedia.org/wiki/High_availability

Выполнимость сценариев это consistensy всех функций сервиса, а вовсе не high availability, как вы думаете.

P>>Вы наверное с кем то меня путаете. Я ни призывал писать всё руками. С аннотациями похоже снова дело в вашей телепатии. Я ж вам сказал — они для конкретных кейсов. Кодогенерация дает медленный цикл разработки. В некоторых кейсах это можно сократить на недели и месяца. Я привел вам примеры но вы как обычно прошли мимо

·>Кодогенерация сама по себе медленный цикл разаработки не даёт. Любой кодогенератор работает от силы порядка минут.

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

P>>У нас кейс "переписать апи на rust" был 0 раз за 10 лет. Смена технологий от балды — тоже 0 раз. А у вас иначе, каждый месяц всё с нуля на rust переписываете?

·>C++, kotlin, java, groovy, scala (может ещё что забыл)... И таки да, спеки всё-таки есть в виде FIX или хотя бы avro/protobuf. А когда копадаются другие команды/внешине сервисы с подходом "нагенерим из аннотаций" — вечная головная боль интегрироваться с такими.

И ежу понятно — вам максимум с собой легко интегрироваться
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.