Həftə 9 · 17/23
Vəziyyət maşınları: mümkün olmayanı yazıla bilməz et
6 dəqiqəlik oxu
Qapı ya açıqdır, ya bağlı, ya kilidli. «Həm açıq, həm kilidli» deyə bir hal yoxdur — amma üç ayrı düymə qoysan, insanlar onu yarada bilər.
Hər hal üçün ayrı boolean qoymaq mümkün olmayan kombinasiyalar yaradır. Vəziyyətləri adlandırıb yalnız icazəli keçidləri yazsan, mənasız hal ümumiyyətlə yazıla bilmir.
// three switches: 8 combinations, 4 of them nonsense
isLoading, isError, hasData
// one state: only what can actually happen
{ status: "idle" | "loading" | "error" | "done" }Çox deyilən söz: Hər hal üçün bir boolean: isLoading, isError, isDone…
Beş boolean 32 kombinasiya deməkdir və onların çoxu mənasızdır: eyni anda həm yüklənir, həm xəta. Seniorlar əvvəl vəziyyətləri və keçidləri adlandırır, sonra AI-dan yalnız icazə verilən keçidləri yazmasını istəyir. Belə model tiplə qorunur, cədvəllə test olunur və kağızda çəkilə bilir.
Sənin kulvarında
Form və ödəniş axını
Veb-də vəziyyət maşını ən çox çoxaddımlı formlarda və ödənişdə lazım olur: boş, doldurulur, göndərilir, rədd edildi, təsdiqləndi. «Göndərilir və rədd edildi» eyni anda ola bilməz.
Fikir eynidir, rəqəmlər və alətlər fərqli. Seçimin brauzerində yadda qalır və bütün dərslərə tətbiq olunur.
UI-dan əvvəl vəziyyətləri sadala
Kağızda vəziyyətləri və onları dəyişən hadisələri çək. Diaqramda olmayan keçid kodda da olmamalıdır.
Sən bunu istə
idle --pick--> ready --upload--> uploading --ok--> done
uploading --fail--> failed --retry--> uploadingDiscriminated union
Hər vəziyyətin öz etiketi və yalnız özünə aid məlumatı var. «Yüklənir» halında error yoxdur, «uğursuz» halında url yoxdur — tip buna icazə vermir.
AI belə yazır
const [isLoading, setLoading] = useState(false);
const [isError, setError] = useState(false);
const [data, setData] = useState(null);Sən bunu istə
type Upload =
| { status: "idle" }
| { status: "uploading"; progress: number }
| { status: "failed"; error: string }
| { status: "done"; url: string };Saf keçid funksiyası, cədvəl testi
(vəziyyət, hadisə) → yeni vəziyyət. Yan təsir yoxdur, ona görə hər icazəli və qadağan keçid bir cədvəl sətri ilə test olunur.
Sən bunu istə
function next(s: Upload, e: UploadEvent): Upload {
if (s.status === "failed" && e.type === "retry") return { status: "uploading", progress: 0 };
if (s.status === "uploading" && e.type === "ok") return { status: "done", url: e.url };
// ...
return s; // anything not listed is ignored
}Diff oxuyanda soruş: Komponentə bax: statusu neçə boolean daşıyır? Üç və daha çoxdursa, mümkün olmayan hal artıq oradadır.
Terminlər
İndi sən yoxla
1Dizayn problemi nədir?
const [isLoading, setLoading] = useState(false);
const [isError, setError] = useState(false);
const [data, setData] = useState(null);2«Yenidən cəhd et» düyməsi əlavə olunur. Hansı keçid düzgündür?
type Upload =
| { status: "idle" }
| { status: "uploading"; progress: number }
| { status: "failed"; error: string }
| { status: "done"; url: string };Hazır prompt
İngiliscədir, çünki terminlər ingiliscədir. Tərcümə etsən də terminləri saxla.
Model <feature> as a finite state machine before writing any UI.
- List every state by name, and the data that exists only in that state.
- List every event and the transition it causes; anything not listed is forbidden.
- Mark guards (conditions on a transition) and side effects (what runs on entry).
- Express it in TypeScript as a discriminated union plus a pure
transition function.
- Write a table test that walks every allowed transition and asserts
that at least one forbidden one is refused.Öz kodunda
- 1Statusu üç və ya daha çox boolean ilə saxlayan bir komponent tap.
- 2Hansı kombinasiyaların həqiqətən mümkün olduğunu yaz və vəziyyət diaqramını çək.
- 3AI-a onu discriminated union + reducer kimi yenidən yazdır və keçid cədvəli testini əlavə et.
Bunu görəndə bitib: Mümkün olmayan kombinasiya artıq tip səviyyəsində yazıla bilmir və keçid cədvəli testi keçir.
Daha dərinə
Oxumaq üçün
- Making Impossible States Impossible (talk) · Richard Feldman, 2016 · Bütün çıxış
- TypeScript Handbook — Narrowing · Microsoft · Discriminated unions
- Game Programming Patterns · Robert Nystrom, 2014 · «State» fəsli