docs: add codebase metrics and impact analysis to DRY refactor plan
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
5b08591a55
commit
dd19281f4f
@ -4,6 +4,37 @@ Status: Planned
|
||||
|
||||
Codebase analysis identifying repeated patterns and consolidation opportunities. Ordered by impact.
|
||||
|
||||
## Codebase snapshot
|
||||
|
||||
| Category | Files | Lines |
|
||||
|----------|------:|------:|
|
||||
| Elixir source (.ex) | 96 | 18,153 |
|
||||
| HEEx templates (.heex) | 15 | 2,384 |
|
||||
| Tests (.exs) | 45 | 6,735 |
|
||||
| JavaScript (.js) | 1 | 351 |
|
||||
| CSS (.css) | 5 | 1,218 |
|
||||
| Config + migrations | 17 | 653 |
|
||||
| **Total** | **179** | **29,494** |
|
||||
|
||||
Code density: 81.1% (22,108 code / 4,355 blank / 809 comment).
|
||||
|
||||
### Concentration
|
||||
|
||||
- `shop_components.ex` alone is 4,424 lines — 24% of all Elixir source
|
||||
- Web layer (9,576) slightly larger than contexts (7,950)
|
||||
- Top 3 files (`shop_components.ex`, `index.html.heex`, `preview_data.ex`) account for 6,650 lines — 36% of source
|
||||
|
||||
### What matters
|
||||
|
||||
Every LOC is maintenance cost, attack surface, and cognitive load. The goal isn't minimising LOC for its own sake — a 50-line module that does one thing clearly beats a 20-line clever abstraction. But 224 lines of copy-pasted template wrapper is the kind of LOC worth eliminating.
|
||||
|
||||
Contexts are well-sized (200-550 lines each, good boundaries). LiveViews average ~157 lines — thin wrappers over contexts, which is right. The problems are in the shared component layer and the repeated boilerplate.
|
||||
|
||||
### Worth questioning
|
||||
|
||||
- `preview_data.ex` (1,049 lines) and `mockups/generator.ex` (522 lines) total 1,570 lines of hard-coded demo content. Should this be seed data or fixtures rather than compiled code? Could be moved behind `Mix.env()` guards or into a mix task to reduce the production runtime footprint by ~8%.
|
||||
- Test-to-source ratio is 0.37:1 (lines). Reasonable for a template-heavy app, but new features should aim to keep this steady or improve it.
|
||||
|
||||
## High priority
|
||||
|
||||
### 1. Extract `<.shop_layout>` wrapper component
|
||||
@ -42,6 +73,8 @@ Codebase analysis identifying repeated patterns and consolidation opportunities.
|
||||
</.shop_layout>
|
||||
```
|
||||
|
||||
**Net saving:** ~195 lines removed (224 duplicated minus ~29 for the new component definition).
|
||||
|
||||
**Files:** `shop_components.ex` (new component), all 8 page templates, `collection.ex` inline render.
|
||||
|
||||
**Complexity:** Medium. The error template has slight variations (no `phx-hook`, different class). Handle with an optional attr or keep error as a special case.
|
||||
@ -86,6 +119,8 @@ def mount(_params, _session, socket) do
|
||||
end
|
||||
```
|
||||
|
||||
**Net saving:** ~55 lines removed (75 duplicated minus ~20 for the new hook module). Also removes 7 sets of aliases (Settings, Media, CSSCache, CSSGenerator) from LiveViews.
|
||||
|
||||
**Files:** New `theme_hook.ex`, `router.ex` (add to on_mount), all 7 shop LiveViews (remove boilerplate).
|
||||
|
||||
**Complexity:** Low. Follows established `CartHook` pattern exactly.
|
||||
@ -96,6 +131,8 @@ end
|
||||
|
||||
**Fix:** Extract a private `common_preview_assigns/1` function. Each clause merges page-specific attrs on top.
|
||||
|
||||
**Net saving:** ~65 lines removed (80 duplicated minus ~15 for the helper function).
|
||||
|
||||
**Files:** `lib/simpleshop_theme_web/live/theme_live/index.ex`
|
||||
|
||||
**Complexity:** Low. Pure refactor within one file.
|
||||
@ -115,6 +152,8 @@ end
|
||||
|
||||
Keep `ShopComponents` as a facade that imports all sub-modules for backward compatibility.
|
||||
|
||||
**Net saving:** ~0 lines (redistribution, not reduction). Value is in navigability, compile speed, and cognitive load — no single file over ~1,000 lines.
|
||||
|
||||
**Files:** `shop_components.ex` split into 5 new files.
|
||||
|
||||
**Complexity:** Medium. Mechanical but touches many imports. Need to update `page_templates.ex` and any direct references.
|
||||
@ -125,6 +164,8 @@ Keep `ShopComponents` as a facade that imports all sub-modules for backward comp
|
||||
|
||||
**Fix:** Extract a `Cart.build_state/1` function that returns `%{items: hydrated, count: n, subtotal: formatted}`. Both CartHook and CheckoutController use it.
|
||||
|
||||
**Net saving:** ~15 lines removed. Main value is correctness — single source of truth for cart state calculation.
|
||||
|
||||
**Files:** `cart.ex`, `cart_hook.ex`, `checkout_controller.ex`
|
||||
|
||||
**Complexity:** Low.
|
||||
@ -135,6 +176,8 @@ Keep `ShopComponents` as a facade that imports all sub-modules for backward comp
|
||||
|
||||
**Fix:** Add `Vault.encrypt!/1` that raises on failure (for changeset use) and keep `Vault.encrypt/1` for tuple returns. Or create an `Ecto.Type` for encrypted fields.
|
||||
|
||||
**Net saving:** ~10 lines removed. Main value is consistent error handling across all encryption callsites.
|
||||
|
||||
**Files:** `vault.ex`, `settings.ex`, `provider_connection.ex`
|
||||
|
||||
**Complexity:** Low-medium.
|
||||
@ -170,6 +213,22 @@ Keep `ShopComponents` as a facade that imports all sub-modules for backward comp
|
||||
- **Context boundaries** — Products, Orders, Settings, Media are well-separated.
|
||||
- **Page LiveView renders** — now all use `{assigns}` spread (just refactored).
|
||||
|
||||
## Impact summary
|
||||
|
||||
| # | Item | Lines saved | Risk | Primary value |
|
||||
|---|------|------------:|------|---------------|
|
||||
| 2 | ThemeHook | ~55 | Low | Eliminates mount duplication + alias clutter |
|
||||
| 1 | shop_layout | ~195 | Medium | Biggest raw line reduction |
|
||||
| 3 | Preview assigns | ~65 | Low | Single-file cleanup |
|
||||
| 5 | Cart state builder | ~15 | Low | Correctness (single source of truth) |
|
||||
| 4 | Split shop_components | ~0 | Medium | Navigability, compile speed |
|
||||
| 6 | Encryption | ~10 | Low | Consistent error handling |
|
||||
| 7 | Settings lookups | ~10 | Trivial | Minor cleanup |
|
||||
| 8 | Secrets loading | ~5 | Trivial | Future-proofing |
|
||||
| | **Total** | **~355** | | **~1.7% of total source** |
|
||||
|
||||
Combined with the structural improvement of splitting `shop_components.ex` (4,424 lines into 5 modules of ~900 lines each), the largest file drops from 24% of all source to under 5%.
|
||||
|
||||
## Suggested order
|
||||
|
||||
1. ThemeHook (item 2) — lowest risk, biggest clarity win
|
||||
|
||||
Loading…
Reference in New Issue
Block a user