Reading A Philosophy of Software Design
As a hobby programmer, my greatest skill gap is achieving good software design. There's very little useful literature on problem decomposition and the main way of learning design seems a byproduct of writing lots of code.
The book starts by defining complexity in software and explaining its effects on the evolution and growth of systems. Along with this it defines the module, a unit of system decomposition that helps reason about design issues. The remainder of the book provides some key red flags to spot complexity, and presents principles and coding practices that improve design while controlling complexity.
Although general, these principles are precise enough to be applicable and effective. The principles and the red flags gently funnel a system along a path through the design space that progressively shapes the system to reduce complexity.
The strength of A Philosophy of Software Design is the guidance it provides helps achieve good design even without highly structured processes or step by step instructions. Ousterhout acknowledges with humility the vastity of the endeavour and doesn't promise silver bullets or instant solutions.
Another thing I like is the few code samples are surprisingly short, clear, and effective at making a point. Although the code is in Java and C++, the material applies to any language.