Tuesday 16 March 2010

Reuse

Re-use is now an established trend. And that's a good thing.

But we go about it in a very back-to-front way.

Primarily, code re-use tends to be a very code-oriented practice. We look at a piece of code, its functionality, performance and other characteristics and decide it makes a good candidate for re-use. And so, it gets re-used. And we find that in the re-use, it didn't quite do what we wanted. We then have to spend a lot of effort re-engineering it towards our needs. We bang a lot of square pegs into round holes.

What went wrong? We put the cart before the horse. We attempted to re-use code, a derived artefact of the software engineering process without considering the original, motivating cause of that engineering effort - the requirements.

Written, implemented code is a concrete solution to some specified problem. The requirements for the code are a pure expression of the problem we need to solve. In attempting to directly re-use code without comparison or consideration of the requirements that led to that code, we're hoping that one solution solves two problems. We're hoping that a given solution can solve problems that were not known, or at least addressed during implementation.

More explicit consideration of the requirements in the re-use process has potential benefits for all parties. For the client code, wishing to re-use some candidate piece of code, we can ensure that it is a good fit for our requirements. If there is a mismatch between requirements, this clearly identifies where work is needed. These conflicting requirements can now inform the design process, to ensure that the any modifications to the re-used code are implemented appropriately, and not simply bolted on, polluting the code. We can more accurately estimate the work required, rather than attempting to untangle the specifics of implementation, piece, by piece, by piece.

Monday 15 March 2010

Critical Chain Project Management

The Critical Chain project management methodology has some interesting ideas that are very relevant to games projects.

1. Time is not used to figure out the critical chain of a project. Instead, dependencies are used.
2. Buffers and padding are not placed at the end of each activity. Instead, they are placed, in aggregate, at the end of the project.

(1) is particularly salient for two reasons. Firstly, as is well known, software remains resolutely incredibly difficult to estimate accurately; what is the point, therefore, in using inherently inaccurate estimates to attempt to calculate your critical chain? Dependencies are a critical factor your ability to deploy resources. You cannot add resources to expediate a particular activity if dependent work is held up. Conversely, identifying those points in a project that have the maximal tasks dependent upon them highlights them as points in the project that need maximal resources to ensure their successful completion and enable dependent tasks to begin.

(2) is simply Parkinson's law. Adding padding to each task makes its timely completion far less critical, and therefore things begin to slip. Critical Chain instead calls for all activities to be begun and completed as quickly as possible (as doing so eliminates them as a dependency allowing further work to begin) and the padding is instead added at the end of the project. This change therefore means that the scheduling of a particular task is purely dependent on its input dependencies, not a function of the dependencies and the padding.

And furthermore, what sense does it make to add 20%, say, to an inherently inaccurate estimate anyway? Why not 10%? Why not 50%? Such a practice is meaningless.

Critical Chain is not a massively revolutionary technique, but its different perspective on some fundamentals of project management is quite insightful.