Every project is influenced by a number of forces that make it less than ideal. Sometimes these forces can be business decisions that create a rate of change faster than a development team can meet with perfection, other times it is technical limitations that prevent ideal solutions from being implemented, and sometimes it is simply the misappropriate application of tools and libraries that can’t fit all of the needs of the business.
Regardless of the source of these forces, anything that has a significant impact on a team delivering perfect software is worthy of documenting. Identifying and clarifying such influential forces provides newcomers with a better context to the decisions that a team might have made along the way, and better yet, provide a way of highlighting them and their undesirable effects, so they could be removed if they no longer apply.
When it comes to the technical forces affecting the level of code being produced (e.g. a library not behaving accordingly, or an unforgiving production environment), the best way that these forces should be documented is in the form of tests. Developers would not be expected to run these, and should be left for execution by a build machine running in a production-like environment. Continuous integration serves as a great mechanism to inform us when the undesirable conditions that forced the creation of less-than-perfect-code, goes away, and highlights what can be changed to bring it that much closer to perfection.