Sure! So by that point I could tell that typical normal software dev problems had not been magically solved by Google: in an ideal workplace maybe someone would have invented a corporate culture where the actual requests were "micro-sized" so that there were no surprises, but if someone has done this, it was not Google. So you commit to shipping a thing and you can't see all of the different parts of it.
So every project should be viewed as having work units and for each work unit you can define "I am 50% confident that it will be done in time T_50 and 80% confident it will be done in time T_80" and those are enough to define a log-normal distribution, whose cumulative density function is
P(t) = 1/2 [1 + erf[ ln(t / T) / (s sqrt(2)) ]]
for parameters
T and
Q, from there it's like if
P(
T_50) = 1/2 then I can work out that
T =
T_50 and from there
s =
k ln(
T_80 /
T_50) where
k is just a fixed number you can work out[1].
You can then generate a random number Z with Box-Muller[2] and then a random variable T exp(s Z) is log-normally distributed with the requested parameters. This is nice because the log-normal distribution is long-tailed so when it's off it's unusually off.
You can then look at some ongoing projects and the commits associated with that project and the research steps and reviews and all that which went into it, and say
- what things happened up til now and what is happening right now on this project
- what was estimated for those tasks, if nothing was estimated then they were "invisible", otherwise assume that was an 80% estimate, try to guess how the 50% "optimistic estimate" might have been different
- how did the tasks that I identified, depend on other tasks happening?
- and finally, I want to know, was this a task I did or a task somebody else did?
So on the basis of that you can start to either
1. take an upcoming project or two, or
2. generate a random tree-like project,
and throw in a bunch of these various things, and define some agents with deterministic strategies like "work on the oldest task" or "these nodes are hidden, now work on the visibly-longest chain of tasks" or the like. Then for a given assignment of times to all the random variables, you can see which algorithm was able to do the project fastest and you can dig into an event log to see what were they doing at the time.
Rather than "start on the hardest problem, the longest chain of dependencies" being the best like I would have expected, it was usually wrong, dominated by approaches like "do the smallest task first," because those could multiplex the review times, "please review this, please review that, I'll be working on this third thing." They did have problems with "okay now there is a long hard slog at the end" but the latency savings usually made up for it at the beginning.
I think that probably you could find a balance between the two that would work even better, "start with a couple fast tasks then work on a slow one, try to do fast-fast-slow all throughout," but that was hard to program and I already had my fundamental lesson that I needed to change my workflow.
1: https://www.wolframalpha.com/input?i=solve+%281+%2B+erf%281%...
2: https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform