Один із способів задуматися над цим - це, що ви маєте на увазі під час / дату ? Комп'ютери не знають, що це за поняття: їх треба якось запрограмувати. Досить часто представляти часи у форматі UNIX «секунди з епохи», і звичайно подавати певну цінність у програму за допомогою викликів ОС. Однак, як би не було поширене таке використання, важливо пам’ятати, що це не «фактичний» час: це лише логічне уявлення.
Як зазначали інші, якщо ви створили "термін", використовуючи цей механізм, тривіально годувати в інший час і порушувати цей "термін". Те ж саме стосується і більш досконалих механізмів, таких як запитання сервера NTP (навіть через "захищене" з'єднання, оскільки ми можемо замінити власні сертифікати, органи сертифікації або навіть виправити криптовалюти). Спочатку може здатися, що такі люди винні у роботі навколо вашого механізму, але, можливо, це робиться автоматично і з поважних причин . Наприклад, добре мати відтворювані збірки , а інструменти, які допоможуть цьому, можуть автоматично скинути / перехопити такі недетерміновані системні виклики. libfaketime робить саме це,встановлює всі часові позначки файлу, функцію запису / повторення1970-01-01 00:00:01
Qemu підробляє всю апаратну взаємодію тощо.
Це схоже на закон Гудхарта : якщо ви зробите поведінку програми залежною від логічного часу, то логічний час перестає бути хорошим показником "фактичного" часу. Іншими словами, люди, як правило, не возиться із системним годинником, але вони зроблять це, якщо ви дасте їм причину.
Є й інші логічні уявлення про час: одне з них - версія програмного забезпечення (або ваша програма, або деяка залежність). Це більш бажане подання на "кінцевий термін", ніж, наприклад, час UNIX, оскільки він більш специфічний для того, що вам важливо (зміна наборів функцій / API) і, отже, менше шансів наткнутися на ортогональні проблеми (наприклад, зіткнення з часом UNIX для обробка терміну може призвести до порушення файлів журналів, завдань із запиту на керування, кешів тощо).
Як говорили інші, якщо ви керуєте бібліотекою і хочете "натиснути" на цю зміну, ви можете надіслати нову версію, яка знецінює функції (викликаючи попередження, щоб допомогти споживачам знайти та оновити їх використання), а потім ще одну нову версію, яка видаляє функції цілком. Ви можете опублікувати їх одразу один за одним, якщо вам подобається, оскільки (знову ж таки) версії є лише логічним поданням часу, вони не повинні бути пов'язані з "фактичним" часом. Тут може допомогти семантична версія.
Альтернативна модель - "витягнути" зміни. Це подібно до вашого "плану B": додайте тест до споживчої програми, яка перевіряє, що версія цієї залежності є принаймні новим значенням. Як завжди, червоний / зелений / рефактор для розповсюдження цієї зміни через кодову базу. Це може бути більш доречним, якщо функціональність не "погана" чи "неправильна", а просто "погана придатність для цього випадку використання".
Важливим питанням підходу "тягнути" є те, чи вважається версія залежності "одиницею" ( функціональності ) чи, отже, заслуговує на тестування; чи це просто "приватна" деталізація реалізації, яку слід використовувати лише як частину тестів фактичної одиниці ( на функціональність ). Я б сказав: якщо відмінність між версіями залежності справді зараховується як особливість вашої програми, тоді робіть тест (наприклад, перевіряючи, чи версія Python>> = 3.x). Якщо ні, то не вартододайте тест (оскільки він буде крихким, неінформативним та надмірно обмежуючим); якщо ви керуєте бібліотекою, тоді рухайтесь по маршруту "push". Якщо ви не керуєте бібліотекою, тоді просто використовуйте будь-яку версію: якщо ваші тести проходять, обмежувати себе не варто; якщо вони не пройдуть, то це ваш "термін" прямо там!
Існує інший підхід, якщо ви хочете відмовитись від певного використання функцій залежностей (наприклад, виклик певних функцій, які не грають добре з рештою коду), особливо якщо ви не контролюєте залежність: нехай ваші стандарти кодування забороняються / перешкоджайте використанню цих функцій та додайте чеки на них у свій літер.
Кожен із них буде застосований за різних обставин.