Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
scroll top