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

Мощный заход, внушает!
> Причём тут обсуждаемый "инлайн nextFriday"? У тебя там Time.now будет константным, да?
Вы зачем то полезли в инлайн строк
P>>Джава компилятор на основании иммутабельности умеет вводить кое какие оптимизации. Строки — одна из таких вещей.
·>Допустим, и причём тут инлайн?
Это вы мне объясните, для чего вам понадобилось инлайнить строки. Это ж ваш аргумент был.
Я вам показал, что с str.length() у нас всё близко к идеалу — компилятор и джит без вас умеют инлайнить не абы как, а практически в константу.
P>>·>Можно, конечно. Но это не происходит непрерывно сто раз на дню как ты тут заявлял выше. Да, возможно раз в месяц надо поискать боттл-нек и как-то порефакторить.
P>>"как то"
Не как то, а вручную вместо работы компилятором и ИДЕ.
·>Это твои фантазии, или кривая IDE, или неумение ею пользоваться.
Вы пока так и не показали, как будете свой nextFriday инлайнить. Ваш последний аргумент — сбежать в сторону "заинлайни str.length()"
P>>>>Не любое. Изменение конфига сюда не подходит.
P>>·>Конфиг это не код. Выделил жирным.
P>>А протаскивание такого конфига — тот еще код. Особенно когда это все инжектится
·>"изменение конфига" != "протаскивание конфига".
Весело у вас — изменение конфига не является кодом, изменение дерева депенденсов не является кодом, добавление параметра в конструктор не является кодом...
Что еще у вас кодом не является?
Зато интерфейс с аннотациями без реализации у вас почему то "ужос-ужос это код!!!!111111"
·>Он _вам_ ответил. Его ответ — другое решение, которое и в моём коде тоже реализуется тривиально. Его решение иногда не подойдёт в том, что у него будет latency spike на cache miss. А моё решение с таймером в твоём коде не реализуется, придётся всё везде перелопачивать. ЧТД — мой код универсальнее, не требует изменения дизайна на каждый чих.
Не нужно ничего перелопачивать — будет ровно такая же функция как у Синклера, только кеширование будет иначе сделано.
В этом случае мы основную бл тестируем без изменений — эта функция вообще не изменится. Для неё как были тесты по таблице истинности, так и остались.
P>>Нет, не нужно — функция где БЛ никак не изменилась, ни внутри, ни снаружи. Изменилась исключительно интеграция.
·>Ага, но у тебя интеграции — на каждый вызов nextFriday из множества методов контроллеров. У меня интеграция wiring — ровно одна строчка.
Вам нужно в каждый компонент явно вписывать это как зависимость, и не ошибаться — где клиентское, где серверное, где текущее, где предзаписаное время.
P>>В вашем случае вы перепахали внутрянку той самой функции
·>Ну вы тоже.
Нисколько. Сама функция осталась без изменений. Смотрите пример Синклера внимательно — он вызывает основную функцию, а не модифицирует её.
·>"Снаружи" это откуда? А проблема в том, что множество мест связки nextFriday с Time.now ты протестировать никикак не можешь. Ещё раз повторюсь: ЧПФ. У тебя его нет.
Буквально "вызываем метод с параметром x" — такого не будет. И не нужно. А все, что дает конкретные результаты — будет ровно как у вас.
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' сам? Найдёт|отрефакторит имя функции и определит типы ляляля параметров?
Найдет. Отрефакторит. Определит. В тайпскрипте есть внятный вывод типа, и вы можете вывести тип тупла аргументов метода по его имени, тип возвращаемого значения, итд и тд. А раз есть тип, то у нас будет статический контроль и whenCalledWith, и returns, и много чего другого.
P>>Смотря что вам надо. Серебряную пулю — такого нет. Составить список требований, сделать ревью, предложить дизайн, сделать ревью, написать тесты, сделать ревью, написать код, сделать ревью, пофиксить баги, сделать ревью — по моему так всё и делается.
·>Именно. Вот это всё и ещё маленько — оно может давать гарантию. Тесты же гарантию давать не могут, или ты так своё умение варить кашу из топора демонстрируешь?
Без тестов гарантий никаких не будет. Нужно всё вместе:
1 Код ревью не работает в том случае, когда его можно скипнуть
2 Тесты не работают, когда их можно обойти
Что бы добиваться качества, вам нужно решить обе этих проблемы.
·>Опять у тебя какая-то особая терминология. Под запросом я имею в виду данные приходящие от клиентов через внешний апи. Вот то что условный curl посылает — это запрос.
А я вам про принимающую сторону. Серверное и текущее время вы получаете забесплатно. А клиентское и так придет в виде значения, если у вас в апи так прописано.
P>>Нет такого "проверка работоспособности" — это менеджерский сленг. Есть выполнение сценариев А...Z, тесты для всевозможных ...ility, итд итд
P>>То есть, находим конкретные свойства, которые покрываем тестами на том или ином уровне, в зависимости от вашего инструментария
·>Реальным клиентам пофиг что у вас за такие сценарии A...Z и когда они у вас гоняются. Им надо их сценарии.
Забавно — это вы всерьёз покрываете тестами левые сценарии? Или это вам видится, что все вокруг вас дураки?
P>>Зачем?
·>Чтобы можно было пальчиком тыкнуть где конкретно ты заблуждаешься.
Я так понимаю, хорошего примера у вас нет.
P>>Голословно. Любой большой кусок кода нужно в первую очередь тестировать непосредственно.
·>Зачем?
1. чем больше кода между замерами, тем хуже детализация ошибок
2. чем больше косвенность, тем вам труднее покрыть основные пути хоть с какой нибудь детализацией
Это особенности тестов вообще. Потому и убирают лишнее из тестового кода, и тут два основных подхода, оба основаны на отделении эффектов и зависимостей:
1. моки — тот подход, который вам кажется единственно верным, т.е. обрезание, подмена зависимостей и эффектов
Пример — обмазали моками и написали тест "таймер вызывается дважды с такими вот аргументами"
2. классический — вытеснение зависимостей и эффектов в код верхнего уровня
Пример "sin(x) = y"
P>>А вы предлагаете всё делать наоборот.
·>Конечно. Т.к. надо тестировать поведение, а не детали реализацию.
Тестируется как раз наблюдаемое поведение вычислителя фильтров. Вычислитель фильтров обычная чистая функция, в ней ничего военного нет — тестируем как любую чистую функцию.