Jednym ze sposobów myślenia o tym jest to, co rozumiesz przez czas / datę ? Komputery nie wiedzą, jakie są te pojęcia: trzeba je jakoś zaprogramować. Dość często reprezentuje się czasy w formacie UNIX „sekund od epoki” i często podaje się określoną wartość do programu za pomocą wywołań systemu operacyjnego. Jednak bez względu na to, jak powszechne jest to użycie, należy pamiętać, że nie jest to „rzeczywisty” czas: jest to tylko logiczna reprezentacja.
Jak zauważyli inni, jeśli zrobiłeś „termin” za pomocą tego mechanizmu, trywialne jest karmienie w innym czasie i przełamanie tego „terminu”. To samo dotyczy bardziej skomplikowanych mechanizmów, takich jak żądanie serwera NTP (nawet przez „bezpieczne” połączenie, ponieważ możemy zastąpić własne certyfikaty, urzędy certyfikacji, a nawet załatać biblioteki kryptograficzne). Na początku może się wydawać, że takie osoby są winne obejścia twojego mechanizmu, ale może się zdarzyć, że zrobi to automatycznie i nie bez powodu . Na przykład dobrym pomysłem jest posiadanie odtwarzalnych kompilacji , a narzędzia, które mogą to pomóc, mogą automatycznie resetować / przechwytywać takie niedeterministyczne wywołania systemowe. libfaketime robi dokładnie to,ustawia znaczniki czasu wszystkich plików na 1970-01-01 00:00:01
, funkcja nagrywania / odtwarzania Qemu udaremnia wszelkie interakcje sprzętowe itp.
Jest to podobne do prawa Goodharta : jeśli uzależnisz zachowanie programu od czasu logicznego, wówczas czas logiczny przestanie być dobrą miarą „rzeczywistego” czasu. Innymi słowy, ludzie na ogół nie będą bałagać się zegarem systemowym, ale zrobią to, jeśli dasz im powód.
Istnieją inne logiczne reprezentacje czasu: jednym z nich jest wersja oprogramowania (aplikacja lub zależność). Jest to bardziej pożądana reprezentacja dla „ostatecznego terminu” niż np. Czas UNIX, ponieważ jest bardziej specyficzna dla rzeczy, na których Ci zależy (zmiana zestawów funkcji / interfejsów API), a zatem mniej prawdopodobne jest deptanie ortogonalnych problemów (np. Majstrowanie przy czasie UNIX do obejście terminu może spowodować uszkodzenie plików dziennika, zadań cron, pamięci podręcznych itp.).
Jak powiedzieli inni, jeśli kontrolujesz bibliotekę i chcesz „wypchnąć” tę zmianę, możesz wypchnąć nową wersję, która przestaje działać (powodując ostrzeżenia, aby pomóc konsumentom znaleźć i zaktualizować ich użycie), a następnie inną nową wersję, która usuwa funkcje całkowicie. Możesz je opublikować bezpośrednio po sobie, jeśli chcesz, ponieważ (ponownie) wersje są tylko logiczną reprezentacją czasu, nie muszą być powiązane z „faktycznym” czasem. Pomocna może być tutaj wersja semantyczna.
Alternatywnym modelem jest „pociągnięcie” zmiany. To jest jak Twój „plan B”: dodaj test do aplikacji konsumującej, która sprawdza, czy wersja tej zależności jest co najmniej nową wartością. Jak zwykle czerwony / zielony / refaktor do propagowania tej zmiany przez bazę kodu. Może to być bardziej odpowiednie, jeśli funkcjonalność nie jest „zła” lub „zła”, ale tylko „źle pasuje do tego przypadku użycia”.
Ważnym pytaniem związanym z podejściem „pull” jest to, czy wersja zależności liczy się jako „jednostka” ( funkcjonalności ), a zatem zasługuje na przetestowanie; czy to tylko „prywatna” szczegółów wdrażania, które powinny być wykonywane jedynie w ramach rzeczywistego urządzenia ( funkcjonalności ) testów. Powiedziałbym: jeśli różnica między wersjami zależności naprawdę liczy się jako funkcja twojej aplikacji, to wykonaj test (na przykład sprawdzając, czy wersja Pythona to> = 3.x). Jeśli nie, to nie rób tegododaj test (ponieważ będzie on kruchy, pozbawiony informacji i nadmiernie ograniczający); jeśli kontrolujesz bibliotekę, idź ścieżką „push”. Jeśli nie kontrolujesz biblioteki, po prostu użyj dowolnej dostarczonej wersji: jeśli testy przejdą pomyślnie, nie warto się ograniczać; jeśli nie przejdą, to właśnie tam jest twój „ostateczny termin”!
Istnieje inne podejście, jeśli chcesz zniechęcić do niektórych zastosowań funkcji zależności (np. Wywoływania niektórych funkcji, które nie działają dobrze z resztą kodu), zwłaszcza jeśli nie kontrolujesz zależności: zabroń standardów kodowania / zniechęcaj do korzystania z tych funkcji i dodawaj je do linera.
Każdy z nich będzie miał zastosowanie w różnych okolicznościach.