Anyone who has worked on a software project of even moderate size or duration will know that projects tend to accumulate technical debt. However, the exigencies of software development in the real world often mean that little is done to deal with accumulated technical debt until it has grown to the point where it simply cannot be ignored any longer, and thus a costly and time-consuming reengineering of the system cannot be avoided. Technical debt in practice is a compact but wide-ranging survey of technical debt in software projects, covering different phases of the software life cycle, from requirements to deployment, and describing methods for the identification, avoidance, measurement, management, and mitigation of such debt.
The authors point out that the problem with technical debt is not necessarily the debt itself, but rather neglecting debt--that is, failing to identify it, measure it, manage it, and ultimately reduce it. Furthermore, they point out that code is not the sole carrier of debt--other dimensions of a software project (requirements, architecture, documentation, and so on) can also accumulate significant technical debt. The book addresses these aspects by discussing the identification, management, and avoidance of technical debt in successive phases of the software life cycle, that is, requirements, architecture and design, implementation, testing, and deployment. In addition, technical debt in the overarching social/organizational and documentation aspects of software projects is also addressed. The core of the book addresses each of these phases or aspects in a separate chapter, each of which is structured around the identification-management-avoidance paradigm. In addition are chapters on technical debt in machine learning systems and another on explaining technical debt in software to nontechnical management. Detailed case studies from four diverse fields are interspersed. An additional feature of this book is the inclusion of interviews with practitioners who describe their individual experiences with technical debt and the subsequent lessons learned.
The book provides a comprehensive, fresh look at software project management and project architecture: it first treats technical debt as something to be incurred as needed and managed over time, rather than merely as something to be avoided; it then points out that technical debt accumulates in different phases of the software life cycle. Further, the systematization of debt control in terms of the identify-manage-avoid approach is a useful generalized strategic principle for software project management. The measurement methods and solution strategies, however, will clearly need to be customized to the needs of particular domains and projects--for example, the general strategy described in chapter 2--“focus on the important aspects of the problem as you understand them today, and release some version of the system to get feedback and to get a sense for what it should be doing”--is obviously unsuitable for critical systems in aviation, marine, medical, and some industrial manufacturing and control domains, at least from operations, regulatory, and user acceptance points of view. That being said, other advice is right on target. For example, chapter 4 (“Design and Architecture Debt”) says “the best way to avoid architecture debt is to never incur it in the first place”--something it is hard to disagree with, but still happens all too often. (As an aside, the authors mention flight-critical systems specifically as one class of systems where care in up-front design is essential.)
Software architects, project managers, and technical leads on software projects will find this book particularly useful for its scope, insights, and solution ideas. It is a broad-ranging, well-written, and very readable text.