# How to design a flexible multi-criteria prioritization?

Let's assume that we have a set of valid results, ex. `Fruits`: `"Apple, Banana, Kiwi, Pear, ..."`. (In reality, it’s not fruits but complex objects)

Now we need to pick the best result according to some simple prioritization. For example, let's say this prioritization is simply an arbitrary order of preference determined on how well I like the `Fruit`:

``````Apple: 1
Banana: 3
Kiwi: 2
Pear: 4
``````

It is easy to design and implement a simple prioritization list to achieve this.

However I know that in a foreseeable future, we’ll need to use a much more complicated prioritization, which may rely on factors such as:

1. What other fruits are in the result set?
2. What other fruits aren't in the results?
3. Does a fruit have a dirty specks or not?
4. Was some fruit already picked in the past days?
5. Any other prioritization criteria

What approaches and design can be used for achieving such a flexible multi-criteria prioritization in a maintainable way, ie without relying on a big messy code with tons of edge cases?

I’ll assume that your set of results is finite and that you perform the prioritization when the set is fully known.

## First naive approach

The prioritization corresponds simply to a mapping function `s(o, r)->int` which takes as argument an object `o` of the result set to be prioritized, and the whole result set `r` and returns a priority score.

You may then implement the prioritization list by sorting the list according to the score of each element. This may be done for example by keeping in the list pairs of elements with their computed score, or by using an iterator on a map/dictionary.

## More robust solution

You may need to take into account the list of possible values (for finding out the missing ones) or the history of previous elements, or anything else the future will bring you.

Therefore you should extend the scoring to take into account these information in addition. You’d best achieve this by making a scoring class, that you can specialize as needed, to take whatever contextual information is relevant to calculate whatever score you need using the explicit parameters (o and r) as well as any contextual one.

This means that you’d best implement the scoring class as a strategy pattern of your prioritization container/list. This will also enable you to consider performance issues and not always redo the same iteration on the sale full set of results if it is not necessary.

Pseudocode would be something like:

``````abstract class Scoring {
public initialize(); // determine loop invariants that are result-set independent
public prepare(ResultSet R); // operations to be done only once per result set
public score(ResultObject o); // calculate score using all available data, including prepared result set
};
``````

Of course, depending on your implementation language you may prefer an interface or protocol instead of a pure abstract class.

• Thank you for the comprehensive answer! It's well thought out, although I think I asked the question very misleadingly to what I'm actually trying to achieve. I'll mark it as correct answer since it will help others in the future! – Joe Jul 30 at 11:04

The priorities aren't complicated - they're still just numbers. The logic that assigns the priority number is more complicated.

Combining multiple factors by adding (or multiplying) them is normal - that way you can have an arbitrary number of classifiers and easily combine them without entangling the logic.

• Hi, thanks for the response! I think I was being a bit unclear in my question, as in the end we do not have numbers where we take the highest one that determine the result, but proper logical paths that can modify the result set / order based on the required business logic – Joe Jul 28 at 11:48
• Well, don't. Just assign a numerical ranking and use a priority queue. Bang, all that business logic spaghetti disappears in a puff of smoke. – Useless Jul 28 at 12:38