Skip to content

Instantly share code, notes, and snippets.

@8ullyMaguire
Last active May 7, 2026 18:19
Show Gist options
  • Select an option

  • Save 8ullyMaguire/69fd61be824934d560f25b60b95408ef to your computer and use it in GitHub Desktop.

Select an option

Save 8ullyMaguire/69fd61be824934d560f25b60b95408ef to your computer and use it in GitHub Desktop.
Code Principles
## Core Philosophy
1. **Make complexity the #1 enemy** – Complexity makes code hard to understand or modify. Fight it continuously.
2. **Strategic over tactical programming** – Don’t just make working code; invest time in good design to reduce long‑term complexity. Avoid being a “tactical tornado”.
3. **Zero tolerance for complexity** – Complexity accumulates incrementally. Remove it aggressively, even from small changes.
4. **Design it twice** – Explore at least two radically different designs before choosing one.
5. **Obviousness is the goal** – Good design makes the system obvious to readers, not just to the author.
6. **It’s easier to see design problems in someone else’s code** – Use code reviews to gain that perspective.
7. **If you aren’t improving the design when changing code, you’re probably making it worse** – Always leave the design better than you found it (Boy Scout Rule).
---
## Module Design (Deep Modules & Information Hiding)
8. **Deep modules** – Favour modules with a simple interface and a complex implementation. Shallow modules (many tiny classes/methods) increase overall complexity.
9. **Hide information** – Each module should encapsulate secrets that are likely to change.
10. **Avoid temporal decomposition** – Don’t design modules based on the order of operations (first do A, then B). Instead group by required knowledge.
11. **Different layer, different abstraction** – Adjacent layers with similar abstractions are a red flag. Eliminate pass‑through methods and variables.
12. **Pull complexity downwards** – Make lower layers handle the hard parts so that higher layers have a simple interface.
13. **General‑purpose modules are deeper** – Design modules that are slightly general; the interface should support future reuse while the implementation fits current needs.
14. **Better together or better apart?** – Combine elements if they share information, are used together, overlap conceptually, or simplify the interface. Split if they are truly independent.
15. **Define errors out of existence** – Reduce exception complexity by designing APIs that eliminate exceptional cases, handle errors at low levels, or crash when appropriate.
16. **Prefer polymorphism to conditionals** (if/else, switch/case).
17. **Separate multi‑threading code** from business logic.
18. **Use dependency injection** to decouple modules.
---
## Comments & Documentation
19. **Comments are not optional** – “Self‑documenting code” is a myth. Good comments add precision and intuition that code cannot express.
20. **Comment first** – Write the comment before the implementation. It helps clarify the design (like TDD, but for documentation).
21. **Comments should describe non‑obvious things** – Document the interface (what callers need to know) and important implementation details. Avoid redundancy.
22. **If naming is hard, the design is likely wrong** – Unclear names indicate missing abstractions or poor separation of concerns.
23. **Comments belong in the code, not in commit logs** – Keep explanations where future developers will see them.
24. **Don’t comment out code** – Just remove it. Use version control for history.
25. **Use comments to explain intent, clarify logic, or warn of consequences.**
---
## Naming
26. **Choose descriptive and unambiguous names** – Make meaningful distinctions.
27. **Use pronounceable and searchable names** – Avoid single letters (except trivial loops).
28. **Replace magic numbers with named constants** – Never embed literal values.
29. **Avoid encodings** – No Hungarian notation or type prefixes.
30. **Be consistent across the codebase** – Same concept, same name.
---
## Functions / Methods
31. **Each method should do one thing and do it completely** – No partial or fragmented operations.
32. **Long methods are fine** – Provided the signature is simple, the method is cohesive, and the code is easy to read. Don’t split artificially.
33. **Use descriptive names** – A method’s name should explain its overall effect.
34. **Prefer fewer arguments** – Zero or one is best. Use objects to group related parameters.
35. **No side effects** – A function should do only what its name says.
36. **Don’t use flag arguments** – Instead split into two independent methods (e.g., `renderActive()` and `renderInactive()` instead of `render(active)`).
37. **Prefer non‑static methods** (for polymorphism and testability).
38. **Avoid logical dependency** – Don’t write methods that work correctly only because of something else in the same class (order dependencies).
---
## Code Structure & Formatting
39. **Separate concepts vertically** – Put related code in dense blocks, separate different ideas with blank lines.
40. **Declare variables close to their usage** – Not at the top of the function.
41. **Place dependent functions close together** – Caller above callee (downward direction).
42. **Keep lines short** (e.g., < 100 characters).
43. **Don’t use horizontal alignment** – It creates noisy diffs.
44. **Use indentation and white space to show association** – Group related code, separate weakly related parts.
45. **Keep configurable data at high levels** (not buried deep in code).
46. **Prevent over‑configurability** – Compute reasonable defaults automatically instead of adding configuration parameters.
---
## Objects & Data Structures
47. **Hide internal structure** – No public fields or exposed internals.
48. **Prefer data structures (simple aggregates) over hybrids** – A class should be either an object (behavior + hidden data) or a plain data structure (no behavior).
49. **Classes should be small** – One responsibility, a small number of instance variables.
50. **Base classes know nothing about their derivatives** – Prefer composition or abstraction.
51. **Better to have many explicit functions than to pass a flag/selector into one function** – That’s the “flag argument” rule again.
52. **Follow the Law of Demeter** – A class should know only its direct dependencies.
---
## Testing
53. **One logical assert per test** – Makes failures easier to interpret.
54. **Tests must be readable, fast, independent, and repeatable** – No shared state, no external dependencies.
55. **Beware: Test‑Driven Development can promote tactical programming** – If it leads to shallow modules and minimal comments, compensate with strategic thinking.
---
## Consistency & Conventions
56. **Follow standard conventions** – Language, framework, team norms.
57. **Don’t “improve” existing conventions without a strong reason** – Inconsistency increases cognitive load.
58. **Use explanatory variables** to clarify complex conditions.
59. **Encapsulate boundary conditions** – Put edge‑case processing in one place.
60. **Prefer dedicated value objects over primitive types** (e.g., `Temperature` instead of `double`).
61. **Avoid negative conditionals** (`if (!notFound)` → `if (found)`).
---
## Code Smells (Signs of Bad Design)
62. **Rigidity** – A small change causes a cascade of changes.
63. **Fragility** – A single change breaks many unrelated places.
64. **Immobility** – You cannot reuse a piece of code in another project without high risk/effort.
65. **Needless complexity** – Over‑engineering, premature optimization, over‑configurability.
66. **Needless repetition** – Duplication of logic or knowledge.
67. **Opacity** – The code is hard to read and understand.
68. **Change amplification** – A simple change requires many edits.
69. **Cognitive load** – Developers must learn too much to make a change.
70. **Unknown unknowns** – You don’t know what to change, or whether you’ve broken something.
---
## Design for Performance & Maintenance
71. **Simpler code tends to be faster** – Clean, obvious code often performs well. Optimize only after measuring.
72. **Design around the critical path** – Keep performance‑sensitive parts small and obvious.
73. **Always find the root cause** – Don’t just fix the symptom; eliminate the underlying design flaw.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment