api-design
Use when designing or reviewing a public API, exported function signature, module boundary, exported type/interface, or any contract other code depends on
Use when introducing, reviewing, or renaming a top-level type, table, or domain concept; or choosing where state lives (in-memory vs persistent)
$ npx -y skills add oribarilan/97 --skill domain-modeling --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/domain-modelingContext preview
The summary Claude sees to decide when to auto-load this skill.
Use when introducing, reviewing, or renaming a top-level type, table, or domain concept; or choosing where state lives (in-memory vs persistent)
name: domain-modeling description: Use when introducing, reviewing, or renaming a top-level type, table, or domain concept; or choosing where state lives (in-memory vs persistent)
The names and shapes you give the concepts in your code *are* the design. **When you introduce a new domain concept, name it for what it means in the user's world, give it a real type, and decide where its state lives — before you write the methods that act on it.**
This is a **rigid** skill. Run the decisions in order. If you can't satisfy one, stop and tell the user what's blocking you. When the concept is exposed across a module/package/service boundary, also invoke `api-design` (overlap on type design and value-vs-identity).
Invoke when you're about to:
If you're not sure whether a change introduces a *new domain concept* (vs. a local helper), **invoke anyway** — the decisions are cheap, mismodeled domain concepts are not.
The typed-domain principles below (`Wlaschin/InvalidStatesUnrepresentable`, `Wlaschin/SmartConstructors`, `Wlaschin/TypesForEffects`, `Fowler/PrimitiveObsession`) fire hardest in languages with sum types and pattern matching (TypeScript, Rust, F#, Haskell, Scala, Kotlin, modern C#). They degrade gracefully in dynamic languages (Python, JavaScript, Ruby) where the agent reaches for frozen dataclasses, `pydantic`, `attrs`, `TypedDict`, or NewType where they help. **Do not be type-system-evangelical** — in a small Python script, a `dict` is the right answer.
Run every decision in order. Do not write the type's methods until decision 5 is settled.
1. **Name the concept the way the domain expert names it.** If the user says "trader", "portfolio", "booking", "policy" — that's the type name. Avoid invented programmer terms (`UserDataObject`, `BookingManager`, `PolicyHelper`) when a domain term exists. If the domain expert wouldn't recognize the name, you're inventing a secret vocabulary the next programmer will have to decode. *(North, 97/11.)* 2. **Make implicit relationships explicit as types or methods.** If the rule is "some traders cannot view some portfolios," prefer `trader.canView(portfolio)` over `portfolioIdsByTraderId.get(...)containsKey(...)`. Replace primitive obsession (raw ints, strings, nested maps standing in for relationships) with named types and operations. *(North, 97/11.)* 3. **Treat this as design, not typing.** The shape you pick now will outlive most of the code that uses it. Sketch two or three alternatives before committing. Validate the chosen shape against at least two realistic scenarios — if it forces awkward workarounds in either, it's the wrong shape. Code is design; design needs validation. *(Brush, 97/12.)* 4. **Default to immutable value types and pure transformations.** Unless the concept *intrinsically* has identity and lifetime (a `User`, a `Booking`), prefer value types you construct fresh rather than mutate. Operations that produce new domain objects from old ones are easier to test, reason about, and reuse than methods that secretly mutate shared state. *(Garson, 97/2.)* 5. **Decide where the state lives — before sketching methods.** Ask: Is this data **large** (won't fit in RAM), **persistent** (survives process restart), or **interconnected** (entities reference each other with consistency rules)? If yes to any two: it belongs in a database (embedded like SQLite is fine for small needs). If no to all three: an in-memory structure is fine. Hand-rolled `Map<int, Map<int, int>>` for what is really a relational dataset is a cost you pay forever. *(Spinellis, 97/48.)* 6. **Consider whether this concept needs its own little language.** When users keep describing the concept with a constrained vocabulary — rules, validations, query expressions, configuration — and several places in the code re-encode that vocabulary by hand, you are recreating a DSL the slow way. An internal DSL (a fluent API in the host language) lets domain experts read and sometimes write the rules directly. Don't *start* here, but recognize the smell. *(Hunger, 97/23.)* 7. **Place the concept in one canonical location.** One file, one module, one table — not three competing definitions. If you find a parallel concept already exists under a different name, stop and unify before adding a third. The next programmer should be able to find this concept by searching for the domain term and finding exactly one definition.
These thoughts mean STOP — restart the decisions:
| Thought | Reality | |---|---| | "I'll use a `Map<int, Map<int, ...>>` — it's just
Agent skills distilled from the hard-won lessons of world-renowned programmers, in the spirit of "97 Things Every Programmer Should Know"
Repo: oribarilan/97
Use when designing or reviewing a public API, exported function signature, module boundary, exported type/interface, or any contract other code depends on
Use when considering, evaluating, or performing a refactor, restructure, cross-file rename, or cleanup
Use when writing, reviewing, or changing build scripts, CI workflows, deploy pipelines, repo setup, or evaluating a new tool/dependency
Use when writing or reviewing functions, classes, naming, or non-trivial logic (≥3 lines)
Use when writing or reviewing error handling, floating-point math, concurrent code, remote calls, singletons/globals, hot-path data structures, or high-volume…
Use when writing or reviewing request handlers, RPCs, or background jobs for production; adding tracing, metrics, or structured-log calls; or making…