"Use when a Typer/Click CLI module exceeds 300 LOC with mixed concerns. Extract business logic into a testable service layer."
Install
npx skillscat add shimo4228/claude-code-learned-skills/service-layer-extraction Install via the SkillsCat registry.
This skill extracts business logic from Typer/Click CLI modules into a separate service layer, replacing CLI-specific types and side effects with plain Python equivalents like ValueError, strings, and standard logging. It addresses CLI files that have grown beyond roughly 300 lines and mixed concerns, making the logic testable without CLI runners and reusable from other interfaces.
Service Layer Extraction from CLI
Extracted: 2026-02-11
Context: Refactoring a Typer/Click CLI module to separate business logic into a testable service layer
Problem
CLI modules (e.g., main.py with Typer) accumulate business logic alongside CLI concerns. This makes the logic untestable without CLI runners and blocks reuse from other interfaces (Web UI, SDK).
Solution
Extract business logic into service.py with these translation rules:
| CLI Layer (main.py) | Service Layer (service.py) |
|---|---|
typer.BadParameter |
ValueError |
CLI enums (OutputFormat) |
Plain strings ("tsv", "off") |
console.print() (Rich) |
logger.info() (logging) |
Private names (_collect_files) |
Public names (collect_files) |
Conversion at the boundary (main.py):
# Catch service ValueError, convert to CLI output
try:
files = collect_files(path)
except ValueError as e:
console.print(f"[red]Error:[/red] {e}")
raise typer.Exit(code=1) from e
# Pass enum .value to service layer
result = process_file(quality=quality.value, fmt=fmt.value)When to Use
- CLI module exceeds ~300 LOC with mixed concerns
- Business logic needs testing without CliRunner
- Planning a second interface (Web UI, API, SDK)