agentleFS
Boom-VittBoom-Vitt/skills-thai/skills/engineering/codebase-design/SKILL.md

codebase-design

Skill5 starsChanged 4 months agoMITView on GitHub

คำศัพท์กลางสำหรับออกแบบ deep module ใช้เมื่อ user อยากออกแบบหรือปรับปรุง interface ของ module, หาโอกาสทำ module ให้ deep ขึ้น, ตัดสินใจว่า seam ควรอยู่ตรงไหน, ทำ code ให้ test ง่ายขึ้นหรือให้ AI นำทางได้ง่ายขึ้น หรือเมื่อ skill อื่นต้องใช้คำศัพท์เรื่อง deep module

194 other projects use a version of this, 3 of them edited.

Adopted by

Most recently taken up by

Used with

Projects with it also use decision-mapping, to-questionnaire and 2 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.
  • 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

  • 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

  • AWSSkill

    wait-what

    Stop. That last message did not land: re-pitch it.

    Also in 109 projects that use this

  • +1 more from aws

The file

Files
SKILL.md

การออกแบบ Codebase

ออกแบบ deep module: พฤติกรรมจำนวนมากอยู่หลัง interface เล็ก ๆ วางไว้ที่ seam (จุดต่อที่เราสลับพฤติกรรมได้โดยไม่ต้องแก้ code ตรงนั้น) ที่สะอาด และ test ได้ผ่าน interface นั้น ใช้ภาษาและหลักการชุดนี้ทุกที่ที่มีการออกแบบหรือปรับโครงสร้าง code เป้าหมายคือ leverage ให้ฝั่ง caller, locality ให้คนดูแล code และความ testable ให้ทุกคน

Glossary

ใช้คำเหล่านี้แบบเป๊ะ ๆ — อย่าเปลี่ยนไปใช้ "component," "service," "API," หรือ "boundary" แทน ภาษาที่สม่ำเสมอคือหัวใจของเรื่องนี้

Module — อะไรก็ตามที่มี interface กับ implementation ตั้งใจให้ไม่ผูกกับขนาด: จะเป็น function, class, package หรือ slice ที่พาดผ่านหลาย tier ก็ได้ เลี่ยง: unit, component, service

Interface — ทุกอย่างที่ caller ต้องรู้เพื่อใช้ module ได้ถูกต้อง: ไม่ใช่แค่ type signature แต่รวมถึง invariant, ข้อบังคับเรื่องลำดับการเรียก, รูปแบบ error, config ที่ต้องมี และคุณสมบัติด้าน performance ด้วย เลี่ยง: API, signature (แคบเกินไป — สองคำนี้พูดถึงแค่ผิวระดับ type เท่านั้น)

Implementation — สิ่งที่อยู่ข้างใน module ตัวเนื้อ code ของมัน ต่างจาก Adapter: ของชิ้นหนึ่งอาจเป็น adapter เล็กที่มี implementation ใหญ่ (Postgres repo) หรือ adapter ใหญ่ที่มี implementation เล็ก (fake ใน memory) ก็ได้ ใช้คำว่า "adapter" เมื่อประเด็นอยู่ที่ seam นอกนั้นใช้ "implementation"

Depth — leverage ที่ตัว interface: ปริมาณพฤติกรรมที่ caller (หรือ test) ใช้งานได้ต่อหน่วยของ interface ที่ต้องเรียนรู้ module จะ deep เมื่อพฤติกรรมจำนวนมากอยู่หลัง interface เล็ก ๆ และ shallow เมื่อ interface ซับซ้อนแทบเท่า implementation

Seam (Michael Feathers) — จุดที่เราเปลี่ยนพฤติกรรมได้โดยไม่ต้องแก้ code ตรงจุดนั้น; คือตำแหน่งที่ interface ของ module อาศัยอยู่ จะวาง seam ตรงไหนเป็นการตัดสินใจออกแบบอีกเรื่องหนึ่ง แยกจากว่าอะไรจะอยู่ข้างหลังมัน เลี่ยง: boundary (ความหมายชนกับ bounded context ของ DDD)

Adapter — ของจริงชิ้นหนึ่งที่ทำตาม interface ณ seam หนึ่ง อธิบายบทบาท (เสียบเข้าช่องไหน) ไม่ใช่เนื้อใน (ข้างในมีอะไร)

Leverage — สิ่งที่ caller ได้จาก depth: ความสามารถมากขึ้นต่อหน่วย interface ที่ต้องเรียนรู้ implementation เดียวคืนทุนกระจายไปทั่ว N จุดเรียกใช้และ M test

Locality — สิ่งที่คนดูแล code ได้จาก depth: การเปลี่ยนแปลง, bug, ความรู้ และการ verify กระจุกอยู่ที่เดียวแทนที่จะกระจายไปตาม caller แก้ครั้งเดียว หายทุกที่

Deep vs shallow

Deep module = interface เล็ก + implementation เยอะ:

┌─────────────────────┐
│   Small Interface   │  ← Few methods, simple params
├─────────────────────┤
│                     │
│  Deep Implementation│  ← Complex logic hidden
│                     │
└─────────────────────┘

Shallow module = interface ใหญ่ + implementation น้อย (ควรเลี่ยง):

┌─────────────────────────────────┐
│       Large Interface           │  ← Many methods, complex params
├─────────────────────────────────┤
│  Thin Implementation            │  ← Just passes through
└─────────────────────────────────┘

เวลาออกแบบ interface ให้ถามว่า:

  • ลดจำนวน method ลงได้ไหม?
  • ทำ parameter ให้เรียบง่ายกว่านี้ได้ไหม?
  • ซ่อนความซับซ้อนไว้ข้างในได้มากกว่านี้ไหม?

หลักการ

  • Depth เป็นคุณสมบัติของ interface ไม่ใช่ของ implementation deep module ข้างในอาจประกอบจากชิ้นเล็ก ๆ ที่ mock ได้ สลับได้ — แค่ชิ้นพวกนั้นไม่ได้เป็นส่วนหนึ่งของ interface และ module มี internal seam ได้ (เป็นของ private ภายใน implementation ใช้โดย test ของตัวมันเอง) ควบคู่กับ external seam ที่ interface ของมัน
  • Deletion test ลองจินตนาการว่าลบ module ทิ้ง ถ้าความซับซ้อนหายไปด้วย แปลว่ามันเป็นแค่ pass-through ถ้าความซับซ้อนโผล่กลับมากระจายอยู่ใน caller ทั้ง N ที่ แปลว่ามันทำหน้าที่คุ้มค่าตัวอยู่จริง
  • Interface คือพื้นผิวสำหรับ test caller กับ test ข้าม seam เดียวกัน ถ้าเราอยาก test ทะลุ interface เข้าไปข้างใน แปลว่า module น่าจะมีรูปทรงที่ผิด
  • Adapter เดียวคือ seam สมมุติ สอง adapter ถึงเป็น seam จริง อย่าใส่ seam ถ้าไม่มีอะไรแปรผันข้ามมันจริง ๆ

ออกแบบเพื่อความ testable

Interface ที่ดีทำให้การ test เป็นเรื่องธรรมชาติ:

  1. รับ dependency เข้ามา อย่าสร้างเอง

    // Testable
    function processOrder(order, paymentGateway) {}
    
    // Hard to test
    function processOrder(order) {
      const gateway = new StripeGateway();
    }
  2. คืนผลลัพธ์ อย่าสร้าง side effect

    // Testable
    function calculateDiscount(cart): Discount {}
    
    // Hard to test
    function applyDiscount(cart): void {
      cart.total -= discount;
    }
  3. พื้นผิวเล็ก method น้อย = test ที่ต้องเขียนน้อย parameter น้อย = setup test ง่ายขึ้น

ความสัมพันธ์

  • Module หนึ่งตัวมี Interface เดียวเป๊ะ ๆ (พื้นผิวที่มันเปิดให้ caller และ test)
  • Depth เป็นคุณสมบัติของ Module วัดเทียบกับ Interface ของมัน
  • Seam คือตำแหน่งที่ Interface ของ Module อาศัยอยู่
  • Adapter อยู่ที่ Seam และทำตาม Interface
  • Depth ให้ Leverage แก่ caller และให้ Locality แก่คนดูแล code

Framing ที่ตัดทิ้งไปแล้ว

  • Depth แบบอัตราส่วนจำนวนบรรทัด implementation ต่อบรรทัด interface (Ousterhout): จูงใจให้ปั้น implementation ให้บวมเปล่า ๆ เราใช้ depth แบบ leverage แทน
  • "Interface" ในความหมาย keyword interface ของ TypeScript หรือ public method ของ class: แคบเกินไป — interface ในที่นี้รวมทุกข้อเท็จจริงที่ caller ต้องรู้
  • "Boundary": ความหมายชนกับ bounded context ของ DDD ให้พูดว่า seam หรือ interface

ไปให้ลึกกว่านี้

  • ทำ cluster ให้ deep ขึ้นตาม dependency ของมัน — ดู DEEPENING.md: หมวดหมู่ของ dependency, วินัยเรื่อง seam และการ test แบบ replace-don't-layer
  • สำรวจ interface ทางเลือกอื่น — ดู DESIGN-IT-TWICE.md: ปั่น sub-agent ขนานกันหลายตัวให้ออกแบบ interface หลายแบบที่ต่างกันสุดขั้ว แล้วเอามาเทียบกันด้วย depth, locality และตำแหน่งของ seam

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.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

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.