Лучший подход для многих ко многим отношениям в дизайне доменов optaplanner
Привет, я хотел бы спросить, какой подход использовать при разработке домена для проблемы, которую я пытаюсь решить, как я вижу в примерах, дизайн имеет тенденцию быть похожим на модель отношений сущностей, где, например, решаются отношения многие ко многим поместив ассоциативную сущность между двумя сущностями. У меня вопрос, почему это так, это помогает в производительности, и я должен следовать этому шаблону проектирования?
1 ответ
Отношения многие ко многим, где обе стороны являются проблемным свойством (например, если оба класса являются проблемным фактом)
Использование ассоциированной сущности необязательно: это ваш проектный вызов. OptaPlanner не волнует, но Drools заботится, так что это может повлиять на эффективность ваших DRL.
Например, давайте предположим, что между многими Employee
и Skill
, Сотрудник имеет несколько навыков, а навык достигается несколькими сотрудниками. Я написал большинство примеров, и я предпочитаю использовать ассоциированные объекты - поэтому я бы использовал SkillAttained
класс здесь (хотя новый пример, taskassigning
будет избегать этих ассоциированных организаций в качестве демонстрации и улучшить охват тестами).
Что касается влияния на производительность, все зависит от того, как хеширование и комбинация учитываются. И как это влияет на вычисление добавочной оценки (см. Документы об этой последней концепции). В любом случае, избегайте ненужного accumulates
а также collect
Находится в ДХО, так как они еще не полностью работают в пошаговом режиме и, следовательно, снижают коэффициент усиления при расчете добавочного балла.
С SkillAttained
обычно легче получить хорошую производительность и разработать правила.
when
ShiftAssignment($s : shift, $e : employee) // The when side must always contain a planning entity
SkillRequired(shift == $s, $s : skill) // Small perf opportunity: ShiftAssigment.getEmployee().getRequiredSkills() would avoid a lookup
not SkillAttained(employee == $e, skill == $s) // Good: the skill matching uses hashing for scalability if there are many skills
then
...addHard(-1); // Fires once per 1 missing skill
Без этого часто труднее писать - без использования накоплений или сборов. Однако такой метод, как Employee.hasSkill(Skill)
(предполагая, что навыки работника находятся в LinkedHashSet
) очень эффективно.
when
ShiftAssignment($c : countMissingSkills())
then
...addHard(- $c); // Fires once per ShiftAssignment with at least 1 missing skill
Так что в этом примере ShiftAssignment.countMissingSkills()
должен быть действительно эффективным (например, использовать LinkedHashSet/Maps и т. д.).
Многие ко многим отношениям, которые являются @PlanningVariabe
В настоящее время OptaPlanner 6.4 пока не поддерживает много-много взаимосвязей переменных планирования. Проголосуй за эту джиру. Таким образом, для решения этой проблемы требуется ассоциированная организация.