DEV Community

Cover image for การเดินทางของ Software Engineer ขอบตาดำ ๆ 🐼
Akkarapon Phikulsri
Akkarapon Phikulsri

Posted on

การเดินทางของ Software Engineer ขอบตาดำ ๆ 🐼

สวัสดีครับผม วันนี้ไม่ได้มาเขียน Tutorial หรือสอนเขียนโค้ดอะไรเป็นพิเศษนะครับ ขอเปลี่ยนบรรยากาศมาเล่าเรื่องสบาย ๆ กันบ้าง...ไหมนะ >< และคาดว่าเนื้อหาจะกระโดดไปมาผสม ๆ หลายไอเดียในนี้นะครับ : ) เนื่องจากว่าทำเป็น draft ทิ้งไว้นานพอสมควรพึ่งมีเวลามาว่างเขียน ถือซะว่าส่งท้ายปี 2026 กันเลยทีเดียว

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

บันทึกการเดินทางของ Developer ขอบตาดำคนหนึ่ง ที่เริ่มต้นจากการเขียน Backend และค่อย ๆ เรียนรู้ว่าการสร้างซอฟต์แวร์มีอะไรให้คิดมากกว่าการเขียนโค้ดให้ทำงานได้

จุดเริ่มต้นจาก Backend Developer ธรรมดาคนหนึ่ง

ย้อนกลับไปช่วงต้นปี 2023 ตอนนั้นผมยังเป็นนักศึกษาจบใหม่ที่กำลังหาที่ฝึกงานอยู่เลยครับ (พูดเหมือนผ่านมาหลายสิบปี ทั้งที่เพิ่งไม่กี่ปีเอง ฮ่า ๆ)

ตำแหน่งที่ผมเลือกสมัครคือ Backend Developer เพราะเป็นสิ่งที่ตัวเองค่อนข้างถนัด และรู้สึกว่าน่าจะทำได้ดีที่สุดในตอนนั้น

ช่วงแรกผมเขียน Python กับ Django เป็นหลัก งานส่วนใหญ่คือการพัฒนา API ตาม ER Diagram ที่พี่ ๆ ในทีมออกแบบไว้ให้

โปรเจกต์แรก ๆ ที่ได้ทำเป็นระบบ Product Management ขนาดเล็ก เกี่ยวกับการจัดการข้อมูลสินค้าและ SKU งานหลักก็เป็น CRUD API เพื่อให้ทีม Frontend นำไปใช้งานต่อ

ตอนนั้นรู้สึกว่างานไม่ได้ยากมาก เพราะสมัยเรียนผมก็ฝึกเขียนโค้ดกับลุง YouTube มาเยอะพอสมควรแล้ว อีกอย่าง AI ในช่วงต้นปี 2023 ก็ยังไม่ได้เก่งเหมือนทุกวันนี้ด้วย

แต่พอทำงานไปสักพัก ความรับผิดชอบก็เริ่มเปลี่ยนไป

จากเดิมที่มีคนออกแบบ Database และกำหนด API มาให้ ก็เริ่มต้องออกแบบเอง ได้รับมอบหมายโปรเจกต์ใหม่ที่ต้องเข้าไปพูดคุยกับ Project Manager ฝั่งลูกค้าโดยตรง เนื่องจากบริษัทที่ผมทำงานอยู่เป็น Software Vendor ที่พัฒนาระบบให้กับองค์กรอื่น

ผมจึงเริ่มต้องทำความเข้าใจ Business Requirements ออกแบบ ER Diagram วางโครงสร้างข้อมูล และพัฒนา API ให้ตอบโจทย์การใช้งานจริง

ทำแบบนั้นมาเรื่อย ๆ จนงานเริ่มขยายไปสู่การ Integration กับ Third-party Systems การใช้ Queue, Background Jobs และ Workflow Orchestration

บางวันต้องคุยกับลูกค้า บางวันต้องประสานงานกับทีม IT ของบริษัทอื่น บางครั้งก็ข้ามไปช่วยตั้งค่า Infrastructure บางส่วนด้วย

ตอนแรกผมก็คิดว่า...

"ก็งาน Backend นี่แหละ จะมีอะไร"

แต่พอทำไปเรื่อย ๆ ผมเริ่มรู้สึกว่าสิ่งที่ตัวเองรับผิดชอบมันไม่ได้หยุดอยู่แค่การเขียน Backend ให้ทำงานได้แล้ว

Backend Developer กับ Software Engineer ต่างกันตรงไหน?

จริง ๆ แล้วสองคำนี้ไม่ได้แยกจากกันอย่างชัดเจนหรอกครับ Backend Developer ก็เป็น Software Engineer ได้เหมือนกัน และหลายบริษัทก็ใช้ชื่อตำแหน่งแตกต่างกันไป

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

ช่วงแรกผมมักตั้งคำถามว่า

"จะเขียน API นี้ยังไงให้ทำงานได้ตาม Requirement?"

แต่พอรับผิดชอบระบบมากขึ้น คำถามก็เริ่มเปลี่ยนไปเป็น

"ถ้า API นี้ทำงานสำเร็จ แต่ระบบปลายทางล่มล่ะ?"

"ถ้าข้อมูลถูกบันทึกไปแล้วครึ่งหนึ่ง จะจัดการยังไง?"

"ถ้าต้อง Retry แล้วเกิดข้อมูลซ้ำ ใครจะเป็นคนรับผิดชอบ?"

"ถ้าต้องเปลี่ยน Database Schema โดยที่ระบบยังให้บริการอยู่ จะทำยังไง?"

จากที่เคยมองเพียงว่า Feature ทำงานได้หรือไม่ ก็เริ่มต้องคิดถึง Reliability, Consistency, Failure Handling, Migration และผลกระทบที่เกิดขึ้นกับระบบโดยรวม

แน่นอนว่า Backend Developer ที่มีประสบการณ์ก็ต้องคิดเรื่องเหล่านี้เช่นกัน ผมไม่ได้มองว่า Software Engineer เป็นตำแหน่งที่เหนือกว่า Backend Developer แต่อย่างใด

สำหรับผม Software Engineer ไม่ใช่แค่ Job Title แต่มันคือวิธีคิดและความรับผิดชอบต่อซอฟต์แวร์ที่เราสร้างขึ้น

เมื่อระบบไม่ได้มีแค่ API แต่มี Workflow, Queue และ Orchestration

ขอยกตัวอย่างจากระบบที่ผมเคยทำจริงสักหน่อยครับ

เป็นระบบเกี่ยวกับการจัดการเอกสารและคำสั่งซื้อที่ต้องเชื่อมต่อกับ Third-party หลายแห่ง ส่วนรายละเอียดทางธุรกิจขออนุญาตไม่พูดถึงนะครับ เนื่องจากการเป็นมนุษย์เงินเดือนการรักษา NDA เป็นสิ่งสำคัญ ><

ซึ่งระบบลักษณะนี้ไม่ได้จบแค่รับ Request แล้วบันทึกลง Database เพราะข้อมูลหนึ่งชุดอาจต้องเดินทางผ่านหลายระบบ และแต่ละระบบก็มีเงื่อนไขการทำงานแตกต่างกัน

สิ่งที่ผมเลือกทำคือแยก Workflow ตามขอบเขตความรับผิดชอบของแต่ละระบบภายนอก แทนที่จะนำทุกอย่างมาผูกเป็น Flow เดียวกันทั้งหมด

เหตุผลก็ไม่ได้ซับซ้อนอะไรครับ

ถ้าระบบภายนอกเจ้าใดเจ้าหนึ่งล่ม ผมไม่อยากให้มันลากระบบส่วนอื่นล่มตามไปด้วย

แต่การแยก Workflow อย่างเดียวไม่ได้ทำให้ระบบทนต่อความผิดพลาดได้ทันที เรายังต้องคิดเรื่อง State, Dependency, Timeout และวิธี Recovery ของแต่ละขั้นตอนด้วย

อีกเรื่องหนึ่งที่สำคัญมากคือ Retry

ไม่ใช่ทุก Operation ที่สามารถ Retry ได้อย่างปลอดภัย

ตัวอย่างเช่น การส่ง Request เพื่อตรวจสอบข้อมูลกับ Third-party อาจ Retry ได้ หาก Operation นั้นไม่มี Side Effect และระบบปลายทางรองรับการ retry

แต่ถ้าเป็นการสร้าง Resource หรือเปลี่ยนสถานะข้อมูล เราต้องระวังมากขึ้น เพราะการ retry อาจทำให้เกิดข้อมูลซ้ำหรือผลลัพธ์ที่ไม่ต้องการ

แม้แต่การส่งอีเมลก็เช่นกัน Retry อาจทำให้ผู้รับได้รับอีเมลซ้ำได้ หากเราไม่มีวิธีจัดการเรื่องนี้

ผมจึงไม่ค่อยเชื่อแนวคิดที่ว่า "Retry everything"

สิ่งที่ควรทำคือทำความเข้าใจว่าแต่ละ Operation มี Side Effect อะไรบ้าง สามารถ retry ได้หรือไม่ และถ้าเกิดความผิดพลาดขึ้นมาจะตรวจสอบหรือกู้คืนอย่างไร

เพราะบางครั้งการ Retry โดยไม่เข้าใจ Business Flow อาจสร้างปัญหาใหม่ที่แก้ยากกว่าเดิมเสียอีก ซึ่งจริง ๆ แล้วถ้าเราออกแบบดี ๆ มันจะไม่ต้องมาดูและโฟกัสตรงนี้สักเท่าไหร่ แต่ก็นั่นแหละครับโดนบีบคอด้วย Timeline 🙀

Double Processing และ Data Inconsistency เรื่องเล็กที่ไม่เล็ก

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

สมมติว่ามีระบบ A และระบบ B

ระบบ A ต้องส่งข้อมูลไปยังระบบ B จากนั้นนำผลลัพธ์กลับมาบันทึกลง Database ของตัวเอง

ปัญหาคือระบบ A รับข้อมูลบางส่วนมาเป็น String เพื่อความสะดวกในการ Integration แต่ Column ใน Database กลับกำหนดไว้เป็น Integer

พอถึงขั้นตอนแปลงข้อมูลก่อนบันทึก ปรากฏว่า Cast ไม่สำเร็จ ทำให้ระบบ A เกิด Error

ฟังดูเหมือนเป็น Bug ธรรมดาใช่ไหมครับ?

แต่ประเด็นอยู่ตรงที่ ก่อนจะเกิด Error ระบบ A ส่งข้อมูลไปสร้าง Resource ที่ระบบ B สำเร็จแล้ว

หมายความว่าในมุมมองของระบบ B งานนี้เสร็จเรียบร้อย แต่ในมุมมองของระบบ A งานกลับล้มเหลว

ถ้าเรา Retry ทั้ง Workflow ตั้งแต่ต้น ระบบ A ก็จะส่ง Request ไปสร้าง Resource ที่ระบบ B อีกครั้ง

ผลที่ตามมาอาจเป็นข้อมูลซ้ำ หรือเกิด Unique Constraint Violation เพราะ Resource นั้นมีอยู่แล้ว

นี่คือตัวอย่างหนึ่งของปัญหา Distributed Data Inconsistency ที่เกิดจากสถานะของสองระบบไม่สอดคล้องกัน

การแก้ปัญหาแบบนี้ไม่ใช่แค่เพิ่ม Try-Catch หรือ Retry เข้าไปก็จบ

เราต้องรู้ว่า Operation ไหนสำเร็จไปแล้ว มีวิธีตรวจสอบสถานะจากระบบปลายทางหรือไม่ และสามารถออกแบบ Idempotency เพื่อป้องกันการประมวลผลซ้ำได้อย่างไร

บางกรณีอาจต้องใช้ Reconciliation Process เพื่อตรวจสอบและปรับสถานะของข้อมูลระหว่างระบบให้ตรงกัน

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

แล้วเวลา Production มีปัญหา ผมทำยังไง?

แน่นอนครับ ทำงานมาสักพักก็ต้องมีโอกาสเจอ Production Issue กันบ้าง

บางครั้ง Job ค้าง บางครั้ง Log ก็ไม่ได้บอกอะไรชัดเจน หรือบางครั้งลูกค้าก็แจ้งมาว่า

"ทำไมออเดอร์บางรายการหายไป?"

เจอแบบนี้ใครจะไม่ปวดหัวบ้างล่ะครับ ฮ่า ๆ

แต่สิ่งแรกที่ผมพยายามทำคือการหา Root cause ผมจะเริ่มจากการเก็บหลักฐานและตรวจสอบสถานะของระบบก่อน สิ่งแรกวิ่งไปทีม Intfa ขอดู logs monitor services & servers ก่อนเลยเพื่อขอดู logs ย้อนหลัง

ทีนี้หากจำเป็นต้องนำข้อมูลมาจำลองใน Local ก็ต้องจำลองสถานะการณ์ในเครื่องก็ต้องทำ เพื่อหา เคสหรือมุมมองที่อาจจะเป็นไปได้สำหรับเคสนั้น โดยปัจจุบันเราจะมี AI คอยช่วยตรงนี้สามารถให้ AI ref ข้อมูลจาก schema code เราได้และจำลอง mocking data เพื่อทดสอบและจำลองเคสว่าอาจจะเกิดจากอะไร

จากนั้นค่อยไล่ตรวจสอบว่า Job ที่มีปัญหาค้างอยู่ตรงไหน เกิด Connection Lost หรือ Timeout หรือเปล่า ระบบภายนอกตอบกลับมาว่าอะไร และมี Request Payload หรือหลักฐานเพียงพอสำหรับการตรวจสอบหรือ Retry ไหม๊

เพราะการจะทำการ Retry งานโดยไม่ตรวจสอบก่อนว่า Operation เดิมสำเร็จไปแล้วหรือยัง เพราะอาจทำให้เกิด Double Processing เหมือนตัวอย่างก่อนหน้าที่ผมพูดถึงได้

ผมมีสมมติฐานอย่างหนึ่งเวลาเจอปัญหาประเภทนี้

ออเดอร์ที่สร้างสำเร็จแล้ว ไม่ควรหายไปจากระบบโดยไม่มีร่องรอย

ถ้าลูกค้าบอกว่าออเดอร์หาย ผมจะเริ่มตรวจสอบก่อนว่ามันหายจริง หรือแค่ค้างอยู่ใน State บางอย่าง ถูกกรองออกจากหน้าจอ หรือเกิดปัญหาระหว่างการ Synchronize ข้อมูล

แน่นอนว่าข้อมูลอาจสูญหายได้จริงจาก Bug หรือความผิดพลาดของระบบ ดังนั้นเราจึงต้องมีทั้ง Audit Trail, Backup และวิธี Recovery ที่เหมาะสม

สำหรับผม การแก้ Production Issue นั้นเป็นส่วนหนึ่งที่สำคัญในขั้นตอน Maintenance ซึ่งการหาสาเหตุหลัก ๆ ให้เจอ แก้ไขอย่างปลอดภัย และพยายามไม่ให้ปัญหาเดิมกลับมาเกิดซ้ำ เป็นสิ่งที่สำคัญมาก ๆ แต่ก็จะแบบเจอบางจังหวะที่แบบ เฮ้ยย ตรงนั้นมันจะทำให้เกิดปัญหา B C D ... ตามมานะ...หมายถึงปัญหาในอนาคต บางทีเรามองเห็นแล้ว แต่ยังไม่ถึงเวลาแก้เพราะติด Part Commercial อันนี้ก็จะคันไม้คันมือเป็นต้น แต่ก็ทำอะไรไม่ได้แบบนี้ก็มี ><

ผมคิดเรื่อง Workflow Orchestration ยังไง?

เวลาต้องออกแบบระบบที่มีหลาย Workflow ผมไม่ได้เริ่มจากการเลือก Tool หรือ Programming Language ก่อน

ผมจะเริ่มจากการตั้งคำถามว่า ระบบนี้สำคัญต่อ Business Domain ของ User แค่ไหน มีข้อจำกัดอะไรบ้าง และยอมรับความผิดพลาดได้มากน้อยขนาดไหนก่อนจะเริ่ม design และแน่นอนแหละเราให้ความสำคัญสำหรับทุกการออกแบบของระบบ แต่ว่าตรงจุดที่ว่า Accept Failure ต่าง ๆ ได้มากน้อยแค่ไหนตรงนี้ผมก็มองว่าเป็นส่วนที่สำคัญส่วนหนึ่ง

จากนั้นจึงค่อยทำความเข้าใจ Domain แบ่งขอบเขตความรับผิดชอบของแต่ละ Workflow และพิจารณาว่าควรแยก Process หรือ Component ออกจากกันตรงไหน

เมื่อเข้าใจภาพรวมแล้วจึงค่อยลงรายละเอียดเรื่อง State Transition, Events, Failure Handling และ Recovery Strategy

โดยทั่วไปผมชอบแบ่งการออกแบบเป็นสองระดับ

ระดับแรกคือ Conceptual Design

เป็นภาพรวมของระบบที่ใช้พูดคุยกับทีมและผู้เกี่ยวข้อง ไม่ว่าจะเป็น Developer, QA, PM หรือฝั่ง Business

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

ระดับที่สองคือ Technical Design

เมื่อภาพรวมชัดเจนแล้วจึงค่อยลงรายละเอียดว่าเราจะใช้ Technology อะไร เช่น RiverQueue, Temporal, RabbitMQ หรือ Kafka

แต่ละเครื่องมือมีหน้าที่และข้อจำกัดแตกต่างกัน บางตัวเหมาะกับ Background Job บางตัวเหมาะกับ Workflow Execution และบางตัวเป็น Messaging Infrastructure

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

ผมคิดว่าไม่ใช่ทุกคนในทีมจำเป็นต้องเข้าใจ Technical Detail ลึกเท่ากันทั้งหมด

แต่ทุกคนที่เกี่ยวข้องควรเข้าใจภาพรวมของระบบและผลกระทบจากการเปลี่ยนแปลงในส่วนที่ตัวเองรับผิดชอบ

เพราะสุดท้ายแล้ว Diagram ที่ดีไม่ได้มีไว้แค่ทำให้ Architecture ดูสวย แต่ควรช่วยให้ทีมสื่อสารและตัดสินใจได้ดีขึ้นจริง ๆ

ทำไมผมไม่ค่อยเชื่อคำว่า "If it works, don't touch it"

ผมได้ยินประโยคนี้อยู่บ่อยเหมือนกันครับ เข้าใจแหละว่าเป็นโจ๊ก ซึ่งจริง ๆ แล้วอาจจะทำให้เป็นโจ๊กจริง (เละเป็นโจ๊ก ><)

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

เช่น เวลามีจำกัด มีงานอื่นสำคัญกว่า หรือทีมยังไม่มีความเข้าใจและ Test Coverage เพียงพอที่จะเปลี่ยนแปลงระบบอย่างปลอดภัย และคุ้มค่ากับเวลาที่เสียไปกับมันจริง ๆ เพราะทุกอย่างล้วนมีต้นทุน

แต่ผมไม่คิดว่าประโยคนี้ควรถูกนำมาใช้เป็นหลักการถาวรในการพัฒนาซอฟต์แวร์

เพราะระบบที่ทำงานได้ในวันนี้ ไม่ได้หมายความว่าจะรองรับ Requirement ใหม่ในวันข้างหน้าได้เสมอไป

สำหรับผม ระบบที่ดีควรเปิดโอกาสให้ Developer คนใหม่เข้ามาศึกษาและพัฒนาต่อได้ สามารถปรับเปลี่ยนตามความต้องการทางธุรกิจ และแก้ไข Edge Case ได้ง่าย โดยจะพยายามทำให้ไม่มี Learning Curve สูงมากนัก ในทาง Development เพราะเราควรเอาเวลาไปเข้าใจ Business Domain เป็นหลักเพื่อทำระบบให้ตอบโจทย์ลูกค้า

ที่พูดถึงในลักษณะนี้เพราะผมเคยเจอระบบที่ไม่มี Source Code ต้นฉบับให้ ต้อง Reverse Engineering ซึ่งเป็นงานที่สนุกดี (เขาไม่ได้ให้ทำถึงขนาดนั้นหรอก แต่อยากทำเองเพราะเรามองเห็นความเป็นไปได้ที่ระบบมันจะกลับมาทำงานได้)

งานแบบนี้ก็ถือเป็น Software Engineering รูปแบบหนึ่งเหมือนกัน เพียงแต่เป็นงานที่มีความไม่แน่นอนและใช้ความพยายามสูงมาก (ก่อนหน้านี้ยังไม่มี REA หรือ AI ยังไม่เก่งเลย แต่ก็สนุกไปอีกแบบ)

บางทีก็นั่งคิดว่า ใครมันจะบ้าดันทุรังทำอะไรแบบนี้

อ้าว... เราเองนี่หว่า (ขอ noted ไว้ว่าการทำในลักษณะนี้ทำในขอบเขตระบบที่จำกัด และมีจุดประสงค์ให้ระบบที่มีอยู่เดิมสามารถทำงานได้เท่านั้นครับไม่ได้ไปทำสุ่มสี่สุ่มห้า)

แต่ประสบการณ์แบบนี้ก็ทำให้ผมเห็นความสำคัญของ Source Control, Documentation, Automated Tests และการถ่ายทอดความรู้ภายในทีมมากขึ้นกว่าเดิม

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

ถ้าวันหนึ่งผมหายเข้าป่าไปหนึ่งเดือนจะเป็นยังไง?

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

ถ้าวันหนึ่งผมลาพักร้อนยาว ๆ หายเข้าป่าไปสักเดือนหนึ่ง ระบบที่ผมรับผิดชอบจะยังทำงานต่อได้ไหม? มันก็จะมีโมนเมนต์ขำ ๆ แบบว่า PM จะบอกเอา Laptop ไปด้วยนะ... ขอโทษเถอะผมจะไปปีนเสาสัญญาณที่ไหน ><

แล้วถ้ามี Requirement ใหม่เข้ามา คนอื่นในทีมจะสามารถพัฒนาต่อได้หรือเปล่า?

สำหรับผม คำตอบที่อยากได้คือ ได้ครับ

ระบบควรมี Documentation ที่จำเป็น มี Diagram หรือ Blueprint ที่ช่วยอธิบายภาพรวม และมี Source Code ที่อ่านแล้วพอเข้าใจเจตนาของการออกแบบได้ ยิ่งทุกวันนี้แบบ AI ทำตรงจุดนี้ได้ง่ายมาก ๆ​ ยกตัวอย่าง ChatGPT ตัวนี้ทำเอกสารได้ดีและได้ไวสำหรับทั้งภาษาไทยและภาษาอังกฤ​ษ ​(ปัจจุบันปลายปี 2026 นะจ๊ะ) ซึ่งต้อง Prompt และ Brief ดี ๆ ช่วยทำเอกสารได้ง่ายมาก ๆ

แน่นอนว่าเราไม่จำเป็นต้องเขียนเอกสารอธิบายทุกบรรทัด เพราะบางอย่าง Source Code และ Automated Tests ก็สามารถอธิบายได้ดีกว่าเอกสารเสียอีก. แต่ก็อย่าลืมนะว่ามีดีกว่าไม่มี และยิ่งถ้าอยากให้มีมาตรฐานมาก ๆ ควรอย่างยิ่ง อันนี้ผมพูดองค์รวมนะ เพราะบริษัทไหนที่ทำ ISO จะมีเอกสารมากำกับอยู่แล้วจุดนี้คงไม่ต้อง Concern อะไรกันมาก

สิ่งสำคัญคือทีมควรมีความรู้และหลักฐานเพียงพอที่จะดูแลระบบต่อได้ โดยไม่ต้องรอให้คนใดคนหนึ่งกลับมาตอบคำถาม ดังนั้นแล้วต้องมีการ Sync Knowledge ให้ทีมเสมอ ๆ สำคัญมาก ๆ

ผมไม่ค่อยเชื่อในการสร้างระบบที่ต้องพึ่งพา "คนเก่งคนเดียว"

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

ผมเองก็เป็นเพียงฟันเฟืองหนึ่งของทีม มีหน้าที่ช่วยให้ระบบและทีมเดินหน้าต่อไปได้

ถ้าวันหนึ่งผมไม่อยู่ ทีมก็ควรทำงานต่อได้เหมือนเดิม

และผมก็ไม่อยากให้มีส่วนไหนของระบบกลายเป็นพื้นที่ต้องห้ามที่ทุกคนกลัวจะแตะต้อง

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

ทุกวันนี้เรามีเครื่องมือช่วยทำความเข้าใจ Codebase มากกว่าแต่ก่อน ทั้ง Static Analysis, Code Search, Diagram และ AI ที่ช่วยสำรวจโครงสร้างของโค้ดได้
ในเมื่อเครื่องมือพัฒนาไปไกลขนาดนี้ การเข้ามาศึกษาระบบเดิมก็ควรจะง่ายขึ้น ไม่ใช่ยากขึ้นสิครับ!

ถึง AI จะไม่ได้เข้าใจ Business Context ทั้งหมด และยังต้องอาศัยคนตรวจสอบความถูกต้องอยู่ดี แต่มันก็ควรช่วยลดเวลาที่ต้องใช้ในการเรียนรู้ระบบได้พอสมควร ทุกวันนี้เราผลัก Congnitive Load ไปที่ AI แล้วก็ Context บางส่วนให้ AI แทบจะทั้งหมด แต่อย่าลืมว่า Overview Over All Context ของระบบหรือปัญหานั้น ๆ เราจะต้องดูด้วยตัวเองเป็นหลัก ๆ ทุกวันนี้ผมยังเถียงกับ AI อยู่เลย มันเก่งนะแต่การจะใช้ให้มีประสิทธิภาพเราต้องใส่ ไอเดียของเรา Fundamental ที่แข็งแรง ๆ ของเรา Pair ไปกับ AI ด้วยถึงจะ Powerful

Conclusion

พอมองย้อนกลับไปตั้งแต่วันที่เริ่มฝึกงานจนถึงวันนี้ ผมก็ยังทำงานเกี่ยวกับ Backend อยู่และอาจจะมีแจมทำ Frontend บ้าง ไปจนถึงระบบ Edge Device & Computer Vision เองที่ถือเป็นน่านน้ำใหม่ และแปลกใหม่จากเดิม

ยังเขียน API ยังออกแบบ Database ยังแก้ Bug และยังต้องนั่งไล่ Log เวลาอะไรสักอย่างทำงานผิดปกติ และใช้ AI ทุ่นแรงไปได้เยอะเลย

สิ่งที่เปลี่ยนไปคือมุมมองต่อการสร้างซอฟต์แวร์

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

ผมรู้สึกว่ายังมีอีกหลายเรื่องที่ไม่รู้ และอีกหลายอย่างที่ต้องเรียนรู้ต่อไปเยอะมาก ๆ

เพียงแต่ทุกปัญหาที่เจอ ทุก Production Issue ที่ต้องแก้ และทุกระบบที่ได้มีโอกาสออกแบบ มันค่อย ๆ ปรับปรุงวิธีคิด และเปิดมุมมองของผมไปทีละนิด ทีละนิดตามประสบการณ์ที่สั่งสมมาในแต่ละโปรเจค

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

ถ้าวันหนึ่งผมหายเข้าป่าไป ระบบยังทำงานได้ ทีมยังพัฒนาต่อได้ และไม่มีใครต้องโทรมาตามให้ผมกลับไปแก้ Production

นั่นแหละครับ คือซอฟต์แวร์ที่ผมอยากสร้าง

เอาล่ะถือว่าบ่นมายาวพอสมควรก็นั่นแหละครับนี่คือทั้งหมดที่ผมทำงานมาจาก เด็กฝึกงานและจนถึงทุกวันนี้ผมคงเรียกบทบาทตัวเองในฐานนะ Software Engineer เป็นหลัก ซึ่งยังคงชอบทำอะไรเกี่ยวกับ Software อยู่ในทุก ๆ วัน

ตอนนี้ในโลกการทำงานเห็นหลาย ๆ ที่เปิดรับเป็น Full Stack แทบจะทั้งหมดแล้ว ซึ่งผมมองว่าก็ Makesense ส่วนหนึ่งได้อิทธิพลมาจาก AI เราอาจจะต้องเพิ่ม Skill Sets ด้านอื่น ๆ และพัฒนาตัวเองยิ่ง ๆ ขึ้นไปตราบใดที่เรายังอยู่ในโลกทุนนิยม นำความรู้ไปต่อยอดในสายอาชีพ หมั่นอัปเดตความรู้เสมอในโลกที่ไวอย่างไม่เคยมีมาก่อนเพราะว่า AI : )

สุดท้ายนี้ ขอฝากประโยคหนึ่งที่ผมเขียนไว้เตือนตัวเองเกี่ยวกับการสร้างซอฟต์แวร์

Crafting software requires artistry, guided by imagination, grounded in logic, endlessly enduring.

  • Akkarapon Phikulsri

สำหรับ diagrams ต่าง ๆ ในบทความนี้ วาดโดยใช้ drawdy ซึ่งบอกเลยว่าลื่นปรื๊ด วาดแบบไม่มีสะดุดเลย ผมหา Tools อะไรแบบนี้มานานละ แล้วได้ฟังทีม Engineer ของ drawdy optimize tools ตัวนี้ใน Youtube ด้วยเลยลองใช้ดู

ส่วนตัวมองว่าตอบโจทย์ผมมาก ๆ ครับ

Top comments (0)