Восемь уроков назад башня таскала провод и книгу аргументом через три функции, а тест на один кадр собирал объект башни руками. Теперь у неё пять сервисов, у каждого свои слои, и смена не знает, какой из них настоящий. Сегодня это проверяется целиком.
Что нужно башне
Тесты накопительные: всё, что башня умеет с этапа 12, и тесты этапов 1, 7, 8 и 10, которые пережили переезд на сервисы. Сверху три вещи в src/main.ts.
watch(lines), смена целиком. Имя смены из ссылки урока 52 первой строкой журнала, потом ночь, потом её сводка, потом подписанная сводка с позывным и печатью из урока 51. На выходе весь журнал и подписанная строка. ВRу смены пять сервисов: провод, книга, журнал, позывной, ключ. Имени смены вRнет.TowerLive(tower, loadSent), боевая сборка. Провод Магистрали поверхtower.send, книга грузится в фоне поloadSentи не держит смену у двери, позывной и ключ читаются из конфигурации. Без ключа сборка падает сConfigError, и это видно в типе слоя.TowerTest(sent, broken), проверочная сборка. Провод рвётся на строках, про которыеbrokenговорит да, книга готовая изsent, позывнойT-1и учебный ключ кладутся без конфигурации.
У обеих сборок журнал один на провод и на смену, а требования пусты: Layer.satisfiesServicesType<never>() в конце каждой. Точные типы, порядок строк журнала и текст подписи в заказе.
Чек-лист перед сдачей
- Тесты всех живых прошлых этапов зелёные.
- Ночь заказа EF4 на проверочной сборке, с обрывом на
T-9, даёт тот же отчёт, что и в уроке 46: обработано 4, ошибок 5, призраков 1, дублей 1. Пять строк журнала: имя смены, два ответа, сводка, подписанная сводка. - Та же ночь на боевой сборке отправляет по Магистрали ровно два ответа, а ключа нет нигде в журнале.
- Печать боевой сборки и проверочной разная: ключи разные.
- Без
TOWER_KEYбоевая сборка не собирается, и ночь кончаетсяConfigError, а не дефектом. - Тип
watch(lines).pipe(Effect.provide(TowerTest(...)))ровноEffect<Watch>: ни ошибки, ни долгов.
Башня, этап 19
Две сборки рядом
Нарисуй граф обеих сборок, прежде чем писать код. Он один и тот же, меняются только листья:
боевая проверочная
смена ──▶ Wire Wire.layer(Магистраль) Wire.layerFlaky(broken)
──▶ Ledger Ledger.layerLazy(loadSent) Ledger.layer(sent)
──▶ CallSign CallSign.layerConfig Layer.succeed(CallSign, 'T-1')
──▶ TowerKey TowerKey.layerConfig Layer.succeed(TowerKey, учебный ключ)
──▶ Journal ◀── Wire так же
Смена не знает, какая колонка под ней. В этом весь раздел: код, который делает работу, отделён от кода, который решает, чем эту работу снабдить. Решение принимается в одном месте, на краю, и его можно поменять целиком, не тронув ни строки смены.
Обрати внимание на ошибку сборки. У боевой башни E это ConfigError: конфигурация бывает неполной. У проверочной E пустой: в ней нечему падать при сборке. Это не случайность, а описание мира. Тест, который хочет проверить поведение без ключа, берёт боевую сборку и пустую конфигурацию, а не изобретает третью.
Практика
Итог
Утром Рыдкулл кладёт на стол два журнала, боевой и проверочный, и сравнивает их строку за строкой. Сводки совпадают. Печати разные, как и должны.
Сундук, который стоял у двери с урока 02, подходит к столу, поднимает крышку и больше её не закрывает. Внутри провод, книга, журнал, позывной и ключ, ровно то, что в него положили.
Ранг: Магистр.
Дальше
Смена кончилась. Рыдкулл обходит башню и останавливается у провода.
В коридоре у незакрытой двери архива кто-то очень высокий ждёт с песочными часами. Он не торопится. Он никогда не опаздывает.
Следующий раздел курса это EF6 «Смерть приходит вовремя»: ресурсы, финализаторы и прерывание. Начинается он с урока 55.