krishdev

ทำ

ก้อน data กับ function ที่เปลี่ยนรูปร่างมัน

ในวันที่ AI เขียน code ให้เราได้มากขึ้น ผมยังอยากจดวิธีคิดเรื่อง functional programming ไว้ เพราะมันเป็นวิธีที่ผมใช้ขึ้น project ดูแล project และทำให้ business logic อยู่ในรูปที่เทสง่ายขึ้น

เมล็ดอ่าน 3 นาทีเปิดแล้ว 0 ครั้ง

ช่วงนี้ AI เขียน code ให้เราได้มากขึ้นเรื่อยๆ

บางทักษะที่เคยสำคัญ อาจไม่ได้จำเป็นเท่าเดิมแล้ว

ผมเองก็ยังไม่รู้เหมือนกันว่า อีก 5 ปี developer จะต้องรู้เรื่องเดิมๆ มากแค่ไหน

ภาพในหัวที่ผมยังกลับมาดูอยู่
ภาพในหัวที่ผมยังกลับมาดูอยู่

แต่มีวิธีคิดหนึ่งที่ผมยังอยากจดไว้

ไม่ใช่เพราะมันเป็นของใหม่

แต่เพราะผมใช้มันมาตลอด ตอนขึ้น project ตอน maintain project และตอนพยายามทำให้ business logic ไม่กระจายจนกลับมาแก้ยาก

วิธีคิดนั้นมาจาก functional programming

สำหรับผม มันเริ่มจากภาพง่ายๆ ภาพหนึ่ง

มี data ก้อนหนึ่ง วิ่งผ่าน function หนึ่ง แล้วออกมาเป็น data อีกก้อนหนึ่ง

ก้อน data

เวลาผมคิดถึง program ผมมักไม่ได้เริ่มจาก class หรือ framework ก่อน

ผมเริ่มจาก data

ตอนนี้เรามี data รูปร่างแบบไหน

เราอยากให้มันกลายเป็นรูปร่างแบบไหน

ระหว่างทางต้องผ่านอะไรบ้าง

ภาพนี้ทำให้ระบบที่ดูซับซ้อน กลับมาเหลือสิ่งที่จับต้องได้มากขึ้น

มี data ตั้งต้น

มี function ที่เปลี่ยนรูปร่าง data

แล้วก็มี data ปลายทางที่เราเอาไปใช้จริง

อาจจะเอาไป serve เป็น API response

อาจจะเอาไปแสดงบน UI

อาจจะเอาไปบันทึกต่อ

แต่ภาพข้างในยังคล้ายกันมาก

ก้อน data ผ่าน function หลายอัน จนได้รูปร่างที่ต้องการ

function ที่ pure

function ที่ผมชอบที่สุด คือ function ที่ pure

ความหมายง่ายๆ คือ input เดิม ต้องได้ output เดิมเสมอ

ถ้าผมส่ง data ชุดหนึ่งเข้าไป แล้วได้ผลลัพธ์แบบหนึ่ง

ต่อให้ส่ง data ชุดเดิมเข้าไปอีก 1 ล้านครั้ง ผลลัพธ์ก็ควรออกมาเหมือนเดิมทุกครั้ง

ไม่มีการแอบ query database

ไม่มีการแอบเรียก external service

ไม่มีการแอบอ่านเวลาปัจจุบัน

ไม่มีการแอบแก้ค่าอะไรข้างนอก

มันรับ data เข้าไป แล้วคืน data ที่ผ่านการ transform ออกมา

แค่นั้น

ตรงนี้ทำให้มันเทสง่ายมาก

ใน unit test เราไม่ต้อง mock โลกทั้งใบ

เราแค่เตรียม input

เรียก function

แล้วดู output

ถ้า input แบบนี้ ต้องได้ output แบบนี้

มันเรียบง่ายจนบางทีดูไม่น่าสนใจ

แต่ความเรียบง่ายแบบนี้ช่วยชีวิตผมหลายครั้งมาก ตอน project โตขึ้น แล้วต้องกลับมาแก้ business logic เดิม

transform function

ผมมักเรียก function แบบนี้ว่า mapping หรือ transform function

หน้าที่ของมันไม่ใช่การไปคุยกับโลกข้างนอก

หน้าที่ของมันคือเปลี่ยนรูปร่าง data

จาก raw data ให้กลายเป็น view model

จาก database row ให้กลายเป็น object ที่ business เข้าใจ

จาก form input ให้กลายเป็น payload ที่ระบบข้างในใช้ต่อได้

จากหลายก้อนรวมกัน ให้กลายเป็นก้อนเดียวที่พร้อมส่งออกไป

พอเราแยก function พวกนี้ออกมาได้ business logic จะเริ่มมีรูปร่างชัดขึ้น

ไม่ใช่ code ก้อนใหญ่ที่ทำทุกอย่างพร้อมกัน

แต่เป็นทางเดินของ data

ก้อนนี้ผ่าน function นี้

แล้วผ่าน function นี้

แล้วผ่าน function นี้

จนสุดท้ายได้ data ที่ต้องการ

ถ้าวันหนึ่ง output ผิด ผมมักไล่ดูได้ว่า data เปลี่ยนรูปผิดตรง function ไหน

ไม่ต้องเดาทั้งระบบพร้อมกัน

side effect

อีกฝั่งหนึ่งคือ function ที่มี side effect

function พวกนี้ไม่ผิด

ระบบจริงยังต้องมีมันอยู่

เราต้อง query database

เราต้องเรียก external service

เราต้องอ่านไฟล์

เราต้องเขียน log

เราต้องส่ง email

โลกจริงมีสิ่งเหล่านี้เสมอ

ฝั่งซ้ายเป็น pure function ที่ปิดอยู่ในกล่อง ฝั่งขวาเป็น side effect ที่มีเส้นวิ่งออกไปหาโลกข้างนอก
ฝั่งซ้ายเป็น pure function ที่ปิดอยู่ในกล่อง ฝั่งขวาเป็น side effect ที่มีเส้นวิ่งออกไปหาโลกข้างนอก

แต่ปัญหาเริ่มเกิดขึ้นตอนเราเอา side effect ไปปนกับ business logic จนแยกไม่ออก

พอ function หนึ่งทั้ง query database ทั้งคิดราคา ทั้ง format response ทั้งเรียก service อีกตัว

function นั้นเริ่มเทสยาก

แก้ยาก

อ่านยาก

และที่หนักกว่านั้นคือ เราเริ่มไม่รู้ว่าความผิดพลาดมาจากตรงไหน

มาจาก data ตั้งต้นผิด

มาจาก business rule ผิด

มาจาก service ข้างนอกตอบไม่เหมือนเดิม

หรือมาจาก database state ตอนนั้น

เวลาผมขึ้น project เอง ผมเลยพยายามแยก function ที่มี side effect ไปไว้อีก layer หนึ่งให้ชัด

ให้มันรับผิดชอบเรื่องการคุยกับโลกข้างนอก

ส่วน business logic ข้างใน พยายามให้เป็น pure function ให้มากที่สุด

business logic ในหัวผม

ถ้ารวมภาพทั้งหมดเข้าด้วยกัน business logic ในหัวผมหน้าตาประมาณนี้

data ตั้งต้นมาจากโลกข้างนอก ผ่าน pure function หลายอันตรงกลาง แล้วเดินทางต่อไปยังปลายทาง
data ตั้งต้นมาจากโลกข้างนอก ผ่าน pure function หลายอันตรงกลาง แล้วเดินทางต่อไปยังปลายทาง

เริ่มจาก function ที่มี side effect ไปเอา data ตั้งต้นมาก่อน

อาจจะมาจาก database

อาจจะมาจาก API

อาจจะมาจาก user input

หลังจากนั้น data ก้อนนี้จะถูกส่งผ่าน transform function หลายอัน

แต่ละอันทำหน้าที่เล็กๆ ของตัวเอง

เปลี่ยนรูปร่างตรงนี้

เติมค่าตรงนี้

กรองบางอย่างออก

จัดกลุ่มบางอย่างใหม่

รวม data หลายก้อนเข้าด้วยกัน

จนสุดท้ายได้ data รูปร่างที่ระบบต้องการ

แล้วค่อยส่งมันออกไปใช้จริง

จะเอาไปเป็น API response ก็ได้

จะเอาไป render บน UI ก็ได้

จะเอาไปส่งต่อให้ service อื่นก็ได้

หลักการข้างในยังเหมือนเดิม

function ที่มี side effect ควรอยู่ตรงขอบของระบบ

มันคุยกับ database, API หรือโลกข้างนอก

ส่วน pure function รับ data เข้ามา แล้วเปลี่ยนรูปร่างมันอยู่ข้างในระบบ

ในวันที่ AI เขียน code

พอมี AI เข้ามา หลายอย่างเปลี่ยนไปมาก

เราอาจไม่ต้องนั่งพิมพ์ code ทุกบรรทัดเอง

เราอาจไม่ต้องจำ syntax ทุกอย่างเหมือนเมื่อก่อน

AI อาจ generate function ให้เราได้เร็วกว่าเราเขียนเองหลายเท่า

แต่ผมเริ่มรู้สึกว่า ภาพในหัวของคนสั่งยังสำคัญอยู่

ถ้าผมมองไม่ออกว่า data ควรไหลยังไง AI ก็อาจเขียน code ที่ทำงานได้ แต่กลับมา maintain ยาก

ถ้าผมไม่แยก pure function ออกจาก side effect AI ก็อาจรวมทุกอย่างไว้ใน function เดียว เพราะมันดูเร็วและตรงโจทย์ที่สุดในตอนนั้น

ถ้าผมไม่มีภาพของ transform function ผมก็อาจ prompt แค่ให้มันทำงานให้เสร็จ โดยไม่ได้บอกว่าระบบควรแบ่งความรับผิดชอบยังไง

ตรงนี้อาจเป็นทักษะที่ยังเหลืออยู่

ไม่ใช่ทักษะในการพิมพ์ code ให้เร็ว

แต่เป็นทักษะในการเห็นรูปร่างของระบบก่อน code จะถูกเขียนออกมา

สิ่งที่อยากจดไว้

ผมไม่ได้คิดว่า functional programming คือคำตอบของทุกอย่าง

ผมก็ไม่ได้เขียน pure ทุก function ในชีวิตจริง

หลายครั้งโลกจริงก็ยุ่งกว่านั้น

framework มีข้อจำกัด

เวลาในงานมีข้อจำกัด

ทีมมีวิธีทำงานของตัวเอง

แต่ภาพเรื่อง data กับ transform function ยังช่วยผมอยู่เสมอ

เวลา code เริ่มยุ่ง ผมกลับมาถามแค่นี้

ตอนนี้ data ก้อนไหนกำลังวิ่งอยู่

function นี้กำลังเปลี่ยนรูปร่าง data หรือกำลังคุยกับโลกข้างนอก

side effect อยู่ตรงไหน

ถ้าตอบคำถามพวกนี้ได้ ระบบมักจะเริ่มเบาลง

อาจไม่ใช่หลักการที่ตื่นเต้นแล้ว

อาจไม่ใช่ทักษะที่ดูสำคัญในวันที่ AI เขียน code ได้เร็วมาก

แต่สำหรับผม มันยังเป็นภาพพื้นฐานที่ทำให้การเขียนโปรแกรมชัดขึ้น

ก้อน data เข้าไป

function เปลี่ยนรูปร่างมัน

แล้วก้อน data ใหม่ก็เดินทางต่อ