17 principles of Unix software design, from Eric Raymond's *The Art of Unix Programming*. You can refer to these principles when carrying out software design.
Rule of Modularity: Write simple components, connected through clear interfaces.
Rule of Composition: Design programs to be connectable with other programs.
Rule of Separation: Separate strategy from mechanism; separate interface from engine.
Simplicity Principles
Rule of Clarity: Clarity is better than cleverness.
Rule of Simplicity: Design for simplicity; only add complexity when necessary.
Rule of Parsimony: Write large programs only when it is clearly proven that there is no alternative.
Rule of Extensible: Design for the future, as it will come faster than you think.
Robustness Principles
Rule of Transparency: Design for visibility to make inspection and debugging easier.
Rule of Robustness: Robustness is the product of transparency and simplicity.
Rule of Representation: Embed knowledge in data so that program logic can be simpler and more robust.
Rule of Least Surprise: In interface design, always do the least surprising thing.
Rule of Silence: When a program has nothing to say, it should say nothing.
Rule of Repair: When you have to fail, fail fast and loudly.
Efficiency Principles
Rule of Economy: Programmer time is expensive; prioritize saving programmer time over machine time.
Rule of Generation: Avoid writing code manually; use code generators (such as protobuf, SQLAlchemy, cargo-generate) to replace repetitive work.
Rule of Optimization: Prototype comes before optimization. Make it work first, then optimize after locating bottlenecks with profiling tools.
Diversity Principles
Rule of Diversity: Question all claims of "the only correct way".
Supplementary Principles
Design data streams in text format as much as possible (easy to view and filter with standard tools).
Database layouts and application protocols should adopt text format as much as possible (JSON/YAML/TOML, human-readable and editable).
Complex frontends (user interfaces) should be clearly separated from complex backends.
Prioritize modern system-level languages such as Rust/Go/Zig; quickly build prototypes with Python/TypeScript, then optimize critical paths with compiled languages.
Use uv to manage Python dependencies, cargo to manage Rust dependencies, and npm/pnpm to manage JS dependencies.
Be generous with input and strict with output.
Never discard unwanted information when filtering.
Small is beautiful. Write programs that do as little as possible while being consistent with completing the task.
Encapsulate applications with Docker/containerization to ensure consistency between development and production environments.
Automate testing and deployment with CI/CD pipelines.