I thought this deserved a coded example:
Imagine you are processing a list of 10 names.
Harriet
Charlie
Ruth
Peter
Bill
John
Alistar
Ken
William
Robert
We can think of these names, in programming, as an array. In javascript for example:
names = ["Harriet","Charlie,"Ruth","Peter","Bill","John","Alistar","Ken","William","Robert"]
Now let's process these names:
names.forEach(function(name){
if(isMale(name)){
sleep(10000) //imitate a long algorithm
} else {
sleep(100) //imitate a short algorithm
}
})
So already you can see that this is going to cause problems... When the name belongs to a male the algorithm takes 10 seconds (10,000 ms) to complete. However when the name belongs to a female, the algorithm takes 0.1 second (100ms) to complete. This isn't something you can easily get around. As it is by the spec that you have been given.
Now. What you may think is to do the following:
var males,females;
names.forEach(function(name){
if(isMale(name)){
males++;
} else {
females++;
}
})
var maleTime = males*10000;
var femaleTime = females*100;
var totalTime = maleTime + femaleTime
var males,females; //reset to 0
names.forEach(function(name){
if(isMale(name)){
males++;
sleep(10000) //simulate a long algorithm
} else {
females++;
sleep(100) //simulate a short algorithm
}
setProgress(males,females,totalTime)
})
That's great and all, but now you are assuming that your algorithm for a male name and a female name will take the same amount of time on everyones system. In this case because we are simulating it using sleep()
we can pretty much guarantee the time is constant. However with real algorithms it is going to change from machine to machine.
So in the real world you'd need to do something along the lines of:
var males,females;
names.forEach(function(name){
if(isMale(name)){
males++;
} else {
females++;
}
})
var realMaleTime = doAlgorithmFor("genericMale")
var realFemaleTime = doAlgorithmFor("genericFemale")
var maleTime = males* realMaleTime;
var femaleTime = females*realFemaleTime;
var totalTime = maleTime + femaleTime
var males,females; //reset to 0
names.forEach(function(name){
if(isMale(name)){
males++;
sleep(10000) //simulate a long algorithm
} else {
females++;
sleep(100) //simulate a short algorithm
}
setProgress(males,females,totalTime)
})
Okay so then we're done! That was easy! Well... Not quite... The same thing goes for all flow control in your code. That long algorithm should ideally be inspected further as it will likely also have flow controls which have this behaviour. Each flow control needs to be inspected in the same way and a progress bar wrapped around everything.
And then of course, when we are finished calculating all the progress times for all parts of the flow control and calculated exactly how long the algorithm will take for our dataset, we've already done more work than we had in the beginning... So our algorithm for seeing how long the algorithm will take probably needs it's own progress bar!
So in general, it is actually more intelligent to do, because it is always impossible to predict the behaviour of your application on other people's machines:
var iName=0;
names.forEach(function(name){
if(isMale(name)){
sleep(10000) //imitate a long algorithm
} else {
sleep(100) //imitate a short algorithm
}
setProgress(iName++,names.length)
})