"KISS!" у даному контексті не поцілунок, а "Keep It Simple, Stupid!"
Займаючись на роботі другою стадією робіт над проектом "CarWash" оглянувся в минуле. Згадав як починався проект, як я все собі уявляв... І порівняв з тим, як все вийшло. Початкова задумка була проста: створити систему керування агрегатами автомийки, яка б на натискання кнопок вибору режиму реагувала активізацією відповідних агрегатів (клапани, дозатори, помпа, etc.). Активізація мала проходити за певною програмою (точніше - за часовою діаграмою). Тож для цього я розробив простеньку мову програмування (5 операторів) та інтерпретатор. А керував цим усім - скінченний автомат (Finite State Machine). Приклад програми:
Ще є команда "wait", яка використовується у програмі зупинки та команда "off". "wait" просто призупиняє виконання програми на заданий час (очікування зупинки помпи перед закриванням клапанів), а "off" вимикає відповідний пристрій. Електроніка першої версії мала модульну архітектуру: багато однотипних контролерів чіплялись на шину RS-485 і працювали за протоколом ModBus. На шині також "висів" перетворювач топології RS-485/RS-232, через який шина підключалась до промислового комп'ютера. Дуже красива і scalable архітектура! Для її програмної підтримки у конфігураційному файлі прописувались аліаси всіх пристроїв. Якось так:
Два числа, розділених двокрапкою - це адреса і порт у протоколі ModBus. Ще є клас пристроїв, які мають одну адресу і один порт, а керуються окремими бітами стану пристрою (такими є, наприклад, кнопки режимів та індикатори).
Вся ця машинерія дуже добре працює зараз. Хоча функціонал її використовується лише на 50%: програми звелись до переліку пристроїв, а семантика датчика потоку зовсім змінилась. Нещодавно до мене поступила друга версія електроніки. Замовник просив зробити її більш компактною. В результаті зараз хоч і підтримується, але зовсім не використовується модульна архітектура: є декілька фіксованих контролерів (наприклад, контролер дисплея, головний контролер чи контролер кнопок), а агрегати (за виключенням двигуна помпи та шнеку подачі порошку) керуються бітами стану контролерів.
Я задумався над цим всім коли почав вносити зміни у код. Навіщо було розроблювати таку гнучку архітектуру? Навіщо робити інтерпретатор, систему подій, прораховувати логіку скінченного автомату (проштудіював підручник і списав не один листок паперу у процесі мінімізації автомату)? Всеодно приходиться переписувати код! Простіше було понаписувати hardcoded функцій реакції на натискання кнопок і просто їх викликати. За весь час тестування та реальної роботи установки програми були написані 1 раз і більше не змінювались. Регулювали лише дозатори піноутворювача та шнек. А от код переписувався багато разів. Одна тільки зміна семантики датчика протоку призвела до кардинальних змін у обробці подій та у таблиці переходів скінченного автомату.
Я прийшов до думки, що краще спершу зробити просто й тупо. А якщо в майбутньому виникне потреба - займатись архітектурними вивертами. Бо з часом красивий будинок з колонами перетворюється на сарай з підпорками. Ну або на високофункціональний і абсолютно не естетичний розподільний щиток.
Займаючись на роботі другою стадією робіт над проектом "CarWash" оглянувся в минуле. Згадав як починався проект, як я все собі уявляв... І порівняв з тим, як все вийшло. Початкова задумка була проста: створити систему керування агрегатами автомийки, яка б на натискання кнопок вибору режиму реагувала активізацією відповідних агрегатів (клапани, дозатори, помпа, etc.). Активізація мала проходити за певною програмою (точніше - за часовою діаграмою). Тож для цього я розробив простеньку мову програмування (5 операторів) та інтерпретатор. А керував цим усім - скінченний автомат (Finite State Machine). Приклад програми:
on COLD_WATER_EMV # відкрити клапан подачі холодної води set MOTOR_CONTROLLER 128 # встановити оберти двигуна помпи on MOTOR_SWITCH # ввімкнути двигун помпи waitfor STREAM_SENSOR # очікувати на активацію датчика потоку on FOAM_BUTCHER # ввімкнути дозатор піноутворюючої рідини on AIR_EMV # відкрити клапан подачі повітря
Ще є команда "wait", яка використовується у програмі зупинки та команда "off". "wait" просто призупиняє виконання програми на заданий час (очікування зупинки помпи перед закриванням клапанів), а "off" вимикає відповідний пристрій. Електроніка першої версії мала модульну архітектуру: багато однотипних контролерів чіплялись на шину RS-485 і працювали за протоколом ModBus. На шині також "висів" перетворювач топології RS-485/RS-232, через який шина підключалась до промислового комп'ютера. Дуже красива і scalable архітектура! Для її програмної підтримки у конфігураційному файлі прописувались аліаси всіх пристроїв. Якось так:
COLD_WATER_EMV 0x01:0x01 HOT_WATER_EMV 0x02:0x01 FOAM_BUTCHER 0x03:0x01 MOTOR_CONTROLLER 0x04:0x01 MOTOR_SWITCH 0x04:0x02 STREAM_SENSOR 0x01:0x02 AIR_EMV 0x05:0x01
Два числа, розділених двокрапкою - це адреса і порт у протоколі ModBus. Ще є клас пристроїв, які мають одну адресу і один порт, а керуються окремими бітами стану пристрою (такими є, наприклад, кнопки режимів та індикатори).
Вся ця машинерія дуже добре працює зараз. Хоча функціонал її використовується лише на 50%: програми звелись до переліку пристроїв, а семантика датчика потоку зовсім змінилась. Нещодавно до мене поступила друга версія електроніки. Замовник просив зробити її більш компактною. В результаті зараз хоч і підтримується, але зовсім не використовується модульна архітектура: є декілька фіксованих контролерів (наприклад, контролер дисплея, головний контролер чи контролер кнопок), а агрегати (за виключенням двигуна помпи та шнеку подачі порошку) керуються бітами стану контролерів.
Я задумався над цим всім коли почав вносити зміни у код. Навіщо було розроблювати таку гнучку архітектуру? Навіщо робити інтерпретатор, систему подій, прораховувати логіку скінченного автомату (проштудіював підручник і списав не один листок паперу у процесі мінімізації автомату)? Всеодно приходиться переписувати код! Простіше було понаписувати hardcoded функцій реакції на натискання кнопок і просто їх викликати. За весь час тестування та реальної роботи установки програми були написані 1 раз і більше не змінювались. Регулювали лише дозатори піноутворювача та шнек. А от код переписувався багато разів. Одна тільки зміна семантики датчика протоку призвела до кардинальних змін у обробці подій та у таблиці переходів скінченного автомату.
Я прийшов до думки, що краще спершу зробити просто й тупо. А якщо в майбутньому виникне потреба - займатись архітектурними вивертами. Бо з часом красивий будинок з колонами перетворюється на сарай з підпорками. Ну або на високофункціональний і абсолютно не естетичний розподільний щиток.