1 คะแนน โดย GN⁺ 2024-11-30 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • ในฟินเทคที่เกี่ยวข้องกับเงินจริง ความต่างเพียงไม่กี่เซนต์ก็ทำลายความเชื่อมั่นของผู้ใช้ได้ และสตาร์ทอัพซื้อขายหุ้นที่บันทึกธุรกรรมด้วยวิธี single-entry ประสบปัญหา dancing cents
  • Ledger แบบ single-entry เหลือไว้เพียงเงินเข้าออก จึงยากต่อการตามรอยสาเหตุที่ทำให้เกิดความต่าง เช่น อัตราแลกเปลี่ยนเงินตรา, rounding to even ของโบรกเกอร์, หรือค่าธรรมเนียม FINRA TAF
  • Ledger แบบ double-entry มองว่าเงินเคลื่อนย้ายจากบัญชีหนึ่งไปยังอีกบัญชีหนึ่งเสมอ และแยก Accounts, Entries, Transactions เพื่อบันทึกทั้งต้นทางและปลายทาง
  • หากกำหนดสถานะ pending, discarded, posted ของ Entries และเงื่อนไขการ post ของ Transactions ให้ชัดเจน จะจัดการ partial failure และ Entries สำหรับชดเชยได้ปลอดภัยขึ้น
  • Ledger เป็นทั้งอินเทอร์เฟซสำหรับรายงานทางบัญชีและเป็น system of record ที่รักษาความสอดคล้องของเงิน ดังนั้นเมื่อขยายระบบ ความตึงเครียดระหว่าง availability กับ strong consistency จะเพิ่มขึ้น

ความต่างไม่กี่เซนต์ที่ทำลายความเชื่อมั่นของผู้ใช้

  • สตาร์ทอัพที่สร้างแพลตฟอร์มซื้อขายหุ้นปฏิบัติตามหลัก “make it work, make it right, make it fast” และไม่ได้สร้าง ระบบบัญชีแบบ double-entry ตั้งแต่แรก
  • ไม่นานหลังเปิดตัว ยอดเงินที่ vendor รับรู้กับยอดเงินที่ระบบภายในรับรู้คลาดเคลื่อนกันทีละไม่กี่เซนต์
    • ภายในเรียกปัญหานี้ว่า dancing cents
    • หากผู้ใช้ซื้อหุ้น Apple มูลค่า 5 ดอลลาร์ แต่คำสั่งซื้อแสดงเป็น 4.98 ดอลลาร์ ผู้ใช้จะติดต่อฝ่ายสนับสนุนลูกค้าทันที
  • แก่นของปัญหาไม่ได้อยู่ที่จำนวนเงินที่เสียไป แต่อยู่ที่ ความเชื่อมั่นและการเติบโต
    • ผู้ใช้ที่ไม่พอใจจะไม่แนะนำบริการ ทำให้การเติบโตของสตาร์ทอัพติดขัด
    • CEO สั่งให้ฝ่ายสนับสนุนลูกค้าชดเชยด้วยมือเป็นจำนวนไม่กี่เซนต์เมื่อเกิดธุรกรรมผิดพลาด
    • ถึงขั้นสร้าง Slack bot เพื่อจัดการเรื่องนี้

เงินไม่ได้ติดตามแค่ยอดคงเหลือปัจจุบัน แต่รวมถึงมูลค่าในอนาคตด้วย

  • Ledger คือ ระบบที่ติดตามเงิน
  • เงินไม่ใช่แค่ยอดคงเหลือปัจจุบันธรรมดา แต่จำเป็นเมื่อแสดงมูลค่าที่จะได้รับหรือจะต้องจ่ายในอนาคต
    • ในเชิงแนวคิด เงินคือ สินทรัพย์ในอนาคต
  • หากบันทึกเพียงเงินเข้าออก เช่น “ผู้ใช้จ่าย 5 ดอลลาร์”, “ผู้ใช้จ่าย 6 ดอลลาร์” จะไม่เพียงพอต่อการอธิบายกระแสการเงินจริง
  • การโอนเงินผ่านธนาคารนั้นช้าเมื่อเทียบกับอินเทอร์เน็ต และธนาคารจำนวนมากชำระบัญชีการโอนใน วันทำการถัดไป
    • เมื่อการชำระเงินเสร็จสิ้น จะมีความมั่นใจว่าสักวันหนึ่งจะได้รับเงิน
    • แต่หุ้นต้องซื้อผ่านโบรกเกอร์ในตอนนี้
    • ต้องแสดงทั้งยอด pending ที่จะชำระบัญชีในอีกไม่กี่วันและยอดที่ออกไปยังโบรกเกอร์ทันทีพร้อมกัน
  • ในวิธี single-entry เมื่อเกิดข้อผิดพลาด การ rollback ทำได้ยากมาก และในบาง corner case ก็ไม่สามารถแม้แต่จะพยายาม rollback ได้

เหตุผลที่ Ledger แบบ single-entry ขัดขวางการดีบัก

  • Ledger แบบ single-entry แสดงกระแสเงินได้ แต่ไม่สามารถอธิบายได้ว่า กระแสนั้น เกิดขึ้นเพราะอะไร
  • หากต้องการหาสาเหตุของการเคลื่อนย้ายเงินเฉพาะรายการ ต้องนำข้อมูลจากหลาย model มาปะติดปะต่อกัน และในบางกรณีก็ทำไม่ได้ด้วยซ้ำ
  • Ledger แบบ double-entry เก็บทั้งสิ่งที่เกิดขึ้นและเหตุผลที่เกิดขึ้นไว้ด้วยกัน
    • การเคลื่อนย้ายเงินทั้งหมดเกิดจากบัญชีหนึ่งไปยังอีกบัญชีหนึ่ง
    • มีการบันทึกว่าแต่ละเซนต์ออกจากบัญชีใดและไปยังบัญชีใด
  • ปัญหา dancing cents แก้ได้ยากในระบบ single-entry
    • ยากที่จะรู้ว่าไม่กี่เซนต์ที่หายไปเกิดจากอัตราแลกเปลี่ยนหรือไม่
    • อาจเกิดจาก rounding to even mechanism ของโบรกเกอร์
    • อาจเกิดจาก FINRA TAF fees ที่เรียกเก็บเมื่อสิ้นวัน
  • หากไม่เข้าใจว่าระบบทำงานอย่างไร การกำจัด bug ก็ทำได้ยาก

โมเดลข้อมูลของ Ledger: Accounts, Entries, Transactions

  • วิศวกรจำนวนมากเมื่อเริ่มติดตามเงินครั้งแรก มักใส่จำนวนเงินไว้ใน domain model
    • เช่น มี attribute price ใน Order หรือมีคอลัมน์ amount ในตาราง expenses
    • นี่คือแนวทาง balance as property
  • วิธีนี้ทำงานได้เร็วในช่วงแรก แต่เมื่อเวลาผ่านไป reporting จะซับซ้อนและช้าลง อีกทั้งการประมวลผลการชำระเงินและ analytics ก็ยากขึ้น
    • หากงานรายงานตอนกลางคืนใช้เวลาหลายชั่วโมง แนวทางนี้อาจเป็นสาเหตุรากฐาน
  • ควรมอง Ledger เป็น โมเดลข้อมูลแยกต่างหาก ที่สามารถอนุมานธุรกรรมทางการเงินทั้งหมดของระบบได้
  • entity สามอย่างเป็นโครงสร้างพื้นฐาน
    • Accounts: bucket ของมูลค่า และเป็นมุมมองสำหรับดูว่ามูลค่าเปลี่ยนแปลงอย่างไรเมื่อเวลาผ่านไป
    • Entries: กระแสเงินระหว่างบัญชี และแสดงการแลกเปลี่ยนมูลค่าเสมอ
    • Transactions: หน่วยที่รับประกันว่า Entries ถูกจับคู่และประมวลผลอย่างถูกต้อง

สถานะและความไม่เปลี่ยนรูปของ Entries

  • Entries สามารถมีสถานะได้สามแบบคือ pending, discarded, posted
  • Entry จะถูกสร้างในสถานะ pending เสมอ
    • มูลค่าที่แลกเปลี่ยน
    • ทิศทางคือ credit หรือ debit
    • ข้อมูล account ที่อ้างอิงถึง
  • การแสดงทิศทางของจำนวนเงินด้วยค่าบวกและค่าลบเป็นความผิดพลาดที่พบบ่อย
  • โดยพื้นฐาน Entries เป็น immutable แต่ pending Entry สามารถถูก discarded เพื่อสร้าง posted Entry ได้
  • อีกทางเลือกหนึ่งคือสร้าง reversal Entry เพื่อย้อน pending Entry
    • แต่แนวทาง reversal Entry อาจทำให้ประวัติของบัญชีรกได้
    • หากใช้สถานะ discarded เมื่อต้องการดู Entries ปัจจุบันก็เพียงยกเว้นรายการที่ตั้งค่า discarded_at ไว้ และยังไม่เสียประวัติ
  • ในระบบ double-entry ยอดรวมของ credit Entries ที่ไม่ถูก discarded จะเท่ากับยอดรวมของ debit Entries ที่ไม่ถูก discarded
    • ในเชิงแนวคิด หมายความว่าไม่ว่าจะย้ายเงินภายในกระเป๋าอย่างไร ยอดรวมก็ยังเท่าเดิม
  • บัญชีพิเศษบางประเภทที่แทนโลกภายนอกและถูกรวมเข้าใน Profit and Loss statement เป็นข้อยกเว้นที่ไม่สามารถทำให้สมดุลได้

Transactions และการจัดการ partial failure

  • Entries ถูกสร้างเป็นคู่ และ Transactions รับประกันว่ากระบวนการนั้นดำเนินไปตามที่ตั้งใจ
  • Transaction จะถูก posted ได้ก็ต่อเมื่อ Entries ที่เชื่อมโยงอยู่ในสถานะ posted หรือ discarded และถูกแทนที่ด้วย posted Entries แล้วเท่านั้น
  • Transaction ที่เกิด partial failure สามารถย้อนกลับเชิงความหมายได้ด้วย compensating Entries
  • แนวทางนี้เข้ากันได้ดีกับ Saga pattern
    • Saga แลก atomicity กับ availability
    • แทนที่จะใช้ transaction ที่ช้าและล็อกหลายตาราง จะแบ่ง process ออกเป็นงานย่อยที่เล็กกว่าและ checkpoint ระหว่างทาง
    • ระหว่างนั้น transaction อื่นสามารถทำงานได้ ทำให้ throughput ดีขึ้น

Accounts และ normal balance

  • จากมุมมองของ Account เดียว Ledger จะดูเหมือนระบบ single-entry
    • Account หนึ่งมีความสัมพันธ์แบบ one-to-many กับ Entries หลายรายการ
    • ยอดคงเหลือรวมต้องตรงกับค่าที่ aggregate จากยอดคงเหลือย่อยของ Entries ที่เชื่อมโยงอยู่
  • วิธีคำนวณยอดรวมจะแตกต่างกันตาม normal balance ของ Account
  • ทางบัญชีควรหลีกเลี่ยงการผูกเครื่องหมายบวก·ลบไว้กับจำนวนเงินของ Entry
    • บางบัญชีมี net credit เป็นปกติ และบางบัญชีมี net debit เป็นปกติ
    • ตัวอย่างเช่น บัญชีเงินสดธนาคารอาจมี net debit เป็นปกติ แต่หากเบิกเกินบัญชีก็อาจกลายเป็นค่าลบได้
  • normal credit balance หมายถึง ภาวะปกติที่ยอดรวมของ credit Entries ที่เชื่อมโยงมากกว่ายอดรวมของ debit Entries
  • normal debit balance คือกรณีกลับกัน

ความตึงเครียดระหว่างระบบบัญชีกับระบบวิศวกรรม

  • ใน Ledger มีสองระบบที่มีความต้องการแตกต่างกันอยู่ร่วมกัน
    • Accounting system: อินเทอร์เฟซของ Ledger ที่มองจากภายนอก
    • Engineering system: implementation ที่ Ledger ใช้มองตัวเอง
  • Accounting system เปิดเผยข้อมูลที่ aggregate จากหลายมุมมอง
    • Reporting
    • Financial ratios
    • Business Intelligence
  • Engineering system ต้องรับประกันความสอดคล้องและความถูกต้องของข้อมูล
    • ในบริษัทฟินเทค Ledger ทำหน้าที่เป็น source of truth คล้าย CRM ของทีมขาย
  • เหตุผลที่การขยาย Ledger ทำได้ยากคือความต้องการของสองระบบนี้แตกต่างกัน
    • Accounting system ต้องการ availability สูงและ latency ต่ำ
    • Engineering system ต้องการ strong consistency และการตรวจสอบแบบ schema-on-write

แหล่งข้อมูลบัญชีสำหรับนักพัฒนา

1 ความคิดเห็น

 
GN⁺ 2024-11-30
ความคิดเห็นจาก Hacker News
  • อยากให้ไปบอกแบบนั้นกับลูกค้าของ Synapse ดูบ้าง เงินหลายล้านดอลลาร์ หายไป
    ธนาคารต้องกระทบยอดบัญชีตามกฎที่เข้มงวดว่าเงินไหลไปไหน แต่ฟินเทคมักจะเอาบัญชีแยกประเภทของตัวเองไปวางทับบน บัญชี FBO พื้นฐานหนึ่งบัญชีหรือไม่กี่บัญชีที่รวมเงินลูกค้าไว้ เพื่อใช้ติดตามยอดคงเหลือของลูกค้าแต่ละราย ในกรณีของ Synapse ยอดรวมคงเหลือของลูกค้าตามบัญชีแยกประเภทของตนเองสูงกว่ายอดเงินจริงในบัญชี FBO มาก
    หลายคนสงสัยว่าเป็นการฉ้อโกง แต่ผมขอเดิมพันว่าน่าจะเป็นแค่บัญชีแยกประเภทที่เละเทะและเต็มไปด้วยบั๊กมากกว่า พอได้เห็นข้างในแล้ว ผมคงไม่เอาเงินไปฝากในบัญชีเงินฝากของฟินเทคเด็ดขาด ใช้ธนาคารจริง ๆ ดีกว่า ถึงฟินเทคจะโฆษณาว่าเงินฝากอยู่ภายใต้ประกัน FDIC แต่นั่นคุ้มครองเฉพาะกรณีธนาคารพื้นฐานล้มเท่านั้น ไม่ได้คุ้มครองกรณีที่ฟินเทคติดตามเงินของผมไม่ได้
    อ้างอิง: https://www.forbes.com/sites/zennonkapron/2024/11/08/what-th...

    • 90 ล้านดอลลาร์ หายไป และ 250 ล้านดอลลาร์ ถูกอายัด เงินจำนวนมากในนั้นอาจเป็นเงินที่ใครบางคนต้องใช้จ่ายค่าเช่า
      Andreessen Horowitz ลงทุนไว้ และพวกเขาเป็นฝ่ายที่ทำสงครามแบบเผาให้ราบกับกฎระเบียบของรัฐบาลทุกอย่าง
      https://finance.yahoo.com/personal-finance/synapse-bankruptc...
    • ตอนทำงานในบริษัทใหญ่ เคยมีกรณีที่เงินเกิดขึ้นจากอากาศหรือหายไป เพราะระบบธุรกรรมต่าง ๆ ไม่สอดคล้องกัน
      ก่อนหน้านั้นผมคาดไว้แล้วว่า codebase เละเทะเกินกว่าจะติดตามเรื่องพวกนี้ได้อย่างถูกต้อง และเคยเถียงกับหัวหน้าที่เชื่อว่าทุกอย่างเดินได้เหมือนเวทมนตร์ ไม่กี่วันต่อมาก็ได้รับอีเมลว่าจะเริ่มตรวจสอบความไม่ตรงกันทางบัญชี
      JPMC เคยเสนอใช้ คริปโทเคอร์เรนซี ภายในเพื่อจัดการกระแสเงินสดให้สอดคล้องกัน แต่ไม่รู้ว่าจริง ๆ ไปถึงขั้นไหน
    • Synapse บอกว่าความผิดพลาดทางบัญชีที่แท้จริงอยู่ฝั่ง Evolve ซึ่งเป็นธนาคาร รวมถึงธุรกรรมที่ตกหล่น เดบิตที่ไม่ได้รายงาน และการส่งธุรกรรมที่กำลังดำเนินการไปยัง Mercury แต่กลับหักจาก Synapse อย่างผิดพลาด
      https://lex.substack.com/p/podcast-what-really-happened-at-s...
    • เคยมีเงินหายจากบัญชี HSBC เป็นการชำระเงินระหว่างสองบัญชี แต่ รายการบัญชีคู่ ไม่ตรงกันอยู่เล็กน้อย และไม่สามารถกระทบยอดในบัญชีได้ง่าย ๆ
      โต้แย้งอยู่พักหนึ่ง แต่พวกเขาไม่ยอมรับจริงจังและไม่แก้ให้ด้วย ผมเคยสงสัยแบบไม่มีหลักฐานว่าอาจเป็นการขโมยเล็ก ๆ น้อย ๆ ภายใน แต่ความไร้ความสามารถน่าจะเป็นคำอธิบายที่เป็นไปได้มากกว่า
    • สถาบันธนาคารจริง ๆ ก็ไม่น่าไว้ใจพอกัน ตัวอย่างเช่น Vanguard เอางานพัฒนาส่วนใหญ่ไป outsource ที่อินเดียเมื่อไม่กี่ปีก่อน
      เพื่อนที่เคยทำงานเป็นผู้ดูแลระบบที่ BoA บอกว่ามี log บางชนิดที่ต้องเก็บไว้ 7 ปี แต่พอ disk เริ่มเต็มก็ลบทิ้งไปเฉย ๆ
  • สิ่งหนึ่งที่ต้องใช้เวลาทำความเข้าใจตอนเริ่มทำงานที่ Google คือการยอมแลกความน่าเชื่อถือหรือความถูกต้องเพื่อ scalability
    ก่อนหน้านั้นผมเคยทำระบบ billing หรือเว็บแอป OLTP ขนาดเล็ก และไม่เคยแม้แต่จะคิดถึงคำถามอย่างข้อมูลสูญหายที่ยอมรับได้ หรืออัตราความผิดพลาดที่ไม่เป็นศูนย์ สิ่งที่ช็อกกว่าความจริงที่ว่าเมื่อรับคำขอหลายล้านครั้งต่อวินาที ย่อมมีบางส่วนล้มเหลว คือความแตกต่างของทัศนคติด้านวิศวกรรม
    ณ ตอนนี้ก็อาจมีคนหลายพันคนเปิด Gmail แล้วโหลดไม่ขึ้นหรือเจอ error 500 อยู่ ไม่มีใครไล่หาสาเหตุ เพราะผู้ใช้จะกด refresh แล้วใช้ชีวิตต่อไป ในทางกลับกัน แม้ตัวเลขความทนทานของ storage จะดูน่าประทับใจที่ 99.99999% ต่อปี แต่ถ้ามีลูกค้า 2 พันล้านคน ก็จะมี 200 คนที่เจอวันแย่สุด ๆ จริง ๆ
    การเปลี่ยนผ่านจากนิสัยที่เคยตรวจสอบทุก error ใน log ไปสู่แนวทางที่มองว่าทุกอย่างพังอยู่เล็กน้อยตลอดเวลา และต้องคิดต้นทุนก่อนจะแก้อะไรสักอย่างนั้นค่อนข้างช็อก

    • ระดับความทนทาน ที่ต่ำขนาดนั้นไม่ใช่มาตรฐานสมัยใหม่แล้ว
      กฎคร่าว ๆ ที่เห็นบ่อยในสเกลใกล้เคียงกันคือ ตั้งเป้าข้อมูลสูญหาย 1 ครั้งต่อ 100 ปีสำหรับโครงสร้างพื้นฐานทั้งหมด โดยปกติต้นทุนจะเพิ่มขึ้นน้อยกว่า 10% มาก แต่ต้องมีคนที่เข้าใจ combinatorics ตอนออกแบบอัลกอริทึมการจัดวางข้อมูล
      ถ้าต้องการทำความเข้าใจเรื่องนี้ งานวิจัย copyset เป็นจุดเริ่มต้นที่ดี
    • คำพูดนี้โดยรวมถูกต้อง แต่ผมก็เห็นทิศทางตรงกันข้ามบ่อยเหมือนกัน โดยเฉพาะคนจากบริษัทโซเชียลมีเดียที่มีความรู้สึกต่อความล้มเหลวแบบหลวมมาก แล้วย้ายเข้ามาทำ แอปพลิเคชันการเงิน ซึ่งโดยมากไปได้ไม่สวย
    • ตอนอยู่ Google ผมเคยถูกส่งไปช่วยทีม Android ทำงานซิงก์รายชื่อผู้ติดต่อ ปัญหาที่ผมเจอนั้นเกิดขึ้นได้ยากมาก และพอดึงข้อมูล aggregate ของ production มาดู ก็น่าจะกระทบผู้ใช้ 0.01%
      ตอนนำเสนอวิธีแก้และบอกอัตราความผิดพลาดนี้ ก็ถูกถามว่าผู้ใช้ Android 200,000 คนนั้นจะกู้คืนได้อย่างไร ไม่มีวิธีกู้คืน และการซิงก์รายชื่อก็จะพังไปเฉย ๆ ผมเลยถูกบอกให้กลับไปออกแบบใหม่
      ตัวเลขนั้นทำให้ถ่อมตัวขึ้นจริง ๆ แน่นอนว่ามีหลายพื้นที่ที่ 99.99% ก็เพียงพอ แต่ก็มีอีกมากพอ ๆ กันที่มันไม่เพียงพอ
  • เรื่องแบบนี้ช่วยได้ด้วยการจ้างคนที่ใช่ตั้งแต่ต้น ไม่ใช่จ้าง ผู้เชี่ยวชาญ LeetCode มาเต็มทีม แล้วไม่ถามเลยว่านอกจากความสามารถในการนึกถึงโครงสร้างข้อมูลและอัลกอริทึมในหัว พวกเขาสามารถสร้างสิ่งที่อยากสร้างจริง ๆ ได้หรือไม่
    ถ้าคนรู้ว่าควรสร้างสิ่งนั้นอย่างไร ก็ไม่จำเป็นต้องแลกการเติบโต และมันจะถูกสร้างให้ถูกต้องตั้งแต่แรก
    บางครั้งเราต้องการวิศวกรที่มีพื้นฐานการศึกษาด้านอื่น เช่น บัญชี การเงิน หรือชีววิทยา ส่วนที่สำคัญที่สุดในอาชีพของผมคือการเข้าใจอุตสาหกรรมของสิ่งที่ผมกำลังสร้างอย่างลึกซึ้ง และรู้จักผู้เชี่ยวชาญในสาขานั้นที่สามารถตั้งคำถามที่สำคัญจริง ๆ ได้ นั่นแหละคือการแก้ปัญหาและวิศวกรรม ส่วนที่เหลือคือการโปรแกรม/เขียนโค้ด

    • นี่เป็นครั้งแรกที่ผมเห็นโพสต์ใน HN บรรยายชีวิตประจำวันตอนนี้ของผมได้แม่นจนน่ากลัว และยังทำให้เห็นด้วยอย่างเต็มที่
      ผมใช้ชีวิตการทำงานส่วนใหญ่ในพื้นที่ที่เทคโนโลยีกับการเงินทับซ้อนกัน ส่วนใหญ่เป็นด้านการปฏิบัติตามกฎภาษีขายและภาษีการใช้ ระหว่างนั้นผมไม่เคยตระหนักพอว่านักบัญชี คอนโทรลเลอร์ และทนายความมีอิทธิพลต่อผมมากแค่ไหน
      ช่วงหลังผมได้ให้คำปรึกษาระบบบัญชีแยกประเภทของสตาร์ทอัพที่ค่อนข้างเก่าแห่งหนึ่ง และตกใจมากเมื่อเห็นว่าถ้าวิศวกรที่ไม่มีพื้นฐานการเงินหรือบัญชีมาสร้าง ระบบบัญชี ผลลัพธ์จะออกมาเป็นอย่างไร
      ไม่จำเป็นต้องตามหาคนวิเศษที่เป็นทั้งนักบัญชีและวิศวกร แค่ให้มีนักบัญชีตัวจริงนั่งข้างทีมวิศวกรรมระหว่างกระบวนการออกแบบก็พอแล้ว หลังจากออกแบบการยกเครื่องทั้งหมดเสร็จ ผมให้เพื่อนที่เป็น CPA ตรวจทานอย่างละเอียด เขาพบช่องโหว่ในบางสถานการณ์ แต่โดยรวมก็ใช้ได้
      เงินเป็นปัญหาวิศวกรรมที่ยาก เพราะเงินมาพร้อมกับความพิลึกพิลั่นสารพัดของมนุษย์ที่รายล้อมมัน
    • ใช่เลย บัญชีแยกประเภท คือความรู้โดเมน ทุกอย่างอื่น รวมถึงการปรับให้เหมาะกับโหลดสูง ต้องสร้างอยู่บนสิ่งนั้น
    • ในบางกลุ่มมีแนวโน้มน่ารำคาญที่เชื่อว่าเทคโนโลยีแก้ปัญหาได้ทุกอย่าง พอให้คุณค่ากับ นวัตกรรม เหนือสิ่งอื่นใด ก็เลยถอยห่างจากผู้เชี่ยวชาญ
  • สิ่งนี้ทำให้ยืนยันอีกครั้งว่า ความรู้โดเมน สำคัญในภาวะผู้นำด้านวิศวกรรม ถ้าทำงานในบริษัทการเงิน ก็ต้องเข้าใจการเงินในระดับหนึ่งเพื่อการตัดสินใจทางเทคนิคและการประนีประนอมที่ถูกต้อง และงานสื่อสารมวลชนหรือพาณิชย์ก็เช่นกัน
    องค์กรที่ประสบความสำเร็จที่ผมเคยทำงานด้วย มักใส่คำถามที่ไม่ใช่เชิงเทคนิคแต่เฉพาะโดเมนไว้ในการสัมภาษณ์ทีมเทคโนโลยีเสมอ ในทางกลับกัน บางทีมที่เก่งทางเทคนิคมากกลับลำบากเพราะขาดความเข้าใจเชิงโดเมน

    • ผมเป็นวิศวกรซอฟต์แวร์และเป็น CPA ด้วย จึงมีความรู้โดเมนอยู่ แต่ไม่รู้ว่าจะหางานที่ได้ใช้มันอย่างไร
      มองไปทางไหนก็ดูเหมือนทุกที่ชอบคนที่มีประสบการณ์วิศวกรรมซอฟต์แวร์มากกว่าผมสองเท่า แม้ไม่มีความรู้โดเมนเลย มากกว่าคนอย่างผมที่มีประสบการณ์บัญชีและมีประสบการณ์วิศวกรรมซอฟต์แวร์ค่อนข้างสั้น ผมสงสัยว่าจะมีวิธีใช้ประโยชน์จากสิ่งนี้อย่างมีประสิทธิภาพไหม
    • เห็นด้วยกับเจตนา แต่จะช่วยกว่าถ้ามองคำถามเฉพาะโดเมนเหล่านั้นเป็น คำถามเชิงเทคนิค ของสาขาเทคนิคอีกด้านหนึ่ง
      การเงินก็เป็นเรื่องเทคนิค วิศวกรรมเครื่องกลก็เป็นเรื่องเทคนิค และการจัดการกีฬา หรือสังคมวิทยา ก็มีองค์ประกอบเชิงเทคนิคขนาดใหญ่เช่นกัน เมื่อมองความสามารถทางเทคนิคให้กว้างขึ้น ก็จะเกิดความถ่อมตัวที่จำเป็นต่อการทำงานร่วมกันในหลายโดเมน
    • หลังจากเริ่มทำงานในบริษัทประกัน ผมก็รู้ว่าการเข้าใจ อุตสาหกรรมประกันภัย ยากกว่าการเข้าใจ codebase มาก ถ้า codebase ทำงานแปลก ๆ อย่างน้อยก็ยังตามดูด้วยดีบักเกอร์ได้
    • ผมไม่ค่อยแน่ใจกับเรื่องนั้น ผมเข้าใจมาเสมอว่าการมีความรู้โดเมนครบถ้วนเป็นบทบาทของ ผู้จัดการผลิตภัณฑ์
      หน้าที่ของ PM คือทำงานร่วมกับวิศวกรรมเพื่อตรวจสอบว่าข้อกำหนดถูกต้องหรือไม่ และผลิตภัณฑ์ที่สร้างขึ้นตอบโจทย์ข้อกำหนดนั้นหรือไม่ ในสภาพแวดล้อมแบบ Agile บทสนทนาและการตรวจสอบแบบนี้เกิดขึ้นทุกสปรินต์ ดังนั้นจึงยากที่อะไรสักอย่างจะหลุดรอดไปนานเกินไป
      ถ้าไม่มี PM ทีมวิศวกรรมก็จำเป็นต้องมีความรู้โดเมนลึก แต่ถ้ามีแล้ว นั่นไม่ใช่ความรับผิดชอบของวิศวกรรม แต่เป็นความรับผิดชอบขององค์กรผลิตภัณฑ์
  • ขอเล่าเรื่องเก่าสักเรื่อง ผมไม่เคยสร้างระบบบัญชีคู่ แต่เมื่อหลายสิบปีก่อนเคยสร้าง ระบบคิดเงิน ในสตาร์ทอัพอินเทอร์เน็ต/โทรคมนาคมที่เติบโตจนมีรายได้ระดับแปดหลัก
    ตอนนั้นเป็นนักพัฒนาหนุ่มที่ยังไม่รู้อะไรมาก และบังเอิญได้เริ่มทำลอจิกการคิดเงินตั้งแต่วันแรก ซึ่งไม่รู้ว่าดีหรือร้าย ผมสร้างมันไว้สองจุดในระบบ คือหน้าเว็บคิดเงินสำหรับผู้บริโภค และโปรเซสแบ็กเอนด์แยกต่างหากที่สร้างอินวอยซ์และตัดบัตรเครดิต
    การทำให้ทั้งสองอย่างสอดคล้องกันเป็นเรื่องยากอย่างน่าประหลาดใจ เราเผาเงินทุนเพื่อวนพัฒนาต่อเนื่องในการหาการตอบรับของตลาด และมีการเพิ่มผลิตภัณฑ์กับบริการใหม่ วิธีส่วนลดและราคาใหม่ การคิดเงินตามการใช้งาน การคิดเงินรายเดือน ใช้ฟรี X ครั้งแรก ผู้ชำระเงินหลัก/บัญชีย่อยของบัญชีองค์กร ศูนย์ต้นทุนที่ผู้ใช้กำหนดเอง การปันส่วนภาษีไปยังศูนย์ต้นทุนนั้น และการปันส่วนระดับ 1 เซ็นต์ เป็นต้น ทุกครั้งที่เพิ่มสิ่งเหล่านี้ ก็จะมีรายละเอียดและข้อยกเว้นใหม่ ๆ ทำให้ตัวเลขในสองหน้าจอ/สองวิธีไม่ตรงกัน
    เพราะผมเป็นคนรับผิดชอบการคิดเงิน ทุกเดือนผมจึงใช้เวลาหลายวันไล่อ่านอินวอยซ์ทั้งหมดด้วยมือ เพื่อตรวจสอบครั้งสุดท้ายว่าตัวเลขตรงกันก่อนจะตัดบัตรเครดิตและส่งอินวอยซ์กระดาษ ผมมักจะพบปัญหาใหม่ที่กระทบลูกค้าหนึ่งรายหรือไม่กี่รายเสมอหรือบ่อยครั้ง แล้วแก้โค้ดก่อนการคิดเงินจริง ผมรู้สึกกังวลเสมอกับการปล่อยระบบไปโดยไม่ตรวจซ้ำทุกอย่างด้วยมือ
    ผมเคยคิดจะรีแฟกเตอร์ลอจิกการคิดเงินให้เหลือที่เดียวเพื่อกำจัดความไม่ตรงกันและการตรวจเทียบด้วยมือ แต่หลังจากคิดอยู่นาน ผมก็ตระหนักว่า codebase เดียวทำให้ไม่สบายใจ และ codebase สองชุดกลับช่วยจับข้อผิดพลาดของผมได้ หลังจากนั้นผมค่อย ๆ ทำให้การรันอัตโนมัติและการตรวจเทียบข้ามกันระหว่างสอง implementation ง่ายขึ้นเรื่อย ๆ
    โค้ดคิดเงินค่อนข้างรกเกินกว่าจะเอาไปอวดได้ แต่ผมภูมิใจมากกับความถูกต้องของการคิดเงิน การที่มีเรื่องร้องเรียนน้อย และความผิดพลาดชวนหวาดเสียวหลายอย่างที่หลีกเลี่ยงได้ตลอดหลายปี ผมรู้สึกผิดนิดหน่อยกับความซับซ้อนที่ทิ้งไว้ให้คนรับช่วงต่อ แต่จนถึงตอนนี้ก็ไม่ได้เสียใจมากนัก
    หลังจากประสบการณ์นั้น ผมเข้าใจแรงจูงใจของการทำบัญชีคู่มาโดยตลอด เท่ากับว่าผมประดิษฐ์ โค้ดคิดเงินแบบลอจิกคู่ ขึ้นมาใหม่ในแบบห่วย ๆ เพื่อกันไม่ให้ความผิดพลาดของผมไปทำร้ายลูกค้า

    • อะไรก็ตามที่เกี่ยวกับการคิดเงินหรือเงิน ล้วนผิดพลาดได้ง่ายมาก
      ทีมข้อมูลที่ผมเคยไปรับหน้าที่นำในบริษัทเก่ามีนิสัยโชคร้ายคือทำเงิน “หาย” ไม่ใช่ว่าเงินจริงหายไประหว่างย้ายไปที่อื่น แต่เป็นกรณีที่บันทึกที่ควรใช้เรียกเก็บเงินลูกค้าหายไป
      เวลาไม่ทำรายได้หาย ก็จะคิดเงินซ้ำ และเรื่องแบบนี้เกิดขึ้นต่อเนื่อง ต้องใช้การทำงานหนักถึง 3 ปี กว่าจะได้ความเชื่อมั่นจากผู้บริหารกลับมา
    • ไม่ได้มีเจตนาร้ายนะ แต่ฟังดูเหมือนฝันร้ายเลย ขณะเดียวกัน การที่ทำให้ได้ความถูกต้องแม้ระบบจะซับซ้อนก็เป็นเรื่องยอดเยี่ยมจริง ๆ คุณควรภูมิใจได้
    • เรื่องนี้คล้ายกับ N-version programming มาก
  • ไม่มีการทดสอบเลยหรือ? ถ้าถึงขั้นยกตัวอย่างว่า “ทุกครั้งที่ซื้อของ 5 ดอลลาร์ ในบันทึกธุรกรรมจะเหลือ 4.98 ดอลลาร์” คือถ้าเสียเงินทุกธุรกรรม ปัญหามันใหญ่กว่า การไม่มีบัญชีคู่ มาก
    ใครกันที่สร้างระบบการเงินแบบนั้นแล้วคิดว่าปกติ? เรื่องค่าชดเชยก็เป็นปัญหา แต่ถ้าเป็นบริการแบบนั้นควรหนีให้เร็วที่สุดเท่าที่ทำได้

    • ก็คนกลุ่มนี้แหละที่ทำแบบนั้น พวกเขาพูดเองว่า “เราจะทำให้ถูกต้องก็ได้ แต่ไม่ได้ทำ” มันไม่ใช่อุบัติเหตุ แต่เป็นการเลือก
      พวกเขาล้อกันว่าเป็น “เซ็นต์เต้นระบำ” และทำแบบนั้นเพราะรู้ว่าไม่ต้องรับผลลัพธ์ที่มีนัยสำคัญใด ๆ พวกเขาเคลื่อนที่เร็ว ทำบางอย่าง—ที่เกี่ยวกับเงิน—พัง แล้วก็หัวเราะกลบเกลื่อน
      ตอนนี้กลับพยายามสั่งสอนคนอื่นราวกับมีอำนาจทางศีลธรรมและเทคนิค เพียงเพราะพวกเขาตั้งใจตัดสินใจแบบนั้น นี่เป็นเรื่องไร้สาระแบบ วัฒนธรรมสตาร์ทอัพ VC ที่หยิ่งผยองอย่างน่าทึ่ง
    • ยังไม่เข้าใจเลยว่าเงินหายไปได้อย่างไร บัญชีคู่อาจช่วยวินิจฉัยได้ แต่จริง ๆ แล้วมันหายไปได้ยังไง?
    • ผมก็คิดแบบเดียวกัน Ledger มีข้อดีมากมาย แต่ไม่ได้แก้ปัญหา เซ็นต์เต้นระบำ ตัวเลขผิด ๆ ก็แค่ถูกบันทึกลงใน Ledger เท่านั้น
      แน่นอนว่ามันอาจให้เบาะแสในการหา bug ได้ แต่การเขียน test พื้นฐานก็ให้ผลแบบเดียวกัน
    • หลักการออกแบบ ที่ดีข้อเดียวมีค่าเท่ากับ test 1000 ตัว
    • จะตัดสินได้อย่างไรว่าเรื่องนั้นจริงหรือไม่?
  • ไม่เข้าใจว่าทำไมผู้เขียนถึงหยิบสุภาษิต “make it work, make it right, make it fast” มาใช้ในเชิงลบ บางทีอาจเข้าใจผิดว่า “make it fast” อยู่ตรงไหน
    “make it right” เป็นขั้นตอนที่สอง และก่อนจะทำให้มันทำงานได้อย่างถูกต้อง งานควรหยุดอยู่ตรงนั้น ระบบต้องทำงานอย่างสมบูรณ์แข็งแรง “make it fast” หรือการ optimize ควรเริ่มหลังจากปัญหาเรื่องความถูกต้องและความสมบูรณ์แข็งแรงถูกแก้หมดแล้วเท่านั้น
    เรื่องนี้ไม่เกี่ยวกับความเร็วในการส่งมอบหรือการทำงานเร็ว แต่หมายถึงให้เลื่อนการ optimize ไปเป็นขั้นตอนสุดท้าย
    แต่ถ้าสิ่งที่ผู้เขียนอยากพูดคือ บางอย่างต่อให้ “ทำงานได้” แบบคร่าว ๆ ก็ยังห่างจาก “ความถูกต้อง” มากจนแก้ย้อนกลับทีหลังไม่ได้ และต้องทำให้ “ถูกต้อง” ตั้งแต่ต้นก่อนที่มันจะเริ่มพอทำงานได้ อันนี้ก็เข้าใจได้

    • ผมคิดว่าประโยคสุดท้ายถูก ผู้เขียนน่าจะบอกว่าใน ระบบชำระเงิน คุณไม่สามารถทำให้มันทำงานได้ก่อนแล้วค่อยทำให้ถูกต้องทีหลัง
      ผมก็คิดเหมือนกัน และเคยมีส่วนร่วมในการ audit ระบบ fintech ผู้ตรวจสอบต้องดาวน์โหลดทุกอย่างเป็นสเปรดชีต Excel แล้วกระทบยอดตัวเลขก่อนอนุมัติสมุดบัญชี ใช้ทั้งเวลาและเงินมาก และผมเดาว่าอีก 3 ปีต่อมา ใน liquidity event คงสร้างความต่างอย่างน้อยราว 0.1 unicorn
    • ผมคิดว่าผู้เขียนเลือกสุภาษิตผิด
      ในสตาร์ทอัพที่เคลื่อนไหวเร็ว จะปล่อย MVP ที่ใช้งานได้จริงให้เร็วที่สุด เพราะต้องสร้างฐานลูกค้า การเงิน ฯลฯ จึงมักหยุดอยู่ที่ขั้น “make it work”
      สุภาษิตที่เหมาะกว่าน่าจะเป็นของ Facebook คือ “move fast and break things” แต่เรื่องนั้นใช้ได้ก็ต่อเมื่อสามารถแก้ทีหลังได้เท่านั้น เช่น ถ้าคุณสร้างเครื่องบิน ก็คงไม่ทำแบบนั้น
    • บอกว่าทีมวิศวกรรมทำตามสุภาษิตนี้ และในนั้นมี “make it right” รวมอยู่ด้วย แต่พวกเขาไม่ได้ทำเช่นนั้น พวกเขาไม่ได้แม้แต่พยายามค้นหาว่าตัวเองไม่รู้อะไรเกี่ยวกับ fintech ก่อนสร้างผลิตภัณฑ์
      เมื่อดูบริบทแล้ว ความเข้าใจผิดที่กล่าวในประโยคแรกดูเป็นไปได้มากที่สุด เพราะถัดจากนั้นก็พูดถึงแรงกดดันด้านเวลาที่สตาร์ทอัพได้รับ
  • คอมเมนต์ส่วนใหญ่ที่นี่กำลังทำซ้ำสิ่งที่บทความวิจารณ์อยู่ เห็นการถกเถียงยาว ๆ ที่ปกป้อง บัญชีเดี่ยว นับไม่ถ้วน
    บัญชีเดี่ยวอาจง่ายกว่าและเป็นแบบทั่วไปกว่า แต่บางครั้งการทำตามระบบและ abstraction ที่พัฒนามาหลายศตวรรษก็เป็นความคิดที่ดี
    ถ้าไม่ได้จำเป็นต้องใช้อะไรที่แตกต่างจริง ๆ ใช้บัญชีคู่ดีกว่า สัญชาตญาณของโปรแกรมเมอร์อาจรู้สึกตะขิดตะขวง แต่เมื่อถึงช่วงที่ต้องเรียกนักบัญชีจริง ๆ มาช่วยจัดการความไม่ตรงกัน คุณจะขอบคุณมัน
    เกี่ยวกับเรื่องนี้ มีใครรู้แหล่งข้อมูลดี ๆ สำหรับโปรแกรมเมอร์ด้านการชำระเงินหรือสาขาใกล้เคียงไหม? ประมาณ “การบัญชีสำหรับโปรแกรมเมอร์” น่ะ

  • ถ้าบอกว่ากำลังใช้ระบบฐานข้อมูลที่ข้อมูล 1% หายไปทุก ๆ 10 ธุรกรรม คุณจะยังรับคำแนะนำในบล็อกวิศวกรรมแบบนี้อย่างจริงจังได้ไหม? บทความแบบนี้ให้ความรู้สึกเหมือนโฆษณาประชาสัมพันธ์บุคคลหรือกลุ่มใดกลุ่มหนึ่งที่ห่อมาอย่างสุขุม มากกว่าจะเป็นการแนะนำแนวคิด

  • ถ้าอยากเห็นว่า ทัศนคติหละหลวม แบบนี้ต่อซอฟต์แวร์ที่เคลื่อนย้ายเงินก่อผลอย่างไรกับคนจริง ๆ ให้ดูคดีอื้อฉาว Post Office
    https://en.wikipedia.org/wiki/British_Post_Office_scandal
    ทุกสิ่งที่เคลื่อนย้ายเงินต้องถูกปฏิบัติอย่างจริงจังที่สุด และควรรู้จักความล้มเหลวในอดีตให้มากที่สุดเท่าที่ทำได้