agentleFS
eyeixeyeix/skills/codebase-design/SKILL.md

codebase-design

Skill1 starsChanged 30 days agoMITView on GitHub

Shared vocabulary for designing deep modules. Use when the user wants to design or improve a module's interface, find deepening opportunities, decide where a seam goes, make code more testable or AI-navigable, or when another skill needs the deep-module vocabulary.

194 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use setup-ts-deep-modules, decision-mapping and 8 more.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • liufeng1976Skill

    setup-ts-deep-modules

    Wire dependency-cruiser into a TypeScript repo so each package is a deep module — implementation hidden in subfolders, reachable only through its entry-point files. User-invoked.

    Also in 43 projects that use this

  • FabienDehopreSkill

    decision-mapping

    Turn a loose idea into a sequenced map of investigation tickets, then drive them to resolution one at a time.

    Also in 8 projects that use this

  • RoentekSkill

    loop-me

    Grill me about specs for the workflows I want to build, within this workspace.

    Also in 55 projects that use this

  • LesaniSkill

    writing-beats

    Shape an article as a journey of beats, choose-your-own-adventure style. The user picks a starting beat from the raw material, you write only that beat, then offer options for where to pivot next, beat by beat, until the article reaches a natural end. Use when the user has raw material and wants to assemble it as a narrative rather than an argument.

    Also in 58 projects that use this

  • AWSSkill

    to-questionnaire

    Turn a decision you can't fully answer into a questionnaire for someone else to fill in.

    Also in 90 projects that use this

  • LesaniSkill

    writing-shape

    Take a markdown file of raw material and shape it into an article through a conversational session — drafting candidate openings, growing the piece paragraph by paragraph, arguing about format (lists, tables, callouts, quotes) at each step. Use when the user has a pile of notes, fragments, or a rough draft and wants help turning it into something publishable.

    Also in 58 projects that use this

  • +1 more from Lesani

The file

Files
SKILL.md

代码库设计

设计深模块(deep module):小接口后面藏大量行为,放在干净的接缝上,通过接口可测。任何设计或重构代码的地方都用这套语言与原则。目标:给调用方杠杆,给维护者局部性,给所有人可测性。

词汇

精确用词:不替换成"组件"、"服务"、"API"、"边界"。语言一致就是全部意义。

模块(module):有接口和实现的东西。刻意不区分尺度:函数、类、包、跨层切片。避免:unit、component、service。

接口(interface):调用方要正确使用模块必须知道的一切:类型签名,以及不变量、顺序约束、错误模式、必需配置、性能特征。避免:API、签名(太窄,只指类型层面)。

实现(implementation):模块内部的东西,代码本体。区别于适配器(adapter):一个东西可以是小适配器加大实现(Postgres 仓储),也可以是大适配器加小实现(内存 fake)。接缝是话题时用"适配器",否则用"实现"。

深度(depth):接口处的杠杆。调用方(或测试)每学一单位接口,能驱动的行为量。深模块:大量行为藏在小接口后;浅模块:接口几乎和实现一样复杂。

接缝(seam,Michael Feathers):不改这个地方的代码就能改变行为的位置;模块的接口所在的地点。接缝放哪本身是一个设计决策,独立于它后面放什么。避免:boundary(与 DDD 的限界上下文撞义)。

适配器(adapter):在接缝上满足一个接口的具体之物。描述角色(填哪个槽),不描述内容。

杠杆(leverage):深度给调用方的东西。每单位接口学到的东西换回更多能力。一份实现,在 N 个调用点、M 个测试上回本。

局部性(locality):深度给维护者的东西。变更、bug、知识、验证集中在一处,而不是摊到各调用方。修一次,处处修好。

深与浅

深模块 = 小接口 + 大量实现:

┌─────────────────────┐
│     小接口           │  ← 方法少,参数简单
├─────────────────────┤
│                     │
│    深实现            │  ← 复杂逻辑被藏起
│                     │
└─────────────────────┘

浅模块 = 大接口 + 薄实现(避免):

┌─────────────────────────────────┐
│        大接口                     │  ← 方法多,参数复杂
├─────────────────────────────────┤
│   薄实现                          │  ← 只是转发
└─────────────────────────────────┘

设计接口时问:

  • 方法数能不能减?
  • 参数能不能简化?
  • 里面还能多藏什么复杂度?

原则

  • 深度是接口的属性,不是实现的。深模块内部可以由小的、可 mock、可替换的部件组成;它们只是不属于接口。模块可以有内部接缝(实现私有,自己的测试用)和接口处的外部接缝;
  • **删除测试。**想象删掉这个模块:复杂度消失,它是转发层;复杂度在 N 个调用方重现,它在挣自己的饭钱;
  • 接口就是测试面。调用方与测试穿过同一个接缝。想测到接口以内,模块形状多半错了;
  • **一个适配器 = 假想接缝,两个适配器 = 真接缝。**没有东西真的在接缝两侧变化,就不引入接缝。

为可测性设计

好接口让测试自然:

  1. 接受依赖,不创造依赖。

    // 可测
    function processOrder(order, paymentGateway) {}
    
    // 难测
    function processOrder(order) {
      const gateway = new StripeGateway();
    }
  2. 返回结果,不制造副作用。

    // 可测
    function calculateDiscount(cart): Discount {}
    
    // 难测
    function applyDiscount(cart): void {
      cart.total -= discount;
    }
  3. **表面积小。**方法少 = 要的测试少。参数少 = 测试准备简单。

关系

  • 一个模块恰有一个接口(呈现给调用方与测试的面);
  • 深度是模块的属性,对着它的接口度量;
  • 接缝是模块的接口所在之地;
  • 适配器坐在接缝上,满足接口;
  • 深度给调用方产出杠杆,给维护者产出局部性。

被拒绝的表述

  • 深度 = 实现行数比接口行数(Ousterhout):奖励给实现注水。我们用"深度即杠杆";
  • "接口" = TypeScript 的 interface 关键字或类的公开方法:太窄,这里的接口包括调用方必须知道的一切;
  • "边界":与 DDD 限界上下文撞义。说接缝或接口。

再深一层

  • 带着依赖深化一簇模块,见 DEEPENING.md:依赖分类、接缝纪律、替换而非叠加的测试;
  • 探索备选接口,见 DESIGN-IT-TWICE.md:并行子代理用几种截然不同的方式设计接口,再按深度、局部性、接缝位置比较。

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

Reviews can't be read right now.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.