Вопрос к ООП-шникам — как организовать архитектуру для конвейера формул?
Здравствуйте.
Пишу на php некоторое приложение, которое для фирмы делает некоторый расчет.
Какие имеет сущности - фирма, у нее множество параметров (param1, param2, ..., paramN), есть несколько методик подсчета определенного уровня доверия, каждая методика включает коэффициенты, расчитываемые по формулам и таблица соответствия для каждой формулы.
Например: Рога и копыта
1. На рынке: 5 лет
2. Сфера: Промышленность
3. Бух. отчет парам. 1: 150 000 (условные параметры)
4. Бух. отчет парам. 2 2: 300 000
Если сфера промышленность, то при
коэф. 1 > 1 = 5 баллов,
коэф.1 = 1 = 3 балла,
коэф.2 < 1 = 1 балл.
Для иных сфера свои коэф., но мы их не рассматриваем в примере.
Один из важных аспектов - методик подсчета уровня доверия фирме может быть сколько угодно, у каждого свои коэффициенты и методики расчета, но на выходе мы всегда имеет некоторый суммарный балл, который нам и нужен.
Теперь к сути - почему-то мне видится, что обоснованным было бы применить ОО-модель с примерно следующей логикой организации:
Методика 1 - класс, имеющий массив коэффициентов.
Сами коэффициенты - тоже классы, внутри которых есть метод handler, запускающий расчет по формулам. Формулы - тоже в отдельные классы. Таблицы соответствия - тоже отдельные классы
И матрешкой одно в другое вкладывать.
Таким образом получится набор методик, внутри которых есть ряд коэффициентов, высчитываемых через формулы и таблицы соответствия этих формул набору значений.
Тут 2 ключевых вопроса и 1 общий.
1) Если делать так, как я сказал, как загружать, например, формулы в класс коэффициента? Какой придумать загрузчик в такой ситуации?
2) Как передавать формулам данные? Не в базу же данных каждая лезть будет, запросов будет тьма. Была мысль насчет формирования некоторого объекта-источника данных, как смотрите на это?
3) Не слишком заморочено? Просто хотелось бы иметь четкую стройную структуру, а не кучу друг на друге налепленных алгоритмов.
>> Какие имеет сущности - фирма, у нее множество параметров (param1, param2, ..., paramN), есть несколько методик подсчета определенного уровня доверия, каждая методика включает коэффициенты, расчитываемые по формулам и таблица соответствия для каждой формулы.
даже осилить смысл этого предложения проблематично
Простите, я совсем не мастер в ООП, но мне не совсем понятно - Вы собираетесь на каждый чих каждого менеджера вашей компании делать новый класс МетодикаN?
Я как-то представлял себе, что будет класс Методик, а его объекты будут каждый со своим набором формул из класса формул и ссылками на коэффициенты из таблицы коэффициентов, по ситуации.
Затем: как формулам передавать данные. Т.е. одни и те же данные надо обработать всем набором Методик?
Эээ... а зачем Методикам самим лезть в БД? Пусть из БД берет данные какой-нибудь ДатаМенеджер и раздает всем Методикам. И собирает с них урожай. И отправляет куда следует.
Просто выделите логику вычисления в отдельную группу классов и сделайте однотипную точку вызова (как в шаблоне Команда), без подробностей, как в Методике 1. Можно сделать два-три пробных класса и нужный алгоритм нарисуется сам собой, выделяя классы заранее можно легко ошибиться
"Вы собираетесь на каждый чих каждого менеджера вашей компании делать новый класс МетодикаN?"
Скажем так - не я собираюсь, а таковы условия задачи. Сейчас методика оценки одна, но заказчик вполне логично обосновал, что в будущем эти методики должны гибко добавляться, удаляться и пр.
Я как-то представлял себе, что будет класс Методик, а его объекты будут каждый со своим набором формул из класса формул и ссылками на коэффициенты из таблицы коэффициентов, по ситуации.
Собственно, и я так представляю, но абстрактно, ввиду малого опыта в ООП не могу пока сложить эти мысли в практическую реализацию.
Например, вот как это будет выглядеть, если писать такое процедурно
namespace BasicMethod;
calculatePerspective($company) {
return $company['param1'] / ($company['param7']) - $company['param4']);
}
calculateStability($company) {
return $company['param8'] * ($company['param1']);
}
calculateAutonomy($company) {
return $company['param8'] * ($company['param1']);
}
// соответствие
conformityPerspective($score, $company) {
// тут проверяем, сколько лет фирме и какой балл соответствует переданному $score, вычисленному через calculatePerspective();
}
conformityStability($score, $company) {
// то же, что и выше для стабильности
}
conformityAutonomy($score, $company) {
// то же, что и выше для автономности
}
function perspective($company) {
$score = calculatePerspective($company);
return conformityPerspective($score, $company);
}
function stability($company) {
$score = calculateAutonomy($company);
return conformityAutonomy($score, $company);
}
function autonomy($company) {
$score = calculateAutonomy($company);
return conformityAutonomy($score, $company);
}
Здесь определены процедуры для вычисления сначала коэффициента, а затем некоего балла для дальнейших сложений.
По идее, выполняться это должно так.
Некоторый участник заходит в систему и выбирает - расчитать балл доверия для компании такой-то по Методике 1.Базовая исходя из ее данных, полученных из некоторого источника за 2019 год.
Общий смысл такой - загнать формулы в БД не получится, там иногда встречаются сложные алгоритмы, которые надо заводить в функции, вне кода там голову сломаешь, что делать.
Почему мы не можем таблицу загнать внутрь calculate-функции? Дело в том, что нам придется на определенном этапе показывать результат calculate функции отдельно, а потом результат, пропущенный через таблицу соответствия.
Но здесь явно прослеживается механизм, который надо загонять в какие-то ООП-шаблоны, я-то и так костылей накручу, с костылями проблем нет, но если учится ООП, то не для теории, а для практики, вот хочется сделать красивую, правильную, рабочую схему.
Эээ... а зачем Методикам самим лезть в БД? Пусть из БД берет данные какой-нибудь ДатаМенеджер и раздает всем Методикам. И собирает с них урожай. И отправляет куда следует.
Совершенно правильно Вы говорите, данные должны приходить извне, но в каком виде?
По идее, функция должна получать только те данные, которые ей нужны для калькуляции. Но если мы пишем такой вот конвейер, то как указать, какие именно данные из набора нужны для передачи, а не передавать вообще массив всех параметров?..
Просто выделите логику вычисления в отдельную группу классов и сделайте однотипную точку вызова (как в шаблоне Команда), без подробностей, как в Методике 1. Можно сделать два-три пробных класса и нужный алгоритм нарисуется сам собой, выделяя классы заранее можно легко ошибиться