Re[56]: Что такое Dependency Rejection
От: · Великобритания  
Дата: 29.01.24 23:43
Оценка:
Здравствуйте, Pauel, Вы писали:

P>>>1 непосредственно удаляет, делает все виды работ

P>>>2 всего лишь создает отложеные операции типа "удалить док по хешкоду", "выгрузить данные в s3 с ттл 1 месяц"
P>>>С т.з. пользователя это ровно одна и та же функция. Ваши бизнес-требования не менялись.
P>·>Не понял, чем отличается 1 от 2? "все виды" это разве не "удалить"+"выгрузить"?
P>Разница в слове "отложенные". У вас недавно была проблема с этим словом. Решилась?
У нас такой проблемы не было. Т.е. разницы нет. ЧТД.

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

P>·>Не знаю что значит "гораздо эффективнее", но инлайнится она ровно так же. Ещё раз. Инлайн это убирание фрейма стека, ничего общего с мутабельностью.
P>str.length() можно заменить на str.chars.length и это будет какой то инлайн.
Не "какой-то", а инлайн.

P>Если вы вызвали str.length() 100 раз у вас есть варианты:

P>1 везде проставить str.chars.length и это будет работать.
P>Но это совсем мало.
P>Компилятор может лучше и делает лучше!
Возможно, и это уже будут другие техники оптимизации.

P>2 можно один раз вызвать str.chars.length и в 99 остальных случаев прописать именно это значение как константу.

Наверно байткод может другой сгенериться для final, может быть. Ну и что?! Причём тут обсуждаемый "инлайн nextFriday"? У тебя там Time.now будет константным, да?

P>Собственно второй вариант возможен исключительно в потому, что str.chars во всех 99 случаях будет одна и та же. В джава строке именно так. Если вы делаете мутабельную строку, ну вот вздумалось вам, то компилятор не сможет вычислить, можно ли применять кейс 2, т.е. более глубокую оптимизацию, т.к. у него нет информации, что там в каждом из 99 случае.

Может он сможет и провести compile-time вычисления, но это никакого отношения к инлайн не имеет.

P>>>Пример как раз про функцию которая ломает ссылочную прозрачность.

P>·>Тогда это пример не про инлайнинг, а про иммутабельность.
P>Джава компилятор на основании иммутабельности умеет вводить кое какие оптимизации. Строки — одна из таких вещей.
Допустим, и причём тут инлайн?

P>>>Щас вы конечно же скажете, что у вас такого никогда не бывает, и вы дизайн на все кейсы, возможные и невозможные, проектируете на 100 лет вперёд.

P>·>Можно, конечно. Но это не происходит непрерывно сто раз на дню как ты тут заявлял выше. Да, возможно раз в месяц надо поискать боттл-нек и как-то порефакторить.
P>"как то" Не как то, а вручную вместо работы компилятором и ИДЕ.
Это твои фантазии, или кривая IDE, или неумение ею пользоваться.

P>>>Не любое. Изменение конфига сюда не подходит.

P>·>Конфиг это не код. Выделил жирным.
P>А протаскивание такого конфига — тот еще код. Особенно когда это все инжектится
"изменение конфига" != "протаскивание конфига".

P>>>Изменения внутри одной функии — тоже.

P>·>Ну у меня внутри функции изменение и было для добавления кеша.
P>А LRU кеш связаный с конфигом, которые надо тащить через dependency injection не считается, да?
Считается, конечно. Целую одну строчку посчитать придётся, от силы.

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

P>·>Итак, продолжаем разговор. Что будет ключом мемоизации для nextFriday(now)?
P>Про мемоизацию я трохи погорячился.
Именно, я несколько раз на это "тонко" намекал. Если бы ты подумал как написать такой код, ты бы сразу понял свою ошибку. Поэтому я и пытаюсь из тебя выуживать куски кода — по ним все твои заблуждения видны как на ладони. И ты тут практически по всем вопросам горячишься на самом деле...

P>Вам Синклер рядом ответил.

Он _вам_ ответил. Его ответ — другое решение, которое и в моём коде тоже реализуется тривиально. Его решение иногда не подойдёт в том, что у него будет latency spike на cache miss. А моё решение с таймером в твоём коде не реализуется, придётся всё везде перелопачивать. ЧТД — мой код универсальнее, не требует изменения дизайна на каждый чих.
Ещё у него статическая глобальная переменная — за такое в детском саду в угол ставят. Если это переписать нормально, получится как у меня, вариация ЧПФ.

P>>>Смешно. Вам нужно тестировать компонент без кеширования, и компонент с кешированием, просто потому что вы всунули всё это внутрь.

P>·>Вам тоже нужно.
P>Нет, не нужно — функция где БЛ никак не изменилась, ни внутри, ни снаружи. Изменилась исключительно интеграция.
Ага, но у тебя интеграции — на каждый вызов nextFriday из множества методов контроллеров. У меня интеграция wiring — ровно одна строчка.

P>В вашем случае вы перепахали внутрянку той самой функции

Ну вы тоже.

P>>>А что мешает это без моков сделать?

P>·>Просвети как, с учётом того, что ты предложил использовать Time.now. КОД покажи.
P>Time.now будет приходить всегда снаружи. В чем вопрос, объясните?
"Снаружи" это откуда? А проблема в том, что множество мест связки nextFriday с Time.now ты протестировать никикак не можешь. Ещё раз повторюсь: ЧПФ. У тебя его нет.

P>>>Проще код, больше контроля. Даже те же моки можно прикрутить безо всяких фремворков.

P>·>Почему он проще? Мне показалось ровно наоборот. А моки можно прикручивать без фреймворков в любом случае. Правда количество кода увеличивается.
P>С каких пор низкоуровневые приседания стали проще?
Я не знаю что называешь низкоуровневыми приседаниями.

P>>>Никуда не испарилась. Все один в один, как и у вас.

P>·>В mock({}).whenCalledWith('getTopRestaurants', 'ляляля').returns(restaurants) оно правда сможет вывести типы?! Что-то не верится...
P>У Фаулера код на жээсе. Я вам показал на жээсе. Теперь вы придираетесь, что де на Тайпскрипте будет чтото еще.
P>Вы все время тратите время на мелкие придирки.
Да, в каком-то смысле мелочи, ок, давай тут подытожим. Твой правильный образцово-показательный по Фаулеру код без использования моков будет выгдяеть вот так:
const dependenciesStub = mock<AnInterface>().whenCalledWith('getTopRestaurants', 'ляляля').returns(restaurants);
const ratingsHandler: Handler = controller.createTopRatedHandler(dependenciesStub);

Я правильно понял?

P>Вот вам типы в TypeScript:

P>
P>mock<AnInterface>().whenCalledWith('getTopRestaurants', 'ляляля').returns(restaurants)[/tt] 
P>

P>Что теперь, попросите показать как это всё типизуется?
Да, серьёзно, Интересно. Ведь в коде теста никакого AnInterface даже и нет, фаулер за типы топит, которые не export. Автодополнятор вставит строчку 'getTopRestaurants' сам? Найдёт|отрефакторит имя функции и определит типы ляляля параметров?

P>>>Это сказки вида "у нас проблем на проде не бывает"

P>·>Цитаты нет, ты опять врёшь. Опять свои фантазии помещаешь в кавычки и пытаешься выдать за мои слова.
P>Я вам много раз приводил примеры, ради чего нужно запускать такое, но вы упорно видите в этом исключительно доказательство проблем в разработке.
Я-то понял. А ты не понял. Мой поинт в том, что ради этого же самого можно делать другое, более подходящее. Пример с тухлыми сертами ты как-то "забыл", перечитай.

P>Тесты на проде нынче вариант нормы.

Верю, сегодня вариант нормы такой. Люди пьют и курят — это тоже норма.

P>>>Ну так чего вы конкретно просите показать?

P>·>Код на ЯП. Для тебя наверное это новость, но сообщаю: кукумбер — это не яп.
P>Это ЯП, декларативный, высокого уровня
Сова трещит по швам.

P>>>Или код ревью, или некоторая формализация с последующей генерацией тестов, чтото навроде

P>·>Код ревью не укажет на пробелы в требованиях. Формализация — практически анреал, очень редкий зверь.
P>Смотря что вам надо. Серебряную пулю — такого нет. Составить список требований, сделать ревью, предложить дизайн, сделать ревью, написать тесты, сделать ревью, написать код, сделать ревью, пофиксить баги, сделать ревью — по моему так всё и делается.
Именно. Вот это всё и ещё маленько — оно может давать гарантию. Тесты же гарантию давать не могут, или ты так своё умение варить кашу из топора демонстрируешь?

P>>>Потому я и говорю, что лучше брать время прямо из реквеста.

P>·>Что значит "лучше"??! Это будет клиентское время, его можно подделывать. Более того, структура запроса диктуется требованиями внешнего api, а не желанием левой пятки, поэтому там его в принципе может не быть.
P>Структура запроса диктуется много чем кроме внешнего апи — протокол, фремворк, рантайм, операционка, итд. Всегда и везде технологических деталей в десятки раз больше чем бизнеслогики. В случае с хттп там разве что кофе не готовится
Опять у тебя какая-то особая терминология. Под запросом я имею в виду данные приходящие от клиентов через внешний апи. Вот то что условный curl посылает — это запрос.

P>>>Смотря какой этот один. Если тот, что только сравнивает выхлоп из базы — то нет, слабовато.

P>·>Сильнее, чем у тебя, т.к. хотя бы синтаксис запроса проверяют.
P>Ну и логика, как набор А, будет сильнее двух наборов А и Б ?
Это у тебя странная интерпретация. На самом деле "набор В, будет сильнее двух наборов А и Б".

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

P>·>Это "свойство" не эквивалентно работоспособности программы.
P>Нет такого "проверка работоспособности" — это менеджерский сленг. Есть выполнение сценариев А...Z, тесты для всевозможных ...ility, итд итд
P>То есть, находим конкретные свойства, которые покрываем тестами на том или ином уровне, в зависимости от вашего инструментария
Реальным клиентам пофиг что у вас за такие сценарии A...Z и когда они у вас гоняются. Им надо их сценарии.
  Картинку что-ли забыл? All tests passed!


P>>>·>Вы не знаете, что такое кукумбер? Забавно. https://www.google.com/search?q=cucumber+glue+code

P>>>Здесь будут примитивы вида резервирование, время операции и тд. Что коннкретно вы хотите узнать?
P>·>Как выглядит код.
P>Зачем?
Чтобы можно было пальчиком тыкнуть где конкретно ты заблуждаешься.

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

P>·>Ты сам заявлял, что эти методы видны только с целью использования их в тестах: "fn1 и fn2 должны быть видны в тестах, а не публично". Т.е. твои тесты тестируют никому более невидимые внутренние кишки реализации. Это — отстой.
P>Голословно. Любой большой кусок кода нужно в первую очередь тестировать непосредственно.
Зачем?

P>А вы предлагаете всё делать наоборот.

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

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

P>>>Не зеленую галку менеджерам показывать, а обнаруживать те вещи, которые в других условиях не видны
P>·>Верно, но это не единственный способ. И, мягко говоря, не самый лучший.
P>Вероятно у вас — не лучший. Зато куча компаний использует именно такой подход. Он сообщает куда больше проблем, чем ваши точечные пробы.
Большинству компаний и проектов не так важно качество и не такое драконовское SLA, это понятно — надо быстрее прыгать, потому что думать некогда. Но выдавать это как "правильный подход" — так себе.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.