ข้าม​ไป​ยัง​เนื้อหา

Lois Lane Planning

สัญญา​ลูกค้า​เกิน​จริง แล้ว​หวัง​ให้​นัก​พัฒนา “กลาย​เป็น​ซูเปอร์​แมน” มากอบ​กู้

Lois Lane Planning เป็น antipattern ระดับ​องค์กร​ที่​ฝ่าย​ขาย​หรือ​ฝ่าย​บริหาร รับปาก​ส่ง​มอบ feature หรือ​กำหนด​เวลา​ที่​เกิน​จริง ทั้ง​ที่​รู้​อยู่​แล้ว​ว่า​ทีม​พัฒนา​ยัง​ไม่​พร้อม โดย​ตั้ง​อยู่​บน​ความ​เชื่อ (มัก​ไม่​ได้​พูด​ออก​มาตรงๆ) ว่า​ทีม​วิศวกร​จะ “ลุก​ขึ้น​มากอบ​กู้​สถานการณ์” ได้​เสมอ ไม่​ว่า​คำ​สัญญา​จะ​ไร้​เหตุผล​แค่​ไหน

ชื่อ antipattern นี้​ล้อ​มา​จาก​ความ​สัมพันธ์​ของ Superman กับ Lois Lane ใน DC Comics: Lois มัก​โยน​ตัวเอง​เข้า​สถานการณ์​อันตราย​เกิน​ตัว​ซ้ำ​แล้ว​ซ้ำ​เล่า เพราะ​เธอ​มั่นใจ​ลึกๆ ว่า Superman จะ​มา​ช่วย​ทัน​เวลา​เสมอ ใน​องค์กร ฝ่าย​ขาย​ก็​ทำ​แบบ​เดียวกัน — เซ็น​สัญญา​กับ​ลูกค้า​โดย​อ้างอิง​จาก roadmap ใน​ฝัน ไม่ใช่​สถานะ​จริง​ของ code แล้ว​วางใจ​ว่า​นัก​พัฒนา​จะ​เป็น “ซูเปอร์​แมน” ที่​เนรมิต feature ให้​ทัน​เส้นตาย​เสมอ

เมื่อ​วัน​ส่ง​มอบ​ใกล้​เข้า​มา​และ​ระบบ​ยัง​รองรับ​คำ​สัญญา​ไม่​ได้ ผู้​บริหาร​จึง​เรียก​ทีม​พัฒนา​มา​ช่วย “ดับ​ไฟ” ทีม​ต้อง​ทุ่มเท​เกิน​ขีด​จำกัด (heroic effort) เพื่อ​รักษา​ชื่อเสียง​องค์กร​และ​ปิด​ดีล​ที่​ขาย​ไป​แล้ว งาน​ที่​สำคัญ​กว่า​ใน​ระยะ​ยาว — การ​จ่าย​หนี้​ทาง​เทคนิค การ refactor การ​วาง​สถาปัตยกรรม​ที่​ยั่งยืน — มัก​ตก​รถ​ไป​เรื่อยๆ เพราะ​ไฟ​ฉุกเฉิน​จาก​ฝ่าย​ขาย​มา​ก่อน​เสมอ

  • ปิด​ดีล​ได้​เร็ว​กว่า — การ​พูด​ว่า “ได้​ครับ ทำได้​ทัน​กำหนด” ปิด​การ​ขาย​ได้​ทันที ใน​ขณะ​ที่​การ​พูด​ความ​จริง​ว่า “ต้อง​ใช้​เวลา​อีก 2 เดือน” อาจ​เสีย​ลูกค้า​ให้​คู่แข่ง​ไป​เลย
  • ใน​อดีต​มัน​เคย​ได้​ผล — ถ้า​ทีม​เคย “กู้​สถานการณ์” สำเร็จ​มา​แล้ว​สัก​ครั้ง​สอง​ครั้ง ฝ่าย​ขาย​ก็​ยิ่ง​มั่นใจ​ว่า​ครั้ง​ต่อ​ไป​ก็​จะ​รอด​เหมือน​เดิม ทั้ง​ที่​แต่ละ​ครั้ง​อาจ​เป็น​เพียง​ความ​บังเอิญ​หรือ​การ​เสียสละ​ที่​ไม่​ยั่งยืน​ของ​ทีม
  • ไม่มี​ใคร​อยาก​เป็น​คน​พูด​ว่า “ไม่​ได้” — ผู้​บริหาร​ระดับ​กลาง​กลัว​ว่าการ​ปฏิเสธ​คำ​สัญญา​จะ​ทำให้​ตัวเอง​ดู​ไม่​เก่ง​หรือ​ไม่​ทะเยอทะยาน​พอ จึง​เลือก​ผลัก​ภาระ​ไป​ให้​ทีม​พัฒนา​รับผิดชอบ​แทน
  • วัฒนธรรม​ฮีโร่​ให้​รางวัล​ผิด​จุด — องค์กร​มัก​ยกย่อง​คน​ที่ “เข้า​กะ​ดึก​กู้​ระบบ” ต่อ​หน้าที่​ประชุม มากกว่า​คน​ที่​วางแผน​ดี​จน​ไม่มี​วิกฤต​ให้​ต้อง​กู้​ตั้งแต่​แรก ทำให้​พฤติกรรม​สัญญา​เกิน​จริง​ถูก​เสริม​แรง​ซ้ำ (reinforced) แทนที่​จะ​ถูก​แก้​ที่​ต้นเหตุ
  • ระยะ​สั้น​ดูเหมือน​ไม่มี​ต้นทุน — ผลกระทบ​ของ​การ​ทุ่มเท​เกิน​ขีด​จำกัด เช่น หนี้​ทาง​เทคนิค คน​ลาออก ไม่​ปรากฏ​ทันที​ใน​ไตรมาส​ที่​ปิด​ดีล​ได้ จึง​ดูเหมือน​เป็นการ​ตัดสิน​ใจ​ที่ “ฟรี” ใน​สายตา​คน​ที่​วัดผล​ราย​ไตรมาส
  • วงจร​อุบาทว์​ที่​ยิ่ง​เล่น​ยิ่ง​เสี่ยง — ทุก​ครั้ง​ที่​ทีม​กอบ​กู้​สถานการณ์​สำเร็จ ฝ่าย​ขาย/ผู้​บริหาร​ยิ่ง​มั่นใจ​ว่า​ครั้ง​หน้า​ก็​จะ​เสี่ยง​ได้​อีก จึง​สัญญา​โหด​ขึ้น​เรื่อยๆ วน​ซ้ำ​แบบ Death March ที่​ไม่มี​จุดจบ เพราะ​พฤติกรรม​ที่​ถูก​ให้​รางวัล​จะ​เกิด​ซ้ำ​เสมอ
  • หนี้​ทาง​เทคนิค​พอกพูน​แบบ​ซ่อนเร้น — งาน​ที่​รีบ​ทำ​ใต้​แรง​กดดัน​มัก​ข้าม​การ​ทดสอบ ข้าม​การ​รีวิว code และ​ใช้​ทาง​ลัด​ที่​ไม่มี​ใคร​มี​เวลา​ไป​แก้​ทีหลัง เพราะ​ไฟ​ฉุกเฉิน​ลูก​ถัด​ไป​มา​ถึง​ก่อน​ที่​จะ​ได้​ย้อน​กลับ​ไป​เก็บกวาด
  • งาน​สำคัญ​ระยะ​ยาว​ถูก​เบียด​ตก​ราง — เวลา​และ​พลังงาน​ของ​ทีม​ที่​ควร​ใช้​กับ​สถาปัตยกรรม การ​จ่าย​หนี้​เทคนิค หรือ feature ที่​วางแผน​ไว้ ถูก​ดึง​ไป​อุด​รู​รั่ว​จาก​คำ​สัญญา​ที่​คน​อื่น​ให้​ไว้​แทน project หลัก​จึง​ล่าช้า​ซ้ำซ้อน
  • คน​เก่ง​เหนื่อย​ล้า​และ​ลาออก — นัก​พัฒนา​ที่​ถูก​เรียก​ให้​เป็น “ฮีโร่” ซ้ำๆ จะ​หมด​ไฟ​เร็ว​กว่า​คน​อื่น และ​มัก​เป็น​คน​ที่​มี​ตัว​เลือก​ใน​ตลาด​แรงงาน​มาก​ที่สุด องค์กร​จึง​เสียคน​เก่ง​ไป​ใน​จังหวะ​ที่​ต้องการ​ฝีมือ​มาก​ที่สุด
  • ทีม​สูญเสีย​ความ​ไว้ใจ​ต่อ​ฝ่าย​ขาย — เมื่อ​รู้ตัว​ว่า​ตนเอง​ถูก​ใช้​เป็น “แผน​สำรอง” ของ​คำ​สัญญา​ที่​ไม่​สมจริง ทีม​พัฒนา​จะ​เริ่ม​ไม่​เชื่อถือ roadmap ที่​ฝ่าย​ขาย​วาง​ไว้ และ​ความ​ร่วมมือ​ข้าม​ทีม​จะ​ยิ่ง​แย่​ลง
  • ตัว​ชี้​วัด​ที่​ผิด — องค์กร​จะ​ไม่มี​ทาง​รู้​ต้นทุน​ที่แท้​จริง​ของ feature เพราะ​สิ่ง​ที่​วัด​ได้​คือ “ปิด​ดีล​ทัน​เวลา” ไม่ใช่ “ทีม​พัง” หรือ “หนี้​เทคนิค​เพิ่ม​ขึ้น​เท่าไร” การ​ตัดสิน​ใจ​ครั้ง​ต่อ​ไป​จึง​ยัง​ตั้ง​อยู่​บน​ข้อมูล​ที่​บิดเบือน

สมมติ​ฝ่าย​ขาย​ปิด​ดีล​ลูกค้า​ราย​ใหญ่​โดย​สัญญา​ว่า​ระบบ​จัด​ส่ง​รองรับ “การ​ส่ง​สินค้า​ระหว่าง​ประเทศ” ได้​ทัน​สัปดาห์​หน้า ทั้ง​ที่​ทีม​ยัง​ไม่​ได้​เชื่อม​ต่อ​กับ​ผู้​ให้​บริการ​ขนส่ง​ราย​ใหม่​เลย เมื่อ​ใกล้​ถึง​กำหนด ผู้จัดการ​จึง​สั่ง​ให้ “เปิด feature ไป​ก่อน” โดย​ข้าม guard ที่​ทีม​ตั้งใจ​กัน​ไว้:

// AntiPattern: เปิด feature ที่ยังไม่พร้อม เพราะฝ่ายขายปิดดีลไปแล้ว
public class ShipmentService
{
// เดิมคือ false รอ integration กับ carrier API ใหม่ให้เสร็จก่อน
// แต่ผู้จัดการสั่งเปิดคืนนี้เพราะลูกค้าจะใช้งานพรุ่งนี้เช้า
public bool IsInternationalShippingEnabled => true;
public ShipmentResult Ship(Order order)
{
if (order.Destination.IsInternational && IsInternationalShippingEnabled)
{
// ยังไม่มีตัวคำนวณค่าส่งจริง ใช้ค่าประมาณ hardcode ไปก่อน
// และยังไม่มีระบบ tracking จริงจาก carrier ใหม่
return new ShipmentResult
{
Cost = 9.99m,
TrackingNumber = "PENDING-MANUAL-FOLLOWUP"
};
}
return _domesticCalculator.Calculate(order);
}
}

ทีม​พัฒนา​ถูก​เรียก​เข้า​ประชุม​ฉุกเฉิน​ตอน​สอง​ทุ่ม ทำงาน​ต่อ​เนื่อง​ข้าม​คืน​เพื่อ “ทำให้​มัน​พอใช้ได้” ก่อน​ที่​ลูกค้า​จะ​เข้า​ระบบ​ตอน​เช้า code ที่​ได้​จึง​เต็ม​ไป​ด้วย​ค่า hardcode และ​ไม่มี​การ​ทดสอบ ผล​คือ​คำ​สั่ง​ซื้อ​ระหว่าง​ประเทศ​จำนวน​หนึ่ง​คำนวณ​ค่า​ส่ง​ผิด​และ​ติดตาม​สถานะ​ไม่​ได้​จริง ทีม support ต้อง​ตาม​แก้​ปัญหา​ด้วย​มือ​ไป​อีก​หลาย​สัปดาห์ ขณะ​ที่​งาน​อื่น​ที่​วางแผน​ไว้​ทั้ง​ไตรมาส​ถูก​เลื่อน​ออก​ไป

หัวใจ​ของ​ทาง​แก้​คือ ผูก​คำ​สัญญา​ที่​ให้​ลูกค้า​เข้า​กับ​สถานะ​ความ​พร้อม​จริง​ของ​ระบบ ไม่ใช่​ความ​หวัง​หรือ​ความ​กล้า​เสี่ยง​ของ​ฝ่าย​ขาย ทีม​พัฒนา​ควร​มี​ช่อง​ทาง​ที่​ฝ่าย​ขาย/ฝ่าย​บริหาร​ต้อง “ถาม” ก่อน​สัญญา​อะไร​กับ​ลูกค้า แทนที่​จะ​สัญญา​ไป​ก่อน​แล้ว​ค่อย​มาบอก​ทีม​ทีหลัง:

// ทางแก้: ผูกคำสัญญาเข้ากับสถานะความพร้อมจริง ผ่าน gate ที่ตรวจสอบได้
public class FeatureReadinessGate
{
private readonly IFeatureFlagService _flags;
private readonly ICapacityPlanner _capacity;
public FeatureReadinessGate(IFeatureFlagService flags, ICapacityPlanner capacity)
{
_flags = flags;
_capacity = capacity;
}
// ฝ่ายขาย/ฝ่ายการตลาดต้องเรียก method นี้ก่อนสัญญาวันส่งมอบกับลูกค้า
public CommitmentDecision CanPromise(string featureKey, DateTime requestedDate)
{
var isReady = _flags.PassedDefinitionOfReady(featureKey);
var hasSlack = _capacity.HasSlackBefore(requestedDate);
if (!isReady || !hasSlack)
{
var reason = !isReady
? "feature นี้ยังไม่ผ่าน Definition of Ready เช่น ยังไม่มี integration test"
: "ทีมไม่มี slack เพียงพอก่อนวันที่ขอ อาจกระทบงานที่วางแผนไว้แล้ว";
return CommitmentDecision.Decline(reason);
}
return CommitmentDecision.Approve();
}
}

องค์​ประกอบ​ของ​การ​แก้​ปัญหา​ที่​ยั่งยืน​กว่า​นี้:

  • Definition of Ready ที่​ตรวจสอบ​ได้​จริง — กำหนด​เกณฑ์​ชัดเจน​ว่า feature “พร้อม​สัญญา” ต้อง​ผ่าน​อะไร​บ้าง (ทดสอบ​ผ่าน, มี fallback, มี monitoring) แทนที่​จะ​ให้​ใคร​คน​หนึ่ง​เดา​เอา​เอง
  • แยก​บทบาท​การ​ประเมิน​ความ​พร้อม​ออก​จาก​ฝ่าย​ขาย — ให้​ทีม​พัฒนา​หรือ product owner เป็น​ผู้​ยืนยัน​ความ​พร้อม​ก่อน​วัน​ที่​ถูก​สื่อสาร​ออก​ไป​สู่​ลูกค้า ไม่ใช่​ฝ่าย​ขาย​ประกาศ​แล้ว​ค่อย​แจ้ง​ทีม​ทีหลัง
  • Update the Plan อย่าง​ต่อ​เนื่อง — เมื่อ​สถานะ​งาน​เปลี่ยน (ล่าช้า, blocked, ขอบเขต​เพิ่ม) แผน​และ​วัน​ที่​สื่อสาร​กับ​ลูกค้า​ต้อง​อัปเดต​ทันที ไม่ใช่​ปล่อย​ให้​แผน​เดิม​ค้าง​อยู่​จนถึง​วัน​สุดท้าย
  • นับ​ต้นทุน​ของ heroics ให้​เห็น​จริง — ติดตาม​ชั่วโมง​ล่วง​เวลา ความ​เหนื่อย​ล้า​ของ​ทีม และ​หนี้​ทาง​เทคนิค​ที่​เกิด​จาก​แต่ละ​ครั้ง​ที่ “กู้​วิกฤต” แล้ว​นำ​ตัวเลข​นี้​ไป​คุย​กับผู้บริหารตรงๆ เพื่อ​ให้​เห็น​ว่าการ​สัญญา​เกิน​จริง​มี​ต้นทุน​จริง ไม่ใช่​ของ​ฟรี
  • ให้​รางวัล​กับ​การ​ป้องกัน ไม่ใช่​การ​กู้ภัย — ปรับ​วัฒนธรรม​องค์กร​ให้​ยกย่อง​ทีม​ที่​วางแผน​ดี​จน​ไม่มี​วิกฤต มากกว่า​ทีม​ที่​ต้อง​ทำงาน​ข้าม​คืน​เพื่อ​กอบ​กู้​สถานการณ์​ที่​ป้องกัน​ได้​ตั้งแต่​แรก

แผนภาพ​ด้าน​ล่าง​แสดง​วงจร​อุบาทว์​ของ Lois Lane Planning และ​จุด​ที่​ควร​ตัด​วงจร​ด้วย gate ตรวจสอบ​ความ​พร้อม:

flowchart TD
    A[ฝ่ายขายสัญญา feature ที่ยังไม่พร้อม] --> B[ใกล้ถึงกำหนดระบบยังไม่รองรับ]
    B --> C[ผู้บริหารเรียกทีมพัฒนามากอบกู้]
    C --> D[ทีมทำงานหนักเกินขีดจำกัดจนส่งมอบได้]
    D --> E[ผู้บริหารเห็นว่าการเสี่ยงได้ผล]
    E --> A
    D --> F[หนี้ทางเทคนิคสะสมงานระยะยาวล่าช้า]
    G[Definition of Ready gate ก่อนสัญญา] -.-> A