Вирішуючи проблему, якщо веб, ви можете створити двигун правил, де кожне конкретне правило кодується незалежно. Наступним уточненням цього було б створення мови для домену (DSL) для створення правил, однак лише DSL зміщує проблему з однієї бази коду (основної) на іншу (DSL). Без структури DSL не обійдеться нічим кращим, ніж рідна мова (Java, C # тощо), тому ми повернемося до неї після того, як знайдемо вдосконалений структурний підхід.
Основоположним питанням є те, що у вас виникає проблема моделізації. Кожного разу, коли ви стикаєтеся з подібними комбінаторними ситуаціями, це явна ознака того, що ваша абстракція моделі, яка описує ситуацію, занадто груба. Ви, швидше за все, комбінуєте елементи, які повинні належати до різних моделей в одне ціле.
Якщо ви продовжуєте ламати свою модель, ви врешті-решт повністю розчинять цей комбінаторний ефект. Однак, пройшовши цей шлях, легко розгубитися у дизайні, створивши ще більший безлад, перфекціонізм тут не обов'язково є вашим другом.
Машини з кінцевим станом і двигуни з правилом - лише приклад того, як цю проблему можна зруйнувати та зробити більш керованою. Основна ідея тут полягає в тому, що хороший спосіб позбавитись від комбінаторної проблеми, такої, як це часто, - це створити дизайн і повторити його adusevuseam у вкладених рівнях абстракції, поки ваша система не працює на задовільному рівні. Зазначте, як фрактали використовуються для створення складних візерунків. Правила залишаються незмінними, незалежно від того, якщо ви дивитесь на вашу систему за допомогою мікроскопа або з високого огляду птахів.
Приклад застосування цього до вашого домену.
Ви намагаєтеся моделювати, як корови рухаються по місцевості. Хоча у вашому запитанні бракує деталей, я б здогадався, що ваша велика кількість ifs включає фрагмент рішення, наприклад, if cow.isStanding then cow.canRun = true
але ви забиваєтесь, додаючи, наприклад, деталі про місцевість. Тому для кожної дії, яку ви хочете здійснити, ви повинні перевірити всі аспекти, які ви можете придумати, і повторити ці перевірки для наступної можливої дії.
Спочатку нам потрібна наша повторювана конструкція, яка в цьому випадку буде FSM для моделювання мінливих станів моделювання. Отже, перше, що я зробив би - це реалізувати довідковий FSM, визначаючи інтерфейс стану, інтерфейс переходу та, можливо, контекст переходуяка може містити спільну інформацію, яка повинна бути доступною для інших двох. Основна реалізація FSM переключиться з одного переходу на інший незалежно від контексту, саме тут надходить двигун правил. Двигун правил чітко включає в себе умови, які повинні бути виконані, якщо відбудеться перехід. Тут двигун правил може бути таким же простим, як і список правил, кожен з яких має функцію оцінки, що повертає булеву форму. Щоб перевірити, чи повинен відбутися перехід, перейдіть до списку правил, і якщо будь-яке з них оцінюється як помилкове, перехід не відбувається. Сам перехід буде містити код поведінки для зміни поточного стану FSM (та інших можливих завдань).
Тепер, якщо я починаю реалізовувати моделювання як єдиний великий FSM на рівні GOD, я закінчую багато можливих станів, переходів і т. Д. Якщо все-таки безлад виглядає так, як він виправлений, але насправді просто поширюється навколо: кожен ІФ тепер правило, яке виконує тест на конкретну інформацію контексту (яка на даний момент містить у собі все), і кожен орган IF знаходиться десь у перехідному коді.
Введіть фрактал розбиття: першим кроком буде створення FSM для кожної корови, де штати є власними внутрішніми станами корови (стояння, біг, ходьба, випас тощо), а переходи між ними впливатимуть на навколишнє середовище. Можливо, що графіка не є повною, наприклад, пасовище доступне лише з стоячого стану, будь-який інший перехід заборонено, оскільки просто відсутній у моделі. Тут ви ефективно розділяєте дані у двох різних моделях, корова та місцевість. У кожного свій набір властивостей. Ця розбивка дозволить вам спростити загальну конструкцію двигуна. Тепер замість того, щоб мати механізм єдиного правила, який вирішує всі, у вас є кілька, більш простих двигунів правил (по одному для кожного переходу), які вирішують дуже конкретні деталі.
Оскільки я повторно використовую той самий код для FSM, це в основному конфігурація FSM. Пам'ятаєте, коли ми згадували про DSL раніше? Тут DSL може принести багато корисного, якщо у вас є багато правил і переходів для написання.
Заглиблюючись
Тепер БОГу більше не доводиться стикатися з усією складністю управління внутрішніми станами корови, але ми можемо просунути її далі. Наприклад, існує велика кількість складностей в управлінні місцевістю. Тут ви вирішите, де достатньо розбиття. Якщо, наприклад, в БОГІ ви закінчите керувати динамікою місцевості (довга трава, грязь, суха грязь, коротка трава тощо), ми можемо повторити ту саму схему. Ніщо не заважає вам вбудовувати таку логіку в саму місцевість, витягуючи всі стани місцевості (довга трава, коротка трава, каламутна, суха тощо) у новий місцевий FSM з переходами між державами та, можливо, простими правилами. Наприклад, щоб потрапити в каламутний стан, двигун правил повинен перевірити контекст, щоб знайти рідини, інакше це неможливо. Тепер БОГ все ж спростився.
Ви можете доповнити систему FSM, зробивши їх автономними та додавши їм кожну нитку. Цей останній крок не є необхідним, але це дозволяє змінювати взаємодію системи динамічно, регулюючи як делегувати прийняття рішень (запуск спеціалізованого FSM або просто повертають попередньо певний стан).
Пам'ятаєте, як ми згадували, що переходи також можуть виконувати "інші можливі завдання"? Давайте дослідимо це, додавши можливість для різних моделей (FSM) спілкуватися один з одним. Ви можете визначити набір подій і дозволити кожному FSM зареєструвати слухача цих подій. Таким чином, якщо, наприклад, корова потрапляє в місцевість місцевості, шестигранна може зареєструвати слухачів для змін переходу. Тут це стає трохи хитро, тому що кожен FSM реалізований на дуже високому рівні без будь-якого знання конкретної галузі, в якій він знаходиться. Однак ви можете досягти цього, якщо корова опублікує список подій, і клітина може зареєструватися, якщо бачить події, на які вона може реагувати. Тут хороша ієрархія родини подій - це хороша інвестиція.
Ви все ще можете просунутись глибше, моделюючи рівень поживних речовин та цикл росту трави, за допомогою ... ви здогадалися ... трава FSM, вбудована у власну модель пластиру місцевості.
Якщо ви підштовхуєте ідею досить далеко, БОГ має зробити дуже мало, оскільки всі аспекти значною мірою самостійно керуються, звільняючи час витрачати на більш благочестиві речі.
Резюме
Як було сказано вище, FSM тут не є рішенням, а лише засобом проілюструвати, що рішення такої проблеми не знайдено в коді за висловом, а як ви моделюєте свою проблему. Є найімовірніші інші рішення, які можливі і, швидше за все, набагато кращі, ніж мої пропозиції щодо УБП. Однак підхід "фракталів" залишається хорошим способом управління цією складністю. Якщо це зроблено правильно, ви можете динамічно розподіляти більш глибокі рівні там, де це важливо, надаючи більш прості моделі, де це менше значення. Можна змінити чергу і застосувати їх, коли ресурси стануть доступнішими. У послідовності дії може бути не все так важливо, щоб обчислити перенесення поживних речовин від коров'ячого до трави. Однак ви можете записати ці переходи та застосувати зміни пізніше або просто наблизити їх до освіченої здогадки, просто замінивши механізми правил або, можливо, замінивши реалізацію FSM взагалі більш простою наївною версією для елементів, які не знаходяться в прямому полі інтерес (корова на іншому кінці поля), щоб дозволити більш детальну взаємодію, щоб отримати фокус та більшу частку ресурсів. Все це без будь-якого перегляду системи в цілому; Оскільки кожна деталь добре відокремлена, стає легше створити заміну, що обмежує або збільшує глибину вашої моделі. Використовуючи стандартний дизайн, ви можете спиратися на це і максимізувати інвестиції, зроблені в спеціальних інструментах, таких як DSL, щоб визначити правила або стандартний словник для подій, знову починаючи з дуже високого рівня і додаючи уточнення за потребою. Оскільки кожна деталь добре відокремлена, стає легше створити заміну, що обмежує або збільшує глибину вашої моделі. Використовуючи стандартний дизайн, ви можете спиратися на це і максимізувати інвестиції, зроблені в спеціальних інструментах, таких як DSL, щоб визначити правила або стандартний словник для подій, знову починаючи з дуже високого рівня і додаючи уточнення за потребою. Оскільки кожна деталь добре відокремлена, стає легше створити заміну, що обмежує або збільшує глибину вашої моделі. Використовуючи стандартний дизайн, ви можете спиратися на це і максимізувати інвестиції, зроблені в спеціальних інструментах, таких як DSL, щоб визначити правила або стандартний словник для подій, знову починаючи з дуже високого рівня і додаючи уточнення за потребою.
Я хотів би надати приклад коду, але це все, що я можу дозволити собі зробити прямо зараз.