A modernized checklist of classic software engineering design principles in the context of AI collaboration. Used as a reference table during new module design, refactoring, and code review; it does not replace specific execution skills.
Trigger Scenarios
- Writing new modules, new services, new interfaces
- User says "design", "split modules", "review", "refactor"
/review、/new-feature、/optimize、/designcommand during the design phase- When assessing technical debt, use the principles to locate bad smells
Six Principles Quick Reference
| # | Principle | In One Sentence | Metric | Detailed Case |
|---|---|---|---|---|
| 1 | Moderate module size | Keep a single file within its responsibility boundary | Lines/responsibilities | Reference size-check |
| 2 | Reduce call depth | Keep call chains ≤ 3 levels where possible | Stack depth | modularity.md#call-depth |
| 3 | More fan-in, less fan-out | Being reused > actively depending | Number of dependencies/number of dependents | modularity.md#fan-in-fan-out |
| 4 | Clear interface boundaries | Unified inputs/outputs/exceptions | Unified response wrapper | modularity.md#clear-boundaries |
| 5 | Scoped cohesion | Changing A does not affect B | Cross-module side effects | Reference refactor-safety |
| 6 | Predictable functionality | Same input → same output | Idempotent/no side effects/testable | predictability.md |
1. Moderate module size
The main execution is delegated to the
size-checkskill; this skill only serves as an overarching reminder.
Core: A single file exceeding the limit is adesign signal, not a formatting issue. It indicates responsibility overload and should be split.
Default thresholds: Java ≤ 300 / Go ≤ 400 / Vue ≤ 200 / TS ≤ 300 / Python ≤ 300 (project may override).
2. Reduce call depth
❌ Counterexample:Controller → ServiceA → ServiceB → ServiceC → DAO → Mapper(6 levels). Locating a bug requires stepping into the stack layer by layer, making it hard for newcomers to understand.
✅ Positive example:Controller → Service → Repository(3 levels), with the rest decoupled via events/queues/pure functions.
Metric: A call stack depth > 5 is considered a bad smell. See modularity.md#call-depth。
3. More fan-in, less fan-out
❌ Counterexample:OrderService.createOrder() depends on UserService, CouponService, PaymentService, StockService, NotifyService, AuditService, CacheService, MetricsService (fan-out 8). Changing one place could break 8 places.
✅ Positive example:StringUtils.toCamelCase() is reused in 30 places across the project (fan-in 30). High reuse value, with no downstream pollution.
Metric: Direct dependencies of a single method ≤ 5; the more dependents, the better. See modularity.md#fan-in-fan-out。
4. Clear interface boundaries + unified error returns
A modernized rewrite of the "single entry, single exit" principle. Early return / guard clause is better than deep nesting.
❌ Counterexample: returns on success, {data}, throws an exception on failure, and there is also a return null, so callers need 3 handling paths.
✅ Positive example: unified {code, data, message} wrapping, with exceptions handled centrally at the boundary layer (middleware / interceptor). One entry/exit contract is consistent for all callers.
See modularity.md#clear-boundaries。
5. Scoped cohesion
Main execution is delegated to
refactor-safetyandmulti-tenant-safetyskill。
Core:
- Changes within a module should not cross boundaries and affect other modules
- Private implementation is not exposed as a public API
- Cross-module communication goes throughexplicit APIs, events, or messages, not through shared mutable state
6. Predictable functionality
❌ Counterexample:
- The same HTTP retry deducts payment twice (no idempotency key)
- Scheduled task fails across midnight (depends on system time zone)
- Unit test passes sometimes and fails sometimes (depends on external state)
✅ Positive example:
- Idempotency key deduplication (mandatory for write operations)
- Time is unified as UTC, converted at boundaries as needed
- Prefer pure functions, with side effects concentrated at boundaries (IO/DB/network)
See predictability.md。
Checklist (for PR / Review comparison)
Before adding or modifying a module, go through each item one by one:
- Size: Does a single file not exceed the line limit? Refer to
size-check - Depth: Is the call chain ≤ 3 levels? Is there no long chain A→B→C→D→E?
- Fan-out: Are there ≤ 5 direct dependencies? Have too many services been introduced?
- Boundary: Are there unified conventions for interface input parameters/output parameters/exceptions?
- Scope: Do the changes cross boundaries and affect other modules?
- Idempotency: Are retries/repeated calls safe?
- Implicit dependencies: Does it depend on implicit environments such as time zone, current time, random numbers, etc.?
Boundaries with other skills
| Principle | Main execution skill | Role of this skill |
|---|---|---|
| 1 Moderate size | size-check |
Trigger prompt |
| 2 Call depth | No independent skill | This skill leads |
| 3 Fan-in/fan-out | No independent skill | This skill leads |
| 4 Clear boundaries | api-design-safety |
Decision comparison |
| 5 Scoped cohesion | refactor-safety / multi-tenant-safety |
Trigger prompt |
| 6 Predictability | time-zone-safety / redis-safety / query-performance-safety |
This skill leads, specialized skills handle specific pitfalls |
This skill is thegeneral outline and decision comparison table, and the specific execution details are within the above skills.
Rule provenance
> 📋 本回复遵循:`code-quality-principles` - [原则编号]