Guest User

smell-catalog.md

a guest
Mar 6th, 2026
284
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.36 KB | None | 0 0
  1. # Architectural Smell Catalog
  2.  
  3. Common structural problems encountered during reviews, organized by detection signal and severity. Reference this when a pattern looks familiar but you need to articulate the root cause precisely.
  4.  
  5. ## Data Pipeline Smells
  6.  
  7. ### Ghost Data
  8. **Signal**: Algorithms running on placeholder, random, or toy data instead of real inputs.
  9. **Root Cause**: The mathematical/algorithmic layer was built before the ingestion layer. Common in research-to-product transitions.
  10. **Impact**: All downstream analysis is meaningless. Patterns detected are artifacts of noise.
  11. **Action**: Trace data flow from source to algorithm input. If any link in the chain uses synthetic data, flag it and prioritize real data wiring.
  12.  
  13. ### Format Thrashing
  14. **Signal**: Data converted between formats in hot paths (e.g., COO → CSR → LIL → CSR, or JSON → dict → dataclass → dict → JSON).
  15. **Root Cause**: Multiple contributors or evolution over time without format standardization.
  16. **Impact**: Performance degradation, memory pressure, subtle bugs from lossy conversions.
  17. **Action**: Pick one canonical format per layer boundary. Convert once at the boundary, never in the interior.
  18.  
  19. ### Hollow Coupling
  20. **Signal**: Cross-component relationships defined in code but populated with empty/zero data.
  21. **Root Cause**: Interface designed top-down before real data exists to populate it.
  22. **Impact**: Components appear connected but operate in isolation. Integration is illusory.
  23. **Action**: Either populate with real data (preferred) or remove the coupling and acknowledge the components are independent until real data exists.
  24.  
  25. ## Abstraction Smells
  26.  
  27. ### Premature Abstraction
  28. **Signal**: Abstract base class with exactly one concrete implementation.
  29. **Root Cause**: Designing for flexibility that hasn't been needed yet.
  30. **Impact**: Added indirection without value. Harder to navigate, no polymorphism benefit.
  31. **Action**: Collapse to concrete unless a second implementation is planned for the current sprint. Interfaces are cheap to extract later.
  32.  
  33. ### Abstraction Inversion
  34. **Signal**: High-level operations implemented by reaching through abstractions to low-level primitives (e.g., calling `.toarray()` on a sparse matrix inside a "scalable" solver).
  35. **Root Cause**: Abstraction boundary doesn't match actual computation needs.
  36. **Impact**: Defeats the purpose of the abstraction. Performance guarantees broken.
  37. **Action**: Fix the abstraction boundary so the operation can be performed at the correct level.
  38.  
  39. ### Theory-Practice Gap
  40. **Signal**: Sophisticated mathematical framework with toy/broken implementation underneath.
  41. **Root Cause**: Research-first development where theory outpaces engineering.
  42. **Impact**: Impressive on paper, useless in practice. Demo results are misleading.
  43. **Action**: Freeze theory development. Wire up real data end-to-end for ONE use case before extending the theory further.
  44.  
  45. ## Performance Smells
  46.  
  47. ### Dense Fallback
  48. **Signal**: Sparse data structures converted to dense for operations that have sparse equivalents.
  49. **Root Cause**: Developer familiarity with dense operations, or library API gaps.
  50. **Impact**: Memory scales as O(n²) instead of O(nnz). Fails silently at scale.
  51. **Action**: Audit all `.toarray()`, `.todense()`, or equivalent calls. Replace with sparse operations from the same library.
  52.  
  53. ### Blocking Pipeline
  54. **Signal**: Synchronous/blocking calls in a path that should be concurrent (e.g., `subprocess.run()` in an agent orchestrator).
  55. **Root Cause**: Prototype code that was never made async.
  56. **Impact**: Throughput bottleneck. N sequential operations take N × latency instead of max(latency).
  57. **Action**: Identify the critical path. Make it async. Blocking operations move to background workers with job queues.
  58.  
  59. ### Rebuild-Everything
  60. **Signal**: Full recomputation on every change instead of incremental updates.
  61. **Root Cause**: Incremental update logic is harder to implement correctly.
  62. **Impact**: Latency scales with total data size, not change size. Unusable for interactive workflows.
  63. **Action**: Identify the most frequent change type. Implement incremental update for that one case first. Full rebuild remains as fallback.
  64.  
  65. ## Integration Smells
  66.  
  67. ### Impedance Denial
  68. **Signal**: Two systems with fundamentally different models (sync vs async, stateless vs stateful, request-response vs event-driven) being integrated without an explicit translation layer.
  69. **Root Cause**: Assuming both sides can "just" adapt.
  70. **Impact**: One side's model gets forced on the other, creating bugs, performance issues, and maintenance burden.
  71. **Action**: Name the mismatch explicitly. Design an adapter that translates between the two models at the boundary.
  72.  
  73. ### Shared State Assumption
  74. **Signal**: Integration assumes both systems can read/write the same state without coordination.
  75. **Root Cause**: Works in prototype (single machine), breaks in production (distributed).
  76. **Impact**: Race conditions, stale reads, lost updates.
  77. **Action**: Define ownership. One system owns each piece of state. Others read through defined interfaces with explicit consistency guarantees.
  78.  
  79. ### Missing Transaction Boundaries
  80. **Signal**: Multi-step operations across systems with no atomicity, rollback, or compensation logic.
  81. **Root Cause**: "Happy path" development — it works when nothing fails.
  82. **Impact**: Partial state on failure. Data corruption. Manual recovery required.
  83. **Action**: Define where transactions begin and end. Implement compensation (saga pattern) or explicit rollback for each step.
  84.  
  85. ## Development Process Smells
  86.  
  87. ### Dogfood Avoidance
  88. **Signal**: Tool designed to analyze/process X has never been run on itself.
  89. **Root Cause**: Team focuses on external validation before internal validation.
  90. **Impact**: Obvious issues go undetected. Credibility suffers when the tool can't handle its own domain.
  91. **Action**: Run the tool on its own codebase. If it can't produce useful results on a known-structure project, it's not ready for unknown projects.
  92.  
  93. ### Demo-Driven Development
  94. **Signal**: Features built to look good in demos rather than to solve real problems. Metrics chosen for impressiveness rather than meaningfulness.
  95. **Root Cause**: Pressure to show progress.
  96. **Impact**: Working demo, broken product. Technical debt disguised as features.
  97. **Action**: Define success metrics from user needs, not demo scripts. Validate against real workloads.
  98.  
Advertisement
Add Comment
Please, Sign In to add comment