Business Model-Driven Development (BM-DD)

จากความรู้ และประสบการณ์ของผมเอง ก็ได้วางกรอบหน้าที่ความรับผิดชอบที่จำเป็นสำหรับการพัฒนาโปรดักส์ ออกเป็น 3 ส่วนหลักเรียกว่า Business Model-Driven Development (BM-DD)

การพัฒนาโปรดักส์ด้วยกระบวนการ BM-DD จะประกอบไปด้วยความรู้ ความเข้าใจ และขั้นตอนวิธีการทำงาน จำแนกอยู่ใน 3 พื้นที่หลัก ได้แก่  Business Model, Design และ Architecture

Business Model คือ โมเดลที่ประกอบไปด้วยสิ่งจำเป็นที่เพียงพอสำหรับทำให้เกิดธุรกิจให้ชีวิตอยู่ได้ คือ มีรายได้ มากกว่ารายจ่าย ให้พอเลี้ยงโมเดลให้อยู่ได้ยาวนาน หรือมีความยั่งยืน และไม่ผิดกฏหมาย นั่นคือการประกอบธุรกิจ จึงเรียกว่า โมเดลธุรกิจ

Design คือ สิ่งที่มีคุณลักษณะที่ให้คุณค่า หรือประโยชน์ ที่ออกมาจากโมเดลธุรกิจ สิ่งนั้นก็คือ สินค้า และ บริการ

Architecture คือ วิธีการทำงาน, กระบวนการ, หลักการ, แนวคิด, การบริหารจัดการ, กลยุทธ์, เทคนิคเครื่องมือ, ทรัพยากรณ์ ต่างๆ ที่ทำงานร่วมกัน ประกอบกันขึ้น ทำให้ Design และ Business Model นั้น เกิดขึ้นจริงได้

Business Model แบ่งได้สองประเภท คือ เกิดขึ้นใหม่ (Startup) และ เกิดขึ้นแล้ว (Corporation)

Design แบ่งได้เป็น สินค้าที่จับต้องได้, สินค้าที่จับต้องไม่ได้ และ ผสมกันคือเป็นทั้งสองแบบ

Architecture แบ่งเป็น Front-end และ Back-end

Business Model ไม่ว่าจะแบบใด สามารถแยกกกอเป็นกรอบหน้าที่ ได้เป็น 9 องค์ประกอบ (จาก Business Model Canvas) ได้แก่ 1-Customer, 2-Value Proposition, 3-Marketing Channel, 4-Delivery Channel, 5-Revenue Stream, 6-Activities, 7-Resources, 8-Partner และ 9-Cost Structure

Design จะเป็นหลักการออกแบบโปรดักส์ โดยจะเรียกประโยชน์ที่ได้จากโปรดักส์ว่า ฟีเจอร์ ซึ่งฟีเจอร์นั้น จะต้องตอบโจทย์ หรือ สามารถแก้ปัญหาจากองค์ประกอบ 2-Value Proposition เป็นหลัก แต่องค์ประกอบอื่นๆใน  Business Model ก็ออกแบบให้ช่วยเหลือ สนับสนุนได้เช่นกัน เพื่อความอยู่รอดของ BM

Architecture ประกอบด้วย Front-end ก็คือ Interface ที่ Customer กับตัว Design มาทำงานร่วมกัน แล้วเกิดคุณค่าตามต้องการใน Value Proposition ส่วนนี้ก็จะเรียก User Experience ตัว Interface มีทั้งเป็นวัตถุ หรือ ซอฟแวร์เสมือน ก็แล้วแต่ Design แต่หลักสำคัญคือ Customer ต้องได้คุณค่าครบตามต้องการใน Value Proposition ที่กล่าวไว้ ส่วน Back-end คือส่วนที่จะทำให้ Front-end เกิดขึ้นจริง ประกอบด้วย Host, Data Center, Network, Software, Source Code, Server Tools เช่น Continues Integration/Delivery และอื่นๆ ที่ประกอบกันทำให้ Front-end เกิดขึ้น

BM-DD นี้ก็เป็นกรอบ (Framework) สำหรับพัฒนาโปรดักส์ เหมือน Scrum คือไม่กำหนดเทคนิค หรือเครื่องมือเฉพาะ ตายตัวเข้าไป เพียงแก่แบ่งกรอบของงาน หรือหน้าที่ไว้เป็น 3 ส่วนก็คือ BM, Design และ Architecture

ซึ่งในส่วนของ Development  จะอยู่ในกรอบของ Architecture สามารถนำเอา Scrum เข้ามาใช้ได้เลย

คือจาก BM และ Design จะทำให้เราสามารถสร้าง product backlog ได้ จากนั้น ก็ดำเนินการ Sprint นั่นก็คือการทำงานในส่วนของ Architecture ในกรอบการทำงานแบบ BM-DD นั่นเองครับ

มุมมอง BM-DD แบบจุลภาค (MicroBM-DD) 

มุมมอง BM-DD แบบมหภาค (MacroBM-DD) 

ข้อมูลอ้างอิง

Business Model:

Design:

Architecture:

 

คิดแบบไฮบริด

ถ้าสิ่งใดๆสามารถกำหนดได้สมบูรณ์ เราสามารถระบุเลยว่ามีความน่าจะเป็นที่จะเกิดขึ้น 100% เรียกว่า วิธีคิดแบบนักคณิตศาสตร์

ถ้าสิ่งใดๆเราไม่สามารถกำหนดได้สมบูรณ์ เพราะเราไม่รู้ หรือ รู้ไม่ครอบคลุมทั้งหมด ทำให้ระบุความน่าจะเป็น ไม่เท่ากับ 100% จะมีส่วนที่ผิดพลาดแถมมาเสมอ เรียกว่า วิธีคิดแบบนักสถิติ

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

ในชีวิตจริง คนเราจะคิด แบบที่เรียกว่า ไฮบริด คือ ใช้ทั้ง 3 แบบผสมกัน ขึ้นกับปัญหา ความรู้ ความคิด ความเชื่อ ประสบการณ์ สรุปได้คือ ขึ้นกับกระบวนทัศน์ ของแต่ละคน

#:P

การออกแบบโมเดลเก็บข้อมูลธุรกรรมการค้าเหมือนนักบัญชี

สวัสดีครับผม

ก็พอมีเวลาว่างมาเขียนแชร์กันอีก จริงๆอยากเขียนความรู้นี้มานานแล้ว แต่ไปสนใจเรื่องอื่นก่อน เพราะผมคิดว่า ความรู้เรื่องหลักการบันทึกบัญชีนี้ สำคัญมากต่อการออกแบบ Data(Domain) Models หรือ โครงสร้างข้อมูลสำหรับเก็บธุรกรรมที่เกิดจากกิจกรรมต่างๆที่เกิดขึ้นในโมเดลธุรกิจทุกชนิดเลยทีเดียว

การบัญชี คือ การจัดการส่วนของกระบวนการจดบันทึกรายการค้า (Entry)

การบัญชีมีสิ่งที่ต้องจัดการ ได้แก่ วิธีการบันทึกรายการค้า, การจัดหมวดหมู่รายการค้า, การสรุปรายงานรายการค้า และการวิเคราะห์รายการค้า

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

ผมจะขออธิบายสมการบัญชีก่อน เพราะ สำคัญต่อการออกแบบ Data Model เพื่อเก็บบันทึกรายการค้าแบบระบบคู่ ต่อไป

สมการบัญชี หรือที่เรียกว่า สมการงบดุล (The balance sheet equation) เป็น สมการหลักสำหรับบันทึกรายการค้าที่เรียกว่า ระบบบันทึกรายการค้าแบบคู่ คือ แต่ละธุรกรรมการค้า จะถูกบันทึก สองด้านคือ debit และ credit โดยที่ debit เท่ากับ credit เสมอ สมการบัญชี เขียนแบบนี้ครับ

สินทรัพย์ (Assets) = หนี้สิน (Liabilities) + ส่วนของเจ้าของ (Owner’s/Stockholder’s Equity, Capital)

Owner’s Equity = Contributed Capital + Retained Earnings

Retained Earnings = Net Income – Dividends

และ

 Net Income = Income − Expenses

Capital ในทางเศรษฐศาสตร์ คือ สินค้าที่แท้จริง ไม่ใช่ เงิน หรือ หุ้น หรือ สินทรัพย์ทางการเงินต่างๆ เช่น สินค้า (Goods) และ สิทธิการได้รับบริการ (Eligibility Services) ที่มีประโยชน์ส่งเสริมการผลิต หรือบริการในโมเดลธุรกิจ คือถ้าเป็นเงิน ก็ต้องเปลี่ยนให้เป็น สินค้า หรือบริการก่อน ก็จะเป็น Capital

Contributed Capital คือ ทรัพย์สินที่สนับสนุนธุรกรรมทางการค้า

Retained Earnings คือ ส่วนรายได้ที่สำรองไว้

Dividends คือ ส่วนที่กันไว้ปันผล

Net Income คือ รายได้ ลบ รายจ่าย ที่เกิดขึ้น จากการค้า

ในหลักการบันทึกบัญชี เขาจะบันทึกโดยเปลี่ยนเป็นหน่วยเงินตรา สกุลเดียวกันทั้งหมดก่อนบันทึกเสมอ

ตัวอย่าง การบันทึกรายการค้าแบบง่าย

หมายเลขธุรกรรม สินทรัพย์ หนี้สิน ส่วนของเจ้าของ รายการค้า
1 +1000 +1000 เจ้าของกิจการ ซื้อหุ้นด้วยเงินสด 1000 บาท
2 +200 +200 ซื้อสินทรัพย์ ด้วยการกู้ยืมเงิน 200 บาท
3 -500 -500 ขายสินทรัพย์ 500 บาท ได้เงินสด แล้วจ่ายหนี้
4 +1000 +600 +400 ซื้อสินทรัพย์ ด้วยทุนส่วนตัว 400 และ กู้ยืม 600
5 +300 +300 รับเงินจากธุรกิจ 300
6 -200 -200 จ่ายค่าเช่าทุก 200
7 +400 -400 มีการจ่าย แต่บันทึกรายการจ่ายไว้ก่อน
8 -500 -500 จ่ายหนี้ด้วยทุกตัวเอง

ต่อไปนี้ เป็นการใช้ การบันทึกโดยใช้ระบบธุรกรรมคู่ ที่มีประจุเป็น debit และ credit จะไม่ใช้สัญลักษณ์ +, –

#1 เจ้าของกิจการ ซื้อหุ้นด้วยเงินสด 1000 บาท

หุ้น เป็นสินทรัพย์ ชนิดหนึ่ง

เงินสด ก็เป็น สินทรัพย์ ชนิดหนึ่ง เหมือนกัน

เนื่องจาก ธุรกรรมการค้านี้ ไม่มี บัญชี เงินสด จึงบันทึกใน บัญชีทุนส่วนของเจ้าของไว้ ดังนั้น จะบันทึกบัญชี แบบนี้

Debit บัญชีหุ้น 1000 บาท

Credit บัญชีส่วนของเจ้าของ 1000 บาท

จะเห็นว่า การบันทึกรายการค้าครั้งนี้ ถูกต้อง เพราะ บัญชีหุ้น = บัญชีส่วนของเจ้าของ หรือ Debit เท่ากับ Credit

รายการค้า Debit Credit
#1 เจ้าของกิจการ ซื้อหุ้นด้วยเงินสด 1000 บาท
บัญชีหุ้น 1000
บัญชีส่วนของเจ้าของ 1000

ถ้ากรณี ส่วนของเจ้าของ มีบัญชีเงินสด อยู่แล้ว เกิดจาก รายการเปิดบัญชี (Opening Entry) เราจะต้องบันทึกรายการค้า ตามจริงแบบนี้

รายการค้า Debit Credit
#1 เจ้าของกิจการ ซื้อหุ้นด้วยเงินสด 1000 บาท
บัญชีเงินสด 1000
บัญชีส่วนของเจ้าของ 1000
บัญชีหุ้น 1000
บัญชีเงินสด 1000

นำรายการมาบันทึก แยกประเภทบัญชี ได้แบบนี้

Code 101: บัญชีเงินสด

Debit Credit
เจ้าของนำเงินสดมาลงทุน 1000
ซื้อหุ้น 1000

Code 111: บัญชีหุ้น

Debit Credit
ซื้อหุ้น 1000

Code 301: บัญชีส่วนของเจ้าของ

Debit Credit
นำเงินสดมาลงทุน 1000

เมื่อนำ บัญชีแยกประเภทมาหาดุล โดยเอา ด้าน Debit ลบ Credit แล้วถ้ามีค่าเป็น + ให้เป็นดุลด้าน Debit และ ถ้าเป็น – ให้ไว้ดุลด้าน Credit เราจะได้

บัญชีเงินสด เท่ากับ 0

บัญชีหุ้น เท่ากับ +1000  และ

บัญชีส่วนของเจ้าของ เท่ากับ -1000

ซึ่งจะเห็นว่า Debit เท่ากับ Credit การบันทึกบัญชีนี้ จึงถูกต้อง

เมื่อนำแนวคิดการบันทึกแบบนักบัญชีมาออกแบบ Data Model สำหรับ ใช้เก็บข้อมูลลงฐานข้อมูล ก็จะได้ออกมาแบบนี้ครับ (ดูภาพ Accounting Data Model)

Entry (#ID, Amount, Currency, EntryType, BookedDate, Description)

Account (#ID, Code, AccountType, EffectiveFrom, EffectiveTo)

AccountingTransaction(#EntryID, #AccountID, TransactionCode)

 

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

TransactionCode Account ID Code AccountType EntryID Amount EntryType Description
IV-1 1 101 Assets 1 1000 Debit เจ้าของนำเงินสดมาลงทุน
IV-1 1 101 Assets 2 1000 Credit ซื้อหุ้น
IV-1 2 102 Assets 3 1000 Debit ซื้อหุ้น
IV-1 3 301 Equity 4 1000 Credit นำเงินสดมาลงทุน

โดย เราสามารถกำหนดกฏตรวจสอบ การบันทึกรายการค้า ด้วยเงื่อนไงนี้

[ Sum of Debit (Amount) = Sum of Credit (Amount) ]

ตัวอย่าง 2: ธุรกิจซื้อสินค้ามาเพื่อขาย จำนวน 10 ชิ้น รวมเป็นเงินทั้งหมด 10000 บาท โดยกู้เงินมาซื้อ

ตัวอย่างนี้ กระทบ บัญชีหนี้ (201) และ บัญชีสินค้าคงเหลือ (121)

Code 121: บัญชีสินค้าคงเหลือ

Debit Credit
ซื้อสินค้า 10 ชิ้น 10000

Code 201: บัญชีเจ้าหนี้

Debit Credit
กู้ยืมซื้อสินค้า 10000

เมื่อเก็บลง Data Model จะได้แบบนี้

TransactionCode Account ID Code AccountType EntryID Amount EntryType Description
IV-2 4 121 Assets 5 10000 Debit ซื้อสินค้า 10 ชิ้น
IV-2 5 201 Liabilities 6 10000 Credit กู้ยืมซื้อสินค้า


ตัวอย่างที่ 3:
จากตัวอย่างที่ 2 มีการขายสินค้า จำนวน 2 ชิ้น

ได้ เป็นเงินสด โดยที่ตั้งขายไว้ ชิ้นละ 1500 บาท บัญชีที่กระทบ มีดังนี้ บัญชีรายรับ (311), บัญชีเงินสด (101), บัญชีต้นทุนสินค้า (321), บัญชีสินค้าคงเหลือ (121)

Code 101: บัญชีเงินสด

Debit Credit
ขายสินค้า 2 ชิ้น 3000

Code 311: บัญชีรายรับ

Debit Credit
ขายสินค้า 2 ชิ้น 3000

Code 321: บัญชีต้นทุนสินค้า/บริการ

Debit Credit
ขายสินค้า 2 ชิ้น 2000

Code 121: บัญชีสินค้าคงเหลือ

Debit Credit
ขายสินค้า 2 ชิ้น 2000

ข้อมูลเก็บลง Data Model จะมีลักษณะแบบนี้

TransactionCode Account ID Code AccountType EntryID Amount EntryType Description
REV-1 1 101 Assets 7 3000 Debit เงินสดรับ
REV-1 6 311 Equity 8 3000 Credit ขายสินค้าได้ 2 ชิ้น
REV-1 7 321 Equity 9 2000 Debit ต้นทุนสินค้า 2 ชิ้น
REV-1 4 121 Assets 10 2000 Credit ต้นทุนสินค้า 2 ชิ้น

ตัวอย่างที่ 4: ลูกค้าซื้อสินค้า 3 ชิ้น ราคา 4500 บาท มีค่าขนส่งอีก 100 บาท ผ่านออนไลย์ ชำระผ่านบัตรเครดิต

บัญชีที่กระทบ บัญชีรายรับ (311), บัญชีลูกหนี้ (111), บัญชีต้นทุนสินค้า (321), บัญชีสินค้าคงเหลือ (121), บัญชีเจ้าหนี้ (201)

Code 111: บัญชีลูกหนี้

Debit Credit
ขายสินค้า 3 ชิ้น บวก ค่าขนส่ง 4600

Code 311: บัญชีรายรับ

Debit Credit
ขายสินค้า 3 ชิ้น 4500
ค่าขนส่ง 100

Code 321: บัญชีต้นทุนสินค้า

Debit Credit
ขายสินค้า 3 ชิ้น 3000
ค่าขนส่ง 100

Code 121: บัญชีสินค้าคงเหลือ

Debit Credit
ขายสินค้า 3 ชิ้น 3000

Code 201: บัญชีเจ้าหนี้

Debit Credit
ค่าขนส่ง 100

ข้อมูลเก็บลง Data Model จะมีลักษณะแบบนี้

TransactionCode Account ID Code AccountType EntryID Amount EntryType Description
REV-2 1 111 Assets 11 4600 Debit ขายสินค้า 3 ชิ้น บวก ค่าขนส่ง
REV-2 6 311 Equity 12 4500 Credit ขายสินค้า 3 ชิ้น
REV-2 6 311 Equity 13 100 Credit ค่าขนส่ง
REV-2 7 321 Equity 14 3000 Debit ขายสินค้า 3 ชิ้น
REV-2 7 321 Equity 15 100 Debit ค่าขนส่ง
REV-2 4 121 Assets 16 3000 Credit ขายสินค้า 3 ชิ้น
REV-2 5 201 Equity 17 100 Credit ค่าขนส่ง

มีธุรกรรมขายสินค้ามา พอสมควรแล้ว ลองสร้างรายงานจาก Data Model ของเราดูครับ ข้างล่างนี้เป็นตัวอย่าง สรุปรายงานขาย

มูลค่าขายรวม: 7600 บาท

ต้นทุนขายรวม: 5100 บาท

กำไรสุัทธิ: 2500 บาท

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

ตัวอย่าง 5: ลูกค้านำเงินสดมาฝาก 100000 บาท

บัญชีที่กระทบ  บัญชีเงินสด (101),  บัญชีเจ้าหนี้ (201)

TransactionCode Account ID Code AccountType EntryID Amount EntryType Description
DEP-1 1 101 Assets 18 100000 Debit ฝากเงิน
DEP-1 5 201 Liabilities 19 100000 Credit ฝากเงิน

ตัวอย่าง 6: ธนาคารปล่อยกู้ให้ลูกค้าจำนวน 100000 บาท โอนเงินเข้าบัญชีลูกค้า

บัญชีที่กระทบ  บัญชีลูกหนี้ (111), บัญชีเจ้าหนี้ (201)

TransactionCode Account ID Code AccountType EntryID Amount EntryType Description
LON-1 8 111 Assets 20 100000 Debit กู้เงิน
LON-1 5 201 Liabilities 21 100000 Credit โอนเงินเข้าบัญชี

ตัวอย่าง 7: ธนาคารจ่ายดอกเบี้ยเงินฝากประจำเดือน 1 จำนวน 1000 บาท ตัดผ่านระบบ

บัญชีที่กระทบ บัญชีต้นทุนสินค้า/บริการ (321), บัญชีเจ้าหนี้ (201)

TransactionCode Account ID Code AccountType EntryID Amount EntryType Description
INT-1 7 321 Equity 22 1000 Debit ดอกเบี้ยเงินฝาก
INT-1 5 201 Liabilities 23 1000 Credit ดอกเบี้ยเงินฝาก

ตัวอย่าง 8: ธนาคารรับชำระเงินจากลูกค้าเงินกู้งวดที่ 1 คิดเป็นเงินต้น 8000 บาท และดอกเบี้ย 2000 บาท ด้วยเงินสด

บัญชีที่กระทบ บัญชีเงินสด (101), บัญชีลูกหนี้ (111), บัญชีรายรับ (311), บัญชีต้นทุนสินค้า/บริการ (321)

TransactionCode Account ID Code AccountType EntryID Amount EntryType Description
RELON-1 1 101 Assets 24 10000 Debit ชำระเงินกู้งวด 1
RELON-1 6 311 Equity 25 8000 Credit เงินต้น
RELON-1 6 311 Equity 26 2000 Credit ดอกเบี้ย
RELON-1 7 321 Equity 27 8000 Debit หักยอดลูกหนี้
RELON-1 8 111 Assets 28 8000 Credit หักยอดลูกหนี้

อธิบาย: รายการค้าที่ 24 รับชำระมาเป็นเงินสด 10000 จึง Debit บัญชีเงินสด โดย แยกรับเป็น เงินต้น 8000 และ ดอกเบี้ย 2000 ดังนั้นจึงต้อง Credit ที่ บัญชีรายรับ ของรายการค้าที่ 25, 26 ส่วนรายการค้าที่ 27 และ 28 เป็นปรับลดยอดลูกหนี้ อีก 8000 สำหรับลูกค้าคนนี้

แถมให้อีกโมเดลก็แล้วกัน ตัวอย่างต่อไปนี้เป็น ธุรกรรมการค้าของโมเดลธุรกิจประกันภัย

ตัวอย่าง 9: ลูกค้ามาซื้อกรมธรรม์ประกันภัย จ่ายเบี้ยมูลค่า 1000 บาท ด้วยเงินสด คุ้มครองทุกเรื่องเป็นระยะเวลา 1 เดือน ด้วยทุนเอาประกันจำกัดไว้ที่ 100000 บาท

บัญชีที่กระทบ บัญชีเงินสด (101), บัญชีรายรับ (311), บัญชีสินค้า/บริการ คงเหลือ (121), บัญชีเจ้าหนี้ (201)

TransactionCode Account ID Code AccountType EntryID Amount EntryType Description
SPOLI-1 1 101 Assets 29 1000 Debit ขายกรมธรรม์ประกันภัย
SPOLI -1 6 311 Equity 30 1000 Credit ขายกรมธรรม์ประกันภัย
SPOLI -1 4 121 Assets 31 100000 Debit กรมธรรม์ประกันภัย
SPOLI -1 5 201 Liabilities 32 100000 Credit ทุนเอาประกัน

อธิบาย: รายการค้าที่ 29 รับเงินสดเข้ามา จึง Debit บัญชีเงินสด ไป 1000 เนื่องจากเป็นรายการขาย เป็นรายรับ จึงต้อง Credit บัญชีรายรับด้วย อีก 1000 สำหรับรายการค้าที่ 31, 32 เป็นการสร้างสิทธ์ ซึ่งเป็นสัญญากรมธรรม์ประกันภัย ว่าจะคุ้มครอง (Coverage) ด้วยเหตุใดๆแล้วแต่ตกลง ด้วยทุนเอาประกัน หรือ สามารถเรียกร้องค่าเสียหายได้สูงสุด ไม่เกิน 100000 ในระยะเวลา 1 เดือน สำหรับตัวข้อมูลระยะเวาลนี้ จะเก็บไว้ใน Data Model สำหรับ กรมธรรม์ประกันภัย (Policy) จะไม่แสดงให้ดู

ตัวอย่าง 10: ลูกค้าเรียกร้องค่าสินไหมทดแทน (Claim) ด้วยค่าเสียหาย 500 บาท จ่ายเงินสด

บัญชีที่กระทบ บัญชีต้นทุนสินค้า/บริการ (321), บัญชีเงินสด (101), บัญชีสินค้า/บริการ คงเหลือ (121), บัญชีเจ้าหนี้ (201)

TransactionCode Account ID Code AccountType EntryID Amount EntryType Description
CLM-1 7 321 Equity 33 500 Debit เรียกร้องค่าสินไหมทดแทน
CLM-1 1 101 Assets 34 500 Credit เรียกร้องค่าสินไหมทดแทน
CLM-1 5 201 Liabilities 35 500 Debit คุ้มครอง
CLM-1 4 121 Assets 36 500 Credit คุ้มครอง

ตัวอย่าง 11: กรมธรรม์ประกันภัยหมดเวลาคุ้มครอง ใช้ทุนไป 500 เหลือทุนเอาประกันที่หมดเวลา 99500

บัญชีที่กระทบ บัญชีสินค้า/บริการ คงเหลือ (121), บัญชีเจ้าหนี้ (201)

TransactionCode Account ID Code AccountType EntryID Amount EntryType Description
EPOLI-1 7 321 Equity 37 99500 Debit สิ้นสุดความคุ้มครอง
EPOLI-1 1 101 Assets 38 99500 Credit สิ้นสุดความคุ้มครอง

Code แสดงไว้ที่นี่ครับ SourceCode

มันก็ดูยากพอสมควรนะครับผมคิดว่า ก็ไปศึกษาเพิ่มเติมในหลักการบัญชีเบื้องต้น แล้วนำไปออกแบบระบบดูนะครับ มันมีประโยชน์มาก ถึงแม้ว่าจะยาก แต่มันก็คุ้ม และจบปัญหาต่างๆได้แน่นอนครับ

อ่านเพิ่มเติม

“Think like Accountant, Do like Programmer”

ขอบคุณครับ

#:P

#accounting, #data-model, #ddd, #domain-model

Continues Delivery: ทำ Artifact repository ง่ายๆ ด้วย Artifactory ครับผม

สวัสดีครับ

ก็พอมีเวลาว่าง และกำลังทำเรื่องเกี่ยวกับ Continues Delivery (CD) ก็มานั่งเขียนแชร์เครื่องมือ ง่ายๆ ที่เป็นส่วนหนึ่งในการทำ CD นั่นก็คือ artifacts repositories หรือ ที่เก็บ สิ่งที่ทีมพัฒนาขึ้น มีความพร้อมใช้ประโยชน์ได้ หรือพร้อมบริการได้ เช่น ซอฟแวร์, program, application, library, เอกสารคู่มือการใช้ เป็นต้น ที่ว่ามีความพร้อมใช้ประโยชน์ คือ ไม่มีการนำไป ต่อเพิ่มเติมอีกแล้ว คือเป็นสิ้นสุดของชิ้นงาน นำไปใช้ประโยชน์ได้เลย เป็น finished goods

สำหรับตัวอย่างนี้ ผมใช้ server ที่ชื่อว่า Artifactory ใช้เก็บ ตัวชิ้นงาน เป็นโปรดักส์ซอฟแวร์ง่ายๆ คือ Hello Artifactory โดยจะแนะนำ การ download file artifacts ที่เป็น exe Hello.Artifactory.App ง่ายๆนี้

ก่อนจะเริ่มลงมือทำ ก็มารู้ที่มาของการ สร้าง artifact repository กันก่อน เจ้า artifact repository เริ่มต้นมาจาก ปัญหาการ build ซอฟแวร์ แล้วจะไปวางไว้ที่ไหน เพื่อให้การ deploy หา ซอฟแวร์ที่ build เรียบร้อยพร้อมใช้แล้ว ค้นหาได้ง่าย

สมัยแรกๆ เราก็ใช้แชร์ folder กัน เราก็ต้องทำ copy เอง จัดการ harddisk เอง backup เอง ซึ่งวุ่นวาย ยุ่งยาก แถมน่าเบื่อ มันก็เลย เกิด server ชนิดนี้ขึ้นมา เพื่อจัดการ path ของ artifacts, backup/restore, จัดการ version, กระจายการ load และ อื่นๆอีก ซึ่งก็ สะดวกขึ้นมาก เมื่อมี artifacts repository จัดการให้เสร็จ

ก็มาถึงแนวคิด CD ที่จำเป็นต้องอาศัย artifacts repository นี้ deploy artifacts เพื่อจุดประสงค์ต่างๆในขั้นตอน หรือ phase การพัฒนาซอฟแวร์ ตามภาพ ข้างล่าง ซึ่งเขาจะเรียกกันว่า Delivery pipeline (ตัดจากหนังสือ Continuous Delivery)

อธิบายจากภาพ มันประกอบด้วยกล่อง Version control เช่น Git, SVN, TFS, Etc คือที่ใช้เก็บ code หรือ file ต่างๆ ที่ทีมกำลังพัฒนาอยู่ มีการเปลี่ยนแปลง แก้ไขตลอดเวลา แน่นอนไม่มีความพร้อมใช้ประโยชน์ได้

ส่วนกลุ่ม 5 กล่องตรงกลาง ได้แก่ Commit stage, Acceptance stage, UAT, Capacity stage, Production คือสถานะ ของทุกชิ้นงานทั้งหมด ที่ประกอบเป็นโปรดักส์ หรือ โปรเจ็ค ว่าอยู่ในขั้นตอนไหน เช่น Commit stage คือ โปรดักส์ อยู่ในขั้นตอนการ วิเคราะห์, code, review code, refactor, unit test ก็ว่ากันไป ตัวชิ้นงานทั้งหมด  หลังจากผ่าน commit stage แล้ว (code ทั้งหมดที่ build เสร็จจะได้ artifacts ส่วน code จะเก็บไว้ที่ version control) ก็จะถูกเก็บไว้ที่ artifact repository เพื่อไปยัง stage หรือ phase ต่อไป คือ Acceptance stage ถ้าผ่าน artifacts ทั้งหมดก็จะไป ขั้นต่อไป ตามลำดับ จนจบ เรียกส่วนนี้ว่า pipeline

และถ้าไม่ผ่านขั้นตอนไหน artifacts ตัวนั้นก็จะไม่สมบูรณ์ ถือว่าไม่ผ่าน ใช้ประโยชน์ไม่ได้ ก็กลับไปที่ขั้นตอน แรก คือ Commit stage งานต่างๆใน version control ก็จะถูกแก้ไข จนผ่าน Commit stage ก็จะถูกจัดเก็บไว้ใน artifacts repository เป็นเวอร์ชั่นใหม่ ส่งต่อไปยัง stage ต่อๆไป จนสุดที่ deploy production ทั้งหมดนี้คือการทำ Continues Delivery

เอาละ ผมจะแสดงตัวอย่าง pipeline ง่ายๆสำหรับตัวอย่าง Hello.Artifactory.App เลยละกัน ผมจะแสดงการทำให้ภาพข้างล่างนี้ ให้เกิดขึ้นให้ดู

เริ่มต้น ติดตั้ง Artifactory

  1. donwload Artifactory ที่ https://www.jfrog.com/open-source/ เป็นตัว open source version ผมใช้ windows OS download ตัว ZIP (jfrog-artifactory-oss-5.1.4.zip) ครับ
  2. แตก file zip จะแสดงโครงสร้าง folder ดังนี้

  1. เข้าไปที่ folder bin แล้ว click ขวาที่ file installService.bat เลือก Run as administrator ดูรูป

  1. ลงเสร็จแล้ว ต้อง run services เองครับ เข้าไปที่ start search programs and file พิมพ์ services  กดเลือกไปที่ service name Artifactory click ขวา แล้วเลือก start ครับ ดูรูป

ติดตั้ง artifactory เสร็จแล้ว ลองทดสอบครับ เปิด browser แล้วไปที่ http://localhost:8081 มันจะเข้าหน้า จัดการ artifactory แบบรูปนี้

ปิดหน้าจอ Welcome to … สวยๆนี้ไปก่อนครับ

กดเข้าไปที่ menu Login ด้านบนสุดขวามือ จะ popup form ให้เรา Login เข้าระบบ ก็พิมพ์ Username *: admin และ Password *: password กดปุ่ม Login

พอเข้ามาแล้วให้ไปที่ menu ด้านซ้าย เลือกที่ icon ตามรูปครับ

จากรูป จะเห็น repository ตัวอย่าง example-repo-local ครับ ผมจะใช้ repository อันนี้ล่ะทำให้ดู ขั้นต่อไปก็ติดตั้งเครื่องมือ สำหรับ พัฒนาซอฟแวร์ครับ ผมใช้ Visual studio community

ติดตั้ง Visual studio community

Download และติดตั้งได้ที่ https://www.visualstudio.com/downloads/ เลือกติดตั้ง version ไหนก็ได้ครับ ตัวอย่างผม version เก่าหน่อย ผมแค่ไว้แสดงแนวคิดการใช้ artifact repository ครับ จะใช้เครื่องมืออะไรพัฒนา app ก็ได้

มีเครื่องมือสร้างพัฒนาซอฟแวร์แล้ว ก็เริ่มลงมือพัฒนาต่อเลย

พัฒนา Hello.Artifactory.App

1. สร้าง project เป็น Console Application ง่ายๆครับ ตามภาพ

2. เขียน code กำหนดให้เป็น version แรกครับผม ดูรูป

3. build projects แล้วลองเล่น app ดูครับ เข้าไปที่ bin/debug folder ของ projects นี้แล้ว กด double click ที่ Hello.Artifactory.App.exe จะแสดงตามรูปนี้

OK มั่นใจว่าทำงานได้ถูกต้องแล้ว ก็ deploy ไปยัง Artifactory เลยครับ ทำตามขั้นตอน ดังนี้

1. ไปที่ http://localhost:8081 แล้วlogin เข้าไปก่อนครับ (ถ้ายัง login ค้างอยู่ก็ไม่ต้อง login ใหม่แล้ว)

2. กดที่ menu Artifact Repository ด้านข้าง แล้วกด Deploy ครับ ดูรูป

3. เลือก Deploy จะขึ้นหน้าจอ ให้เลือก file deploy ให้ browse file Hello.Artifactory.App.exe ใน projects bin/debug ของเรา แล้ว check เลือก Deploy According To Layout ใส่ข้อมูล Layout Tokens

ดังนี้

orgPath ผมใส่ chavp คือ ชื่อบริษัทผม

module  เป็นชื่อ app หรือ component หรือ service สรุปคือเป็นชื่อ ของชิ้นงานที่พร้อมใช้ประโยชน์ได้แล้ว ผมใส่ hello-artifactory-app

baseRev คือ version ของ app ที่เราจะ release ผมใช้การตั้งแบบ <major>.<minor>.<patch>

โดย <major> คือ รหัสกลุ่มของ feature หลัก , <minor> รหัสกลุ่มของ feature เพิ่มเติมลงมา โดย จะ feature จะ ใช้งานได้กับ <major> ที่มันอยู่ ซึ่งจะสามารถ deploy ย้อนหลังได้เช่น ตอนนี้เป็น 1.5 เราสามารถ ใช้ร่วมกับ version 1.4, 1.3 ได้ แต่ถ้าตอนนี้เป็น 2.1 แล้ว เราจะไม่สามารถย้อนไปใช้ 1.9 ได้ แบบนี้ และ

<patch> คือ รหัสที่เราแก้ bug สำหรับ <minor> และ <major> ที่เรา release ไป เช่นตอนนี้ 1.5.0 ปล่อยไปเรามี bug ก็แก้ไข แล้วตั้งเป็นรหัส 1.5.1, 1.5.2 แบบนี้เป็นต้น

(อ่าน Semantic Versioning เพิ่มเติม)

ใส่ตามภาพ ไปก่อนครับ

ใส่ข้อมูลครบแล้ว กด Deploy เสร็จแล้วจะแสดงโครงสร้าง artifactory ดังภาพข้างล่างนี้ครับ

หลังจาก deploy เสร็จแล้ว stage ต่อไป ก็คือ <<acceptance stage>> ตามภาพ ก่อนอื่นเราต้อง install Hello.Artifactory.App.exe ไปยังเครื่องที่ทำ acceptance test

ผมจะพัฒนา app อีกตัวหนึ่งขึ้นมา เพื่อ download artifact Hello.Artifactory.App.exe มาติดตั้ง ครับ โดยจะเขียน client rest api เรียก ใช้ Web API ของ Artifactory download app  Hello.Artifactory.App.exe มาไว้ที่เครื่อง เพื่อเล่นทดสอบ

พัฒนา app ช่วย install 

1. เปิด visual studio สร้าง project Chavp.Get เป็น console application ตามภาพครับ

 

2. ไปที่ Tools เลือก Nuget package manager console แล้วติดตั้ง

Install-Package Appccelerate.CommandLineParser

3. ติดตั้ง Rest Client เพื่อใช้เรียก WEB Api ครับ ผมใช้ RestSharp ติดตั้งครับ

Install-Package RestSharp

4. เขียน code ตามข้างภาพข้างล่างนี้ ลงไป ที่ main app กับ

อ่าน code จากภาพ

static string ArtsRepoUrl คือ artifactory server หรือที่เก็บ ชิ้นงานที่ใช้ประโยชน์ได้ ของเราครับ

static string ProgramsFolder คือ ที่วาง artifact หรือ program ผมวางไว้ที่ drive C:\Program Files\chavp\hello-artifactory-app

static string HelloAppName คือ ชื่อ app ตอนนี้รับคำสั่ง install ได้แค่ app hello.artifactory.app แค่อันเดียวครับ

ผมจะขอผ่าน การอธิบายส่วนของ package Appccelerate.CommandLineParser ไป ข้ามไป อธิบาย จุดที่มีการ เรียก REST Api เลยละกันครับ ดู code ในภาพต่อไป

ตัวแปร var artPath คือ นำเอา version ที่ต้องการ install มาต่อกับ URI หรือ path ของ app ที่เก็บอยู่บน server artifactory ครับ โดย copy มาจาก link ตามภาพ

กด Copy path to clipboard แล้วนำไปวางหลัง artifactory ได้เลยครับ โดย ดู URI การใช้งาน WEB REST API บนเวป ได้ที่นี่ https://www.jfrog.com/confluence/display/RTF/Artifactory+REST+API#ArtifactoryRESTAPI-ArchiveEntryDownload

หลังจาก build เราจะได้ exe ของ app install มา ก็ลองใช้ Chavp.Get เพื่อ install app กันเลยครับ

ไปที่ windows start search  programs and files พิมพ์ cmd แล้ว cd ไปที่ folder app Chavp.Get ครับ ผม build project Chavp.Get แล้วเอา bin\debug ไปวางไว้ที่ C:\Program Files\chavp\chavp-get ตามภาพครับ

โครงสร้าง app Chavp.Get ดูภาพ

พิมพ์ Chavp.Get แล้ว ใส่ option –a hello.artifactory.app และ –v 1.0.0 ครับ แลวกด enter app chavp.get ก็จะ download app Hello Artifactory แล้ว ติดตั้งไว้ที่ folder C:\Program Files\chavp ตาม code ที่เราเขียนไว้ เสร็จครับ ดูภาพ

ทีนี้ acceptance test ก็จะเข้าไปที่ folder app C:\Program Files\chavp\hello-artifactory-app แล้วทดสอบ app ดูได้แล้วครับ

ผลปรากฏว่า โปรแกรมเมอร์ เขียนแสดง message ไม่ถูกต้อง คือ

                Hello, Artifac!

ซึ่ง ที่ต้องการ คือต้องแสดง

                Hello, Artifactory!

ก็ แจ้งให้ โปรแกรมเมอร์ กลับไปแก้ ไข code ครับ กลับไปแก้ไข code แล้ว deploy ใหม่ เปลี่ยนเป็น version 1.0.1 ครับ ดูภาพ หลัง deploy version 1.0.1

หลังจากนั้น ก็ install app โดยผ่าน Chavp.Get อีกที ทีนี้ใส่ version เป็น 1.0.1 นะครับ พอเล่น app อีกทีก็จะแสดงได้ ถูกต้องแบบนี้ครับ

เข้าไปที่ folder app C:\Program Files\chavp\hello-artifactory-app กด double click ที่ file hello.artifactory.app.exe จะแสดงตามรูปภาพนี้

Ok เห็น ข้อความว่า Hello, Artifactory! ตามต้องการแล้ว

นั่นก็หมายความว่า ชิ้นงานนี้ของเราก็พร้อม install ที่ stage production ได้แล้วใช่มั้ยครับ

สำหรับงานด้าน delivery products ยังมีงานให้ทำอีกเยอะเลยละครับ ผมก็ขอใช้เวลาน้อยๆ นำเสนอไว้เพียงแค่นี้

หวังว่าบล็อคนี้ จะเป็นจุดเริ่มต้นของการทำ Continues Delivery ให้ได้สักคนหนึ่งนะครับ

ขอให้ผู้หลงไหลในการสร้างโปรดักส์ทุกท่านจงโชคดี…

SoureCode: hell-artifactory-app

ขอบคุณครับ

#:P

มีความ “ว่างง่าย”

“ว่างง่าย”เมื่อ เข้าใจหนึ่ง ให้รับรู้ว่าทุกสิ่งที่เราฟัง, อ่าน, เห็น, คิด, สัมผัส, ลิ้มรส นี้เป็นเพียงความรู้… เข้าใจสอง การแสดงผล เช่น รู้สึกสุข ทุกข์, เฉยๆ, ชอบใจ, ไม่ชอบใจ, พูด, ไม่พูด, ลงมือทำ, ไม่ทำ นี้เป็นเพียงการปฏิบัติ หรือการแสดงออกที่มีผล และ เข้าใจสาม คือ จดจ่อเรื่องเดียว, ไม่จดจอเรื่องเดียว, คิดอยู่เรื่องเดียว, คิดปนกันหลายเรื่อง นี้เป็นเพียงสภาวะของจิต… เมื่อแยกเข้าใจว่า อะไรคือ ความรู้, การปฏิบัติ และสภาวะของจิต ได้อย่างตลอดเวลาแล้ว… เราเรียกสภาวะอย่างนี้ว่า “ว่างง่าย” ….

#:P

สำเร็จ 100k ที่ โป่งแยงเทรล 2016 (PYT100)

สวัสดีครับ

บล็อกนี้ผมจะมาเล่าประสบการณ์วิ่งเทรล 100 กิโลเมตร สำเร็จครั้งแรกที่โปงแยงเทรล 2016

ก่อนจะมาสำเร็จงานนี้ ผมก็ไปล้มเหลวมา 3 สนามแล้ว หรือ ที่เรียกว่า Did Not Finish (DNF)

DNF สนามแรก: The North Face 100 (หรือ TNF100) ปี 2016 ผมวิ่งครึ่งแรกได้ดีกว่าครั้งที่แล้ว เพราะมีประสบการณ์วิ่งเทรลมากขึ้น ผ่าน 50 กิโลเมตรมาได้อย่างสบายๆ แต่สุดท้ายแรงไปหมดที่ กิโลเมตรที่ 70 ผมไม่สามารถไปต่อได้จริงๆ ยอมยกเลิกการแข่งขันที่ check point นั้น … ผมได้ประสบการณ์จากความรู้สึก ที่หมดแรง ร่างกายอ่อนล้า อย่างแท้จริงจากการแข่งครั้งนี้ มันเป็นความรู้สึกคล้ายๆกับคนเป็นไข้ที่ต้องนอนซมอยู่ใต้ผ้าห่ม แต่ดันมาอยู่บนสนามวิ่งบนพื้นดิน และจะต้องวิ่งต่อไปอีก 30 กิโลเมตร มันยากเหลือเกินที่จะไปต่อได้ ยอมแพ้ดีกว่า… ผมไม่ค่อยเสียใจเท่าไร เพราะยอมรับว่า ซ้อมมาน้อย เตรียมตัวมาไม่ดีพอ

DNF สนามที่สอง: Ultra trail koh chang (หรือ UTKC) ปี 2016 ผมลงแข่ง 66 กิโล จาก DNF สนามแรก ที่ผมหมดแรง จึงซ้อมวิ่งระยะยาวมาอย่างต่อเนื่อง… ผมมาถูก cutoff ที่กิโลเมตรที่ 35 ทั้งๆที่มีแรงเหลืออยู่ แต่ก็ไม่สามารถไปต่อได้… เกมก็คือเกม ยอมรับความพ่ายแพ้ไป… สนามนี้ทำให้ผมเรียนรู้ว่า จะต้องฝึกให้แข็งแกร่งกว่านี้ จึงเริ่มต้น การฝึกกล้ามเนื้อที่ต้องใช้ในสนามเทรล… ผมจึงแบ่งเวลาเล่นเวทเพิ่มขึ้น แทนที่จะวิ่งอย่างเดียว

DNF สนามที่สาม: Vietnam Mountain Marathon (หรือ VMM) ปี 2016 ผมลงแข่ง 100 กิโล จาก DNF สนามสอง ที่ผมได้เรียนรู้และต้องแบ่งเวลามาเล่นเวท… ผมเล่นเวท ทั้งหมด 3 ท่า ท่าละ 1 เซ็ต ทุกวัน คือ 1. แพลงกิ้ง 1:30 นาที, 2. สควอท 30 ครั้ง และ 3.  ดิพ 20 ครั้ง… มาใช้กับการแข่งครั้งนี้ ปรากฏว่าได้ผลมาก การขึ้นเขา, ลงเขา ผมดีขึ้นอย่างเห็นได้ชัด แต่ก็ปรากฏว่า ยังแข็งแกร่งไม่พอสำหรับการพิชิตสนามนี้ได้ครับ ไปโดน cutoff ที่กิโลเมตรที่ 35… ก็เสียใจนะ แต่ดีใจมากกว่าที่รู้ว่าการเล่นเวทเพิ่มเข้าไปของเรานั้นมีประสิทธิผลอย่างมาก แค่มันน้อยไป ต้องฝึกเพิ่มอีก

OK จากความล้มเหลวทั้งสามสนาม ทำให้ผมเรียนรู้ว่า จะวิ่งเทรล ให้ผ่านคือ หนึ่ง ความฟิตต้องพร้อม และ สอง ความแกร่งต้องถึง เอาละ สนามต่อไปผมจะต้อง ฟิตพร้อม และ แกร่งถึง ให้พอสำหรับการพิชิตระยะ 100k นี้ให้ได้

ผมจึงกลับมาพัฒนาเวทเทรนนิ่งอีก คือ

  1. แพลงกิ้ง 2:30 นาที
  2. สควอท 200 ครั้ง แบ่งเป็น 4 เซต เซตละ 50 ครั้ง
  3. ดิพ 60 ครั้ง แบ่งเป็น 3 เซต เซตละ 20 ครั้ง

ทำ 3 ท่านี้ทุกวัน และก็ออกไปวิ่งเฉลี่ย วันละ 20 กิโล โดยในหนึ่งอาทิตย์จะมีวันวิ่งยาว 40-50 กิโล ในวันหยุด การวิ่งนั้นผมจะพยายามวิ่งให้ได้ 3 วันต่อเนื่องกัน แล้วพักหนึ่งวัน เวทเทรนนิ่งทำทุกวัน

ในที่สุดผมก็สามารถเอาชนะ 100 กิโลเมตรที่สนาม Pong yang trail (หรือ PTY100) ปี 2016 ได้สำเร็จสักที (นี่เป็นลิงค์ข้อมูลวิ่งครับ คลิกเลย)

เป้าหมายสูงสุดตอนนี้ของผมก็คือ การพิชิตเทรล 100 ไมล์ หรือ 160 กิโลเมตรให้ได้

จริงๆผมเป็นคนที่ชอบ DNF … เพราะมันทำให้ผมเรียนรู้ในหนทางเพื่อที่จะเอาชนะมันให้ได้… อีกอย่างหนึ่งที่ผมสนใจก็คือ อันดับ… อันดับ มันทำให้ผมรู้สึกว่า เรานั้น ยังมีพื้นที่ให้พัฒนาเพิ่ม ให้ฝึกเพิ่มขึ้นได้อีกเยอะ

สำหรับกีฬาวิ่งเทรลนี้ ผมบอกคุณได้คำเดียวว่า สนุก และ ผมอยากให้คุณโดน 😉

ขอบคุณครับ

#:P

C#.NET: คิดแบบขนาน, แก้ปัญหาแบบขนาน (Think like parallel, act like parallel)

สวัสดีครับ 

ทิ้งระยะนานมาก กลับมาเขียนบล็อคทีหนึ่ง บล็อคนี้ก็มานำเสนอ โปรแกรมเมอร์ หรือนักแก้ปัญหาทั้งหลายให้มาคิดแก้ปัญหาแบบขนาน แต่งเป็นหัวข้อว่า “คิดแบบขนาน, แก้ปัญหาแบบขนาน” (Think like parallel, act like parallel)

ตัวอย่าง ผมขอใช้ภาษา C#.NET version 4 ขึ้นไปครับ

คำว่าขนาน ในที่นี้ก็ คือ การออกแบบงานให้สามารถทำไปพร้อมๆกัน หรือขนานกันได้ ดูภาพ (001-concept.png)

001-concept

จากภาพ เส้นบนสุด t คือเส้นเวลา กล่องสีฟ้าๆ คือ เนื้องาน ที่ต้องทำเพื่อใช้แก้ปัญหา ปัญหาในที่นี้ เช่น งานที่ต้องทำเพื่อส่งมอบของตามความต้องการ, การคํานวณตัวเลขเพื่อใช้แก้ปัญหา หรือตั้งค่าบางอย่างให้เครื่องจักรทำงานผลิต เป็นต้น

การออกแบบงานแบบ ผมแบ่งกรอบให้คิด ออกเป็น 2 ขั้นตอน คือ

1- วางแผนแบ่งแยก (Plan partitioning)

เป็นขั้นตอนวิเคราะห์ปัญหา ประกอบไปด้วยสองส่วนหลักที่ต้องวิเคราะห์เพื่อแยกแยะออกมาให้ครบถ้วน คือ โครงสร้างข้อมูล (Data structure) และขั้นตอนวิธีแก้ปัญหา (Algorithm)

โครงสร้างข้อมูล (Data structure) ต้องวิเคราะห์ข้อมูลให้อยู่ในรูปแบบที่ สามารถแบ่งแยกเป็นอิสระจากกันได้ คือ จะไม่มีการแชร์ หรือ ใช้ข้อมูลใดๆร่วมกัน

ขั้นตอนวิธีแก้ปัญหา (Algorithm) ขั้นตอนวิธี ซึ่งประกอบไปด้วย งานแมพ (Map) และงานลดค่า (Reduce) โดย

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

งานลดค่า คือขั้นตอนวิธีการรวม คำนวณค่า หรือ ก็คือการสรุปข้อมูลให้ออกมาเป็นผลลัพธ์ตามต้องการ

2- ทำแบบขนาน (Do parallel)

เป็นขั้นตอน execute [1] งานในแบบขนาน หรือทำหลายๆงานไปพร้อมกัน งานที่ว่าก็คืองานที่เราวิเคราะห์ แล้วแบ่งแยกได้แล้วจากขั้นตอนแรก เพื่อให้ได้ผลเฉลยของปัญหาตามต้องการ

ตัวอย่าง: จงคํานวณผลรวมของ function foo(bar) = bar * bar + bar + 1 ตั้งแต่ bar = 1 ถึง 3,000,000

เขียน code ตัวงานได้เป็น

long foo(long bar)
{

return bar * bar + bar + 1;

}

[1] execute ก็คือ การทำงานของบางสิ่งบางอย่างตามชุดคำสั่งที่เรากำหนดไว้ ในที่นี้ ชุดคำสั่งที่เรากำหนดเขียนด้วย code C# จากนั้นนำไปให้เครื่องคอมพิวเตอร์ทำงานตามชุดคำสั่ง หรือ execute คำสั่งให้เรานั่นเอง

ผมจะเริ่มจาก ทำแบบเป็นลำดับตรงๆ คือการทำงานแบบปกติก่อน หลังจากนั้น ผมจะนำเสนอการแก้ปัญหาแบบ คิดแบบขนาน, แก้ปัญหาแบบขนาน ผมก็จะได้ผลลัพธ์ออกมาเป็น สองผลลัพธ์ เพื่อนำมาเปลียบเทียบกัน ให้ผู้อ่านได้เห็นภาพในแบบ ก่อน/หลัง (before/after) ได้

ทำแบบเป็นลำดับตรงๆ

var stopWatch = Stopwatch.StartNew();
var sum = Enumerable.Range(1, 3000000).Select(bar => foo(bar)).Sum();
Console.WriteLine(“Sum: {0}, Elapsed: {1}s”, sum, stopWatch.Elapsed);

ผลลัพธ์ ดูภาพ (001-result-1.png)

001-result-1

จากภาพ ผลลัพธ์ที่ต้องการเท่ากับ 9000000000001999999

ใช้เวลาไป 0.1504391 วินาที ถ้าอ้างอิงจากภาพ (001-concept.png) คือ t1 – t0 เท่ากับ 0.1504391 วินาที

ทำแบบขนาน

var stopWatch = Stopwatch.StartNew();
var sum = default(long);
var results = new List<long>(); // เตรียมข้อมูลไว้ใส่ผลลัพธ์ที่ผ่านขั้นตอน map
Parallel.ForEach(

Partitioner.Create(1, 3000000), // วางแผนแบ่งงาน
range =>
{

// งาน map

long r = 0;

// ข้อมูลถูกแบ่งด้วย Partitioner.Create เป็นส่วนๆ จาก Item1 ถึง Item2
for (int bar = range.Item1; bar < range.Item2; bar++)
{

r += foo(bar);

}
results.Add(r); // การ emit ข้อมูลที่ map เสร็จแล้วเพื่อส่งต่อไปงาน reduce

}

);
sum = results.Sum(); // งาน reduce
Console.WriteLine(“Sum: {0}, Elapsed: {1}s”, sum, stopWatch.Elapsed);

ผลลัพธ์ ดูภาพ (001-result-2.png)

001-result-2

จากภาพ ผลลัพธ์ที่ต้องการเท่ากับ 9000000000001999999 (ผลลัพธ์เท่ากับทำแบบเป็นลำดับตรงๆ)

ใช้เวลาไป 0.0602625 วินาที ถ้าอ้างอิงจากภาพ (001-concept.png) จากเครื่องของผู้เขียนเอง สามารถทำงานพร้อมๆกันได้สูงสุด 4 งาน ดังนั้นการวางแผนแบ่งงาน จึงสามารถแบ่งงานได้ 4 งานจากงานใหญ่

โดยใช้ class Partitioner สร้างงานให้ ผมจึงไม่จำเป็นต้องกำหนดขนาดของข้อมูลเพื่อแบ่ง partition เองก็ง่ายดี แสดงเป็น ภาพใหม่ได้ แบบบนี้ (001-concept2.png)

001-concept2

เมื่ออ้างอิงเวลาทำงานจากภาพใหม่ (001-concept2.png) ที่มี CPU ประมวลผลได้ 4 งานพร้อมๆกัน เวลาที่ใช้คือ t0.25 – t0 เท่ากับ 0.0602625 วินาที

สรุปได้ว่า คิดแบบขนาน และทำแบบขนานนั้นใช้เวลาน้อยกว่า คิดแบบเป็นลำดับตรงๆ ใช้เวลาน้อยกว่าเท่าไรนั้น ขึ้นกับจำนวน CPU ของเครื่องที่เราใช้ execute นั้นเอง ดังนั้น เราจำเป็นต้องเขียน code ให้สามารถทำงานแบบขนานให้ได้เสมอ จึงสามารถใช้ประโยชน์จากเครื่องที่มี CPU หลายๆตัวได้อย่างมีประสิทธิภาพสูงที่สุด… เรามา “คิดแบบขนาน, แก้ปัญหาแบบขนาน” กันเถอะครับ มันมีประโยชน์ดีนะ ฝากไว้ไปคิด ไปทำกันต่อไป

ขอบคุณครับ

#:P