Skip to content

การเขียน Spec ที่ดี

คุณแทบไม่เคยเขียน spec จากหน้าเปล่าเลย คุณอธิบายการเปลี่ยนแปลงด้วยภาษาทั่วไป แล้ว /opsx:propose จะร่างข้อกำหนดและสถานการณ์ให้ จากนั้นคุณก็ปรับให้ดีขึ้น หน้านี้พูดถึงส่วนสุดท้ายนั้น — ความหมายของ "ดี" คืออะไร และวิธีนำ AI ไปสู่จุดนั้น

หน้านี้เป็นเอกสารประกอบสำหรับ การทบทวนการเปลี่ยนแปลง: การทบทวนคือการหาจุดอ่อนในร่างแรก การเขียนคือการรู้ว่าสิ่งที่สร้างขึ้นมาคืออะไรที่แข็งแกร่ง

Spec คือพฤติกรรม ไม่ใช่โค้ด

Spec อธิบายว่าสิ่งที่ระบบของคุณ ทำ คืออะไร ในรูปแบบที่ใครก็สามารถตรวจสอบได้ — ไม่ใช่วิธีที่มันถูกสร้างขึ้นมา มันประกอบด้วย ข้อกำหนด (requirements) (คำอธิบายพฤติกรรม) และ สถานการณ์ (scenarios) (ตัวอย่างที่ชัดเจนที่พิสูจน์ว่าพฤติกรรมนั้นเป็นจริง)

markdown
### ข้อกำหนด: หมดเวลาเซสชัน
ระบบ SHALL หมดอายุเซสชันหลังจาก 30 นาทีที่ไม่มีการใช้งาน

#### สถานการณ์: หมดเวลาจากไม่ใช้งาน
- GIVEN เซสชันที่เข้าสู่ระบบแล้ว
- WHEN ผ่านไป 30 นาทีโดยไม่มีการใช้งาน
- THEN เซสชันจะถูกยกเลิกและผู้ใช้ต้องเข้าสู่ระบบใหม่

เก็บส่วน วิธีทำงาน — คิว, ไลบรารี, โครงสร้างตาราง — ไว้ใน design.md หรือในโค้ด เมื่อพฤติกรรมและการนำไปใช้ใช้งานผสมกันอยู่ในข้อกำหนดเดียวกัน ข้อกำหนดนั้นจะไม่สามารถทดสอบได้ และเริ่มเก่าเป็นทันทีที่โค้ดมีการเปลี่ยนแปลง

สิ่งที่ทำให้ข้อกำหนดดีได้

ข้อกำหนดที่ดีคือพฤติกรรมเดียวที่อธิบายอย่างชัดเจนจนคุณสามารถส่งให้คนอื่นทดสอบได้

  • หนึ่งประโยค หนึ่ง SHALL/MUST หากข้อกำหนดมีสามประการที่ขึ้นต้นด้วย "และยัง" มันก็คือสามข้อกำหนดจริง แยกออกเป็นส่วนๆ

  • สามารถสังเกตได้ คนที่ไม่ได้เขียนโค้ดควรจะสามารถบอกได้ว่ามันเป็นจริงหรือไม่ "ระบบ SHALL แสดงแบนเนอร์ข้อผิดพลาดเมื่อการอัปโหลดเกิน 10 MB" สามารถสังเกตได้ "ระบบ SHALL จัดการการอัปโหลดไฟล์ขนาดใหญ่อย่างลื่นไหล" ไม่สามารถสังเกตได้

  • ความเข้มงวดที่เหมาะสม OpenSpec ใช้คำสำคัญจาก RFC 2119 และแต่ละคำมีความหมายต่างกัน:

    คำสำคัญความหมาย
    MUST / SHALLข้อกำหนดที่แข็งแกร่ง ไม่สามารถต่อรองได้
    SHOULDคำแนะนำที่เข้มงวด มีพื้นที่ยกเว้นหากมีเหตุผลที่สมควร
    MAYเป็นตัวเลือกจริงๆ

    ใช้ MUST/SHALL เป็นค่าเริ่มต้นโดยปริยาย ใช้ SHOULD เฉพาะเมื่อคุณหมายถึง "เว้นแต่จะมีเหตุผลที่ดีที่ไม่ควรทำ" จริงๆ

วิธีทดสอบข้อกำหนด: นักทดสอบที่เคยเห็นโค้ดเลยสามารถบอกได้ว่ามันผ่านหรือไม่? หากไม่สามารถ ทำความชัดเจนขึ้น

สิ่งที่ทำให้สถานการณ์ดีได้

สถานการณ์คือจุดที่ข้อกำหนดแสดงคุณค่าของมัน ละสถานการณ์เป็น GIVEN / WHEN / THEN ที่ชัดเจนซึ่งสามารถแปลงเป็น automated test ได้

  • ทดสอบข้อกำหนดของมันจริงๆ สถานการณ์ที่แค่อธิบายซ้ำข้อกำหนดด้วยคำอื่นไม่ได้ทดสอบอะไรเลย กำหนดให้เป็นสถานการณ์เฉพาะพร้อมผลลัพธ์เฉพาะ
  • ครอบคลุมกรณีที่สำคัญ ไม่ใช่แค่เส้นทางปกติ การเข้าสู่ระบบที่ถูกต้องเป็นเรื่องง่าย การป้อนข้อมูลว่าง, โทเคนหมดอายุ, การคลิกครั้งที่สอง, สิ่งที่ผิดพลาด — นั่นคือจุดที่บั๊กอยู่ และสถานการณ์นั้นมีค่าที่สุดที่นั่น
  • ตั้งชื่อกรณีไว้ในหัวข้อ "สถานการณ์: ปฏิเสธโทเคนหมดอายุ" บอกให้ผู้ทบทวนเห็นว่ามีอะไรครอบคลุมได้ทันที; "สถานการณ์: ทดสอบ 2" ไม่บอกอะไรเลย

นิสัยที่เป็นประโยชน์: ก่อนอนุมัติ ถาม กรณีไหนที่ฉันจะรู้สึกไม่ดีหากมันเสียหาย? — และตรวจสอบให้แน่ใจว่าสถานการณ์มีชื่อเรียกกรณีนั้น

เลือกประเภท delta ที่เหมาะสม

การเปลี่ยนแปลงอธิบายการแก้ไขกับ spec โดยใช้สามประเภทส่วน ใช้ประเภทที่ถูกต้องจะทำให้ spec ที่เก็บไว้ในอาร์ไคฟ์ถูกต้องตรงกับความเป็นจริง:

  • ## ADDED Requirements — พฤติกรรมใหม่ที่ไม่มีอยู่มาก่อน
  • ## MODIFIED Requirements — พฤติกรรมที่มีอยู่ก่อนและกำลังมีการเปลี่ยนแปลง ใส่เวอร์ชันใหม่ทั้งหมด; โน้ตสั้นๆ ว่ามีอะไรเปลี่ยนจะช่วยให้ผู้ทบทวนเข้าใจง่ายขึ้น
  • ## REMOVED Requirements — พฤติกรรมที่กำลังจะลบออก พร้อมบรรทัดที่อธิบายเหตุผล

เมื่อเก็บลงอาร์ไคฟ์ ส่วน ADDED จะถูกเพิ่มต่อท้าย spec หลัก ส่วน MODIFIED จะแทนที่เวอร์ชันเก่า และส่วน REMOVED จะถูกลบออก หากคุณทำเครื่องหมายว่าการเปลี่ยนแปลงจริงเป็น ADDED คุณจะได้ข้อกำหนดที่ขัดแย้งกันสองชุด; หากคุณอธิบายพฤติกรรมใหม่เป็น MODIFIED จะไม่มีอะไรให้แทนที่ หากไม่แน่ใจ เปิด spec ปัจจุบันและดูว่ามีข้อกำหนดนั้นอยู่แล้วหรือไม่

ขนาดการเปลี่ยนแปลงที่เหมาะสม

ข้อผิดพลาดที่พบบ่อยที่สุดของผู้เขียนไม่ได้เป็นข้อกำหนดที่เขียนคำไม่ดี — นั่นคือการเปลี่ยนแปลงที่พยายามจะเป็นสามการเปลี่ยนแปลง

การเปลี่ยนแปลงที่ดีมีเจตนาเดียวที่คุณสามารถพูดออกมาในหนึ่งประโยค "เพิ่มสลับโหมดมืด" "จำกัดอัตราการเข้าถึงจุดสิ้นสุดการเข้าสู่ระบบ" "ย้ายเซสชันออกจากการใช้คุกกี้" หากการอธิบายการเปลี่ยนแปลงต้องการคำว่า "และยัง" หลายครั้ง นั่นเป็นสัญญาณว่าควรแยกออกเป็นส่วนๆ

สัญญาณว่าการเปลี่ยนแปลงมีขนาดใหญ่เกินไป:

  • ขอบเขตของข้อเสนอดูเหมือนรายการคุณสมบัติที่ไม่มีความเกี่ยวข้องกัน
  • การทบทวนมันจะต้องใช้เวลาเต็มบ่าย ดังนั้นไม่มีใครจะทำ
  • สองคนไม่สามารถทำงานกับมันได้โดยไม่ชนกัน
  • ครึ่งหนึ่งของงานสามารถส่งออกได้ด้วยตัวเอง

การเปลี่ยนแปลงที่เล็กกว่าเป็นเรื่องง่ายที่จะทบทวน ง่ายที่จะสร้างในหนึ่งเซสชันที่โฟกัส และง่ายที่จะเข้าใจหกเดือนต่อมาเมื่ออาร์ไคฟ์เป็นสิ่งที่เหลืออยู่เท่านั้น คุณสามารถรันหลายการเปลี่ยนแปลงพร้อมกันได้เสมอ — ดู การแก้ไขและทำซ้ำ และ เวิร์กโฟลว์

อีกด้านหนึ่งก็เกิดขึ้น: การแก้ไขพิมพ์ผิดหนึ่งบรรทัดไม่จำเป็นต้องมีสามข้อกำหนดและเอกสารออกแบบ กำหนดความพิธีตามความเสี่ยง

วิธีนำ AI ไปสู่ร่างแรกที่ดี

เนื่องจาก /opsx:propose ทำร่างแรก คุณภาพของสิ่งที่คุณได้รับกลับมาตามตามคุณภาพของสิ่งที่คุณให้กับมัน คุณไม่จำเป็นต้องเขียนข้อกำหนดด้วยตัวเอง — คุณต้องเป้าหมาย AI อย่างถูกต้อง:

  • ระบุเจตนาและขอบเขต "เพิ่มสลับโหมดมืดที่ใช้การตั้งค่าของระบบปฏิบัติการเมื่อโหลดครั้งแรก — อย่าแก้ไข API ธีมที่มีอยู่เดิม" ส่วนที่ไม่อยู่ในขอบเขตมีความสำคัญเท่ากับส่วนที่อยู่ในขอบเขต
  • ระบุกรณีที่คุณสนใจ "ตรวจสอบให้แน่ใจว่ามีสถานการณ์สำหรับผู้ใช้ที่เคยเลือกธีมด้วยตนเอง" AI จะครอบคลุมสิ่งที่คุณชี้ให้เห็น
  • จากนั้นแก้ไข มันเป็น Markdown ธรรมดา ปรับ SHALL ที่ไม่ชัดเจนให้เข้มงวดขึ้น, ลบสถานการณ์ที่ไม่ได้ทดสอบอะไร, เพิ่มกรณีที่มันพลาด — หรือขอให้ AI ทำ: "ข้อกำหนดเกี่ยวกับหมดเวลาอย่างไม่ชัดเจน กำหนดให้เป็น 30 นาที"

ร่าง, ชัดเจน, ทำซ้ำ หลายรอบของกระบวนการนี้จะสร้าง spec ที่คุณเชื่อถือได้ ซึ่งคือจุดประสงค์ทั้งหมด

รายการตรวจสอบด่วน

  • [ ] ข้อกำหนดแต่ละข้อเป็นพฤติกรรมที่สามารถสังเกตได้หนึ่งข้อพร้อมกับ SHALL/MUST
  • [ ] ไม่มีรายละเอียดการนำไปใช้ใช้งานที่ฝังอยู่ในข้อกำหนด
  • [ ] ข้อกำหนดทุกข้อมีอย่างน้อยหนึ่งสถานการณ์ที่ทดสอบมันจริงๆ
  • [ ] กรณีขอบและข้อผิดพลาดที่สำคัญมีสถานการณ์ ไม่ใช่แค่เส้นทางปกติ
  • [ ] Delta ใช้ ADDED / MODIFIED / REMOVED อย่างถูกต้องเทียบกับ spec ปัจจุบัน
  • [ ] การเปลี่ยนแปลงทั้งหมดมีเจตนาเดียวที่คุณสามารถพูดออกมาในหนึ่งประโยค

ที่ต่อไปนี้