Cіпласпластик: post #521 — TG.ME

Я обожнюю скінченні автомати. Це штука, яку дуже легко втямити і яка потім вам знадобиться мільйон разів. Їх можна використовувати для опису процесів, автоматизацій на кшталт IoT або CI/CD, діалогів або поведінки НІПів в іграх, парсингу тощо. Завдяки їм зручно контролювати послідовність виконання чого-небудь, робити відновлення до попередніх станів, обробляти помилки. (Памʼятаю, у нас у MBUX був скінченний автомат для підʼєднання телефону до автівки по Bluetooth… на півтори сотні станів 😵‍💫 Гляньте якось BT-спеку заради цікавості).

Але найулюбленіший мій спосіб їх використовувати — це звісно UI. Як усім відомо, найбільша проблема UI — це комбінаторний вибух станів. Якщо у вас купа «прапорців», які можуть по-різному впливати на поведінку програми, то інколи навіть утримати це все в голові важко. Але щойно ви робите скінченний автомат, усе стає значно легшим!

На прикладі вгорі якраз такий для мого таймера на Pebble. На годиннику всього чотири кнопки, але уявіть собі код обробки натискання BACK без скінченного автомата: це був би довжелезний ланцюг if-else штибу «якщо таймер запущений, але не на павзі», «якщо таймер запущений і на павзі, але програється анімація скидання» і ще десяток таких. Натомість я описав окремі стани програми, і в кожному стані у кожної кнопки лише одна функція. Я писав на
💻, тому обробник натискання кожної кнопки перетворився на простий switch.

Але бувають способи й красивіше. Наприклад, QML дозволяє описувати скінченні автомати декларативно. Обожнюю цей підхід. Також існує цілий окремий стандарт для опису скінченних автоматів в
💻SCXML; деякі тулзи вміють його читати, навіть той же 💻.

Проте той же таймер мій — це дуже проста програма. Що робити, коли в'юшок стає багато? Ну, вочевидь робити більше скінченних автоматів!

Доволі зручно робити їх ієрархічними. Уявіть типове IDE, в якому є «звичайний» режим кодінгу і є окремий режим зневадження — це ваш скінченний автомат верхнього рівня з двома станами. У кожного автомата є точка входу, наприклад, в IDE ви завжди починаєте у звичайному режимі. Коли ж ви перемикаєтеся в режим зневадження, то на екрані відбувається багато чого: відкриваються нові панелі, зникають інші, міняються гарячі клавіші, інколи навіть кольорова тема змінюється. У принципі для цього всього можна було б побудувати гігантський «плаский» скінченний автомат, але значно зручніше робити їх вкладеними: наприклад, щойно ви попадаєте в стан зневадження, ви активуєте інший скінченний автомат, що контролює ті ж панелі чи гарячі клавіші. У нього буде власна точка входу й власні стани, і найголовніше — йому взагалі не треба навіть знати про існування звичайного режиму.

На діаграмі цього нема, але в моєму таймері насправді теж є дещо схоже. Річ у тім, що з головного екрану перед запуском таймера можна по довгому натисканню на SELECT зайти у вікно вибору кольорових тем, тож фактично є два стани верхнього рівня: сам таймер та його налаштування. Останні — це звичайний список, який можна гортати вгору-вниз відповідними кнопками, можна підтвердити вибір або повернутися назад. SDK платформи фактично дає напівготовий компонент для цього, тож мені не довелося писати все вручну, але всередині там звісно теж якась імплементація скінченного автомата.

Окрім цього стани можуть паралельними, що якраз чудово комбінується з ієрархічними станами. Коли спробуєте побудувати щось більш-менш складне, зрозумієте, де саме це стає в пригоді.

Переходи між станами також можна робити по-різному: це може бути реакція на щось, може таймер спрацьовувати, може бути безумовний миттєвий перехід, може бути перехід зі стану в той самий стан (наприклад, заради сайд-ефектів, що виконуються при вході або при виході) тощо.

Одна з розповсюджених помилок, які я бачу: зробити основу UI на автоматі, а потім за якоїсь термінової потреби «примазати» там десь фічу звичайним ifʼчиком. Повірте на слово, робити так не варто — у майбутньому пожалкуєте десять разів. Краще зробіть це частиною цього ж автомата або ж додайте ієрархію.

До речі, за брак зручної можливості робити скінченні автомати я не люблю автоматизації в Home Assistant.
👍186🔥5🤯1👀11
July 3, 2026 1.2K 55 18