A Philosophy of Software Design by John Ousterhout focuses primarily on what separates good software design from bad software design.
Understand why you disagree with coding advice found in books like this one or Clean Code.
Complexity in software is more apparent to readers than writers.
Good design should be obvious; symptoms of complexity include change amplification, cognitive load, and unknown unknowns.
Modules should be deep and complex implementations hidden behind simple interfaces with sensible defaults.
Try to pick approaches that are radically different from each other when designing software.
Comments should be used to explain things that can't be expressed in code and the biggest challenge with cross-module documentation is finding a place to put it.
Enforce coding conventions and coding style preferences using automated tools like ESLint and Prettier.
Concentrate on strategic programming and don’t focus just on features.
Tests, particularly unit tests, play an important role in software design because they facilitate refactoring.