Как я могу структурировать программу (proces) с очень большим количеством операторов IF
Мне нужно создать программу для своего рода сложных процессов.
Ну, процесс не является сложным, но есть много переменных, которые контролируют процесс.
Я не могу подробно рассказать о процессе, поэтому я составил один, который имеет ту же нагрузку IF:
процесс: следует ли остановить печь для расплавления железа или нет.
У нас есть следующие параметры:
если температура превышает 800 градусов Цельсия, остановите ее
Кроме того, когда мы ожидаем, что холодная вода будет доступна из печи 2 в течение следующих 20 минут, мы можем продолжить
За исключением тех случаев, когда температура в ближайшие 10 минут повышается на 10 градусов, мы не можем ждать еще 10 минут для холодной воды, поэтому мы должны остановиться.
Кроме того, когда температура по какой-то причине снижается до 790-800 градусов в течение 5 минут, мы добавляем дополнительные 5 минут к тому времени, когда нам нужна дополнительная прохладная вода.
Кроме того, когда температура по какой-то причине снижается до 780-790 градусов в течение 5 минут, мы добавляем дополнительные 5 минут к тому времени, когда нам нужна дополнительная прохладная вода.
и т.д.. и др.
Вы все можете подумать о других 20, кроме /if/then
в нашем процессе мы имеем > 50 ситуаций, все для одной цели: если машина остановится или нет.
Я должен сказать, что у меня обычно не так много ситуаций для одной цели/проблемы (а именно: остановите машину или нет), и это также связано со временем: если это происходит в течение 10 минут, тогда... и мы должны каждую минуту вычислять ситуацию.
Есть ли способ запрограммировать это по-умному?
(а также unit test, потому что у нас есть нагрузки и нагрузки комбинаций, которые являются отдельными модульными тестами, которые я предполагаю?)
Ответы
Ответ 1
Некоторые проблемные пространства не вписываются в принцип ООП очень элегантно. Похоже, ваша ситуация может быть намного лучше реализована в парадигме, основанной на правилах (особенно при изменении правил).
Вот пример платформы, основанной на правилах для .NET: http://www.codeproject.com/KB/cs/Drools_NETPrimer.aspx
Ответ 2
Вместо того, чтобы вручную выработать все ситуации, в которых вы должны остановить печь, основываясь на ваших знаниях о том, как работает печь, вы можете заставить компьютер сделать это за вас.
Попробуйте запрограммировать модель работы печи, и в каждый момент времени вы можете запустить симуляцию того, что произойдет в ближайшие 10 минут или около того. Если симуляция показывает, что вскоре возникнет серьезная проблема, вы можете остановить печь сейчас, иначе пусть она запустится на минуту, прочитайте входы и снова запустите симуляцию.
Кодирование точной модели потребует определенных усилий, но по мере небольшого изменения вашего требования (например, ваше обновление было обновлено или отремонтировано) было бы относительно легко обновить модель - в лучшем случае вы просто измените параметры модели или обновите единственная формула.
При вашем текущем подходе, если вы немного изменили духоту, вам нужно сначала вычислить вручную, какие эффекты будут иметь, а затем пройти через весь код по очереди, обновляя различные условия.
Что касается модульного тестирования - в идеале вы должны протестировать свою модель на данных из реальной печи в различных ситуациях и проверить, что ваше симуляция предсказывает фактические измеренные результаты (с некоторым допуском, допускающим неточности чтения). Если это невозможно, вы можете жестко указать некоторые примеры сценариев и ожидаемый результат (например, перегрев) и проверить, что симуляция правильно предсказывает результат.
Ответ 3
imho, как вы рассуждаете о проблеме, очень похож на конечный автомат.
Итак, это больше о моделях состояний и о том, что вы можете сделать в каждом из них. WF упоминался для другого использования (на самом деле его набор правил), но я бы посмотрел больше на рабочие процессы на основе штата, так как там вы можете сосредоточиться на каждом из этих состояний и как вы можете перейти между ними.
Ответ 4
+1 bump MrDosu ответьте на правила. Простой механизм правил, такой как механизм правил WF, может быть достаточным для того, что вам нужно. Пока вы используете .NET 3.0+, вы можете использовать это программно, не используя рабочие процессы.
EDIT: модульное тестирование должно быть простым, но трудоемким, чтобы создать все сценарии для тестирования. Данные (класс), которые вы отправляете в качестве входа в механизм правил, являются текущим состоянием сценария. Создайте несколько состояний или сценариев и отправьте их в механизм правил в unit test. Или вы можете комбинировать несколько состояний один за другим в одном unit test для проверки логической прогрессии
EDIT2: некоторый исходный код для использования наборов правил WF
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ServiceModel.Description;
using System.Xml.Schema;
using System.Workflow.Activities.Rules;
using System.Workflow.ComponentModel.Serialization;
namespace ServiceMediation.Behaviors
{
public class TransformingMessageServiceBehavior : IServiceBehavior
{
private string _ruleSetPath = null;
private RuleSet _ruleSet = null;
public TransformingMessageServiceBehavior(string ruleSet)
{
if (!string.IsNullOrWhiteSpace(ruleSet))
{
_ruleSetPath = ruleSet;
WorkflowMarkupSerializer serializer = new WorkflowMarkupSerializer();
XmlTextReader reader = new XmlTextReader(_ruleSetPath);
RuleDefinitions rules = serializer.Deserialize(reader)
as RuleDefinitions;
_ruleSet = rules.RuleSets[0];
}
}
...
а затем что-то вроде
RuleValidation validation = new RuleValidation(typeof(EvaluationData), null);
RuleExecution exec = new RuleExecution(validation, data);
_ruleSet.Execute(exec);
с EvaluationData
= данные, которые вы вводите в качестве ввода. Эти правила вводятся в правила. Он также служит результатом вывода, проверяет результат выполнения набора правил на свойстве данных.
Ответ 5
Найдите библиотеку, которая обеспечивает реализацию для конечного автомата и смоделирует ваш процесс как fsm. Существует несколько вопросов о fsms в stackoverflow: http://www.google.com/search?sourceid=chrome&ie=UTF-8&q=fsm+site:stackoverflow.com.