- "การเขียนโปรแกรมเชิงฟังก์ชัน (FP) เรียนรู้ยาก แต่จะทำให้โค้ดของคุณสร้างความประหลาดใจที่ไม่น่าพอใจน้อยลง"
- ใน FP นั้น "less is more"
- แก้ปัญหา Null Reference ได้ (ด้วย Maybe/Option)
- FP มีเส้นโค้งการเรียนรู้ที่ชัน
- อนาคตของ FP
- หากต้องการพัฒนาให้ได้มากขึ้นด้วยนักพัฒนาที่น้อยลง ก็ต้องใช้ทุกเครื่องมือที่เป็นไปได้ และ FP คือบัตรผ่านสำหรับสิ่งนั้น
- บริษัทที่ไม่ได้โดดเด่นหวือหวาแบบพวกเรานั้นจ้างนักพัฒนาได้ยาก แต่จะสามารถดึงดูดนักพัฒนาระดับท็อปที่อยากทำงานกับโค้ดเบส FP ได้
- การนำ FP มาใช้จะช่วยยกระดับคุณภาพและความทนทานของซอฟต์แวร์ และลดเวลาที่ต้องเสียไปกับบั๊กประเภทที่ไม่เกิดขึ้นใน FP
- การที่ฟีเจอร์ของ FP เริ่มปรากฏมากขึ้นในภาษากระแสหลัก หมายความว่าอุตสาหกรรมซอฟต์แวร์กำลังเตรียมพร้อมสำหรับการเปลี่ยนผ่านเชิงกระบวนทัศน์
- แม้จะยังต้องมีงานอีกมากก่อนที่ทั้งอุตสาหกรรมจะเปลี่ยนผ่านได้อย่างสมบูรณ์ แต่เพราะข้อดีของแนวทางนี้ชัดเจน จึงแทบไม่มีข้อสงสัยเลยว่ากำลังมุ่งหน้าไปทางไหน
13 ความคิดเห็น
ดูเหมือนว่าเส้นโค้งการเรียนรู้จะสูงจริง ๆ และในคอมเมนต์ก็มีเนื้อหาที่แสดงว่ายังไม่เข้าใจ Functional Programming อย่างแท้จริงอยู่ด้วย แน่นอนว่าก็มีคอมเมนต์ที่เขียนโดยคนที่เข้าใจดีเช่นกัน Functional นั้นยากครับ ตัวผมเองก็ยังเรียนรู้อยู่จนถึงตอนนี้ เศร้าเลย เศร้าเลย
เราจะกลับมาพูดถึงความจำเป็นของ FP ได้อย่างจริงจังก็ต่อเมื่อเกิดกรณีที่ภาษาโปรแกรมมิ่งไม่ใช่เรื่องรสนิยมของทีมพัฒนาอีกต่อไป แต่เป็นเรื่องความอยู่รอดของบริษัท
ขอสรุปให้เลย ตอนนี้ในเรื่องการจัดการหน่วยความจำและอัลกอริทึมบางส่วน ก็ยังเหนือกว่าเชิงวัตถุไม่ได้อยู่ดี เลือกใช้ให้เหมาะสมตามสถานการณ์และต้นทุนก็พอ
อืม.. ผมไม่ค่อยเห็นด้วยกับข้ออ้างที่ว่าช่วงการเรียนรู้มันชันมากนัก
เอาเข้าจริงมันก็แค่ง่าย ความผิดพลาดก็มีโอกาสน้อยลง และเพราะอย่างนั้นประสิทธิภาพการทำงานก็สูงขึ้น
แค่นั้นก็พอแล้วไม่ใช่เหรอ
มันยากที่จะทำให้ความคิดและงานของมนุษย์ถูกทำให้เป็นสูตรอย่างสมบูรณ์แบบเหมือนภาษาโปรแกรมเชิงฟังก์ชันแบบบริสุทธิ์ทั้งหลาย พอเห็นอะไรอย่าง free monad แล้วก็รู้สึกว่าแค่ระดับ rxjs น่าจะเป็นขอบเขตสูงสุดที่พอยอมรับได้
FP เองก็มาถึงจุดที่ต้นทุนแฝงมากกว่าประโยชน์ได้เหมือนกัน
เอฟเฟกต์ของ FP แบบเดิมก็แค่ประมาณว่าแยกข้อมูลกับเมธอดออกจากกัน
ดูแค่
Optionalที่ในความเป็นจริงไม่ได้ถูกใช้ดีอย่างที่คิด ก็พอจะเห็นได้ว่านามธรรมด้าน type เป็นการทำ abstraction ที่ไม่จำเป็นนัก (ต้องคอยทำ type ให้ลงตัวจนกิน productivity มากเกินไป)ถ้าไม่ไปในทิศทางที่ abstract ทั้งข้อมูลและการคำนวณให้มากขึ้นแบบ closure ก็มีข้อจำกัดในการใช้ประโยชน์จากภาษาที่มีอยู่เดิม
ความไม่เปลี่ยนแปลงเป็นเพียงเครื่องมือที่ใช้บ่อยในกระบวนทัศน์การเขียนโปรแกรมเชิงฟังก์ชันเท่านั้น
เท่าที่ผมเข้าใจ กระบวนทัศน์การเขียนโปรแกรมเชิงฟังก์ชันคือกระบวนทัศน์ที่มุ่งควบคุม "ผลข้างเคียง" (Side effect) ให้ได้มากที่สุด
เมื่อพยายามควบคุมผลข้างเคียง จึงทำให้แนวคิดอย่าง referential transparency, ความไม่เปลี่ยนแปลง, pure function ถูกให้ความสำคัญไปโดยธรรมชาติ
ในแง่นั้น ผมคิดว่าแม้จะไม่ได้ใช้ภาษาโปรแกรมเชิงฟังก์ชันโดยตรง ก็ควรตระหนักให้ชัดเจนถึงผลข้างเคียงของฟังก์ชันหรือเมธอดที่ตัวเองเขียน และควบคุมมันอย่างเหมาะสม ซึ่งมีข้อดีมากมาย เช่น ช่วยลด Code smell ในโค้ด และทำให้เขียน unit test ได้ง่ายขึ้น
ยังมีบทความแปลที่อธิบายเรื่องนี้ไว้อย่างละเอียดกว่านี้ด้วย
ในมุมมองแบบนี้ หนังสือที่เน้นการรีแฟกเตอร์เพื่อลดผลข้างเคียงให้น้อยที่สุดคือ การเขียนโค้ดเชิงฟังก์ชันแบบเข้าใจง่าย: จัดการซอฟต์แวร์ที่ซับซ้อนด้วยโค้ดที่เรียบง่าย เนื่องจากหนังสือเล่มนี้เข้าหาจากมุมมองที่ใช้งานได้จริงและเน้นงานภาคปฏิบัติมากกว่าทฤษฎี จึงมีคุณค่ามากพอสำหรับคนที่อยากเขียนโค้ดที่ดีให้อ่านและศึกษา หลังจากอ่านแล้ว แค่ทำให้ตอนเขียนโค้ดใส่ใจกับผลข้างเคียงมากขึ้นกว่าก่อนหน้านี้ได้มาก ก็ถือว่าคุ้มค่าราคาหนังสือแล้วในความเห็นของผม
ขอบคุณครับ เดี๋ยวต้องลองหาไปอ่านดูแล้ว
อ๋อ! มีฉบับแปลออกมาแล้วสินะ! ไว้ต้องลองอ่านดูครับ!
ขอบคุณสำหรับคำแนะนำหนังสือครับ!! เดี๋ยวจะซื้อมาอ่านเลย!
หนังสือเล่มนั้นดีมากจริง ๆ!
มองจากมุมของการรีแฟกเตอร์แล้ว ใช้งานสะดวกมากจริง ๆ ครับ
แน่นอนว่าผมก็คิดว่าการเขียนโปรแกรมเชิงฟังก์ชันเป็นแนวทางที่ดี แต่ดูเหมือนจะไม่ค่อยมีคนที่ถ่ายทอดข้อดีของมันได้อย่างน่าเชื่อถือนัก แค่บอกว่าดีก็ยังไม่ค่อยทำให้เห็นภาพจริงไหม?
ต่อไปนี้เป็นความเห็นส่วนตัวของผม และเพราะโปรแกรมสมัยใหม่ทั้งหมดล้วนสร้างอยู่บนพื้นฐานของเครื่องทัวริง จึงสามารถแบ่งเชิงนามธรรมออกได้เป็นฟังก์ชันกับข้อมูลเป็นหลัก ดังนั้นผมจึงมองว่าโดยรากฐานแล้วการเขียนโปรแกรมเชิงกระบวนการก็เป็นเชิงฟังก์ชันเหมือนกัน ถ้าอย่างนั้นข้อดีที่แท้จริงของแนวเชิงฟังก์ชันเมื่อเทียบกับเชิงกระบวนการคืออะไร ผมคิดว่ามันก็คือการ "ไม่ใช้ตัวแปรแบบ global หรือในขอบเขตที่ใกล้เคียงกัน" นั่นเอง ด้วยข้อดีนี้จึงเหมาะกับทั้ง "การแยกส่วนระหว่างฟังก์ชันกับฟังก์ชัน" และ "การประมวลผลแบบมัลติเธรด" ด้วย
แต่ถ้าถามว่านี่เป็นข้อได้เปรียบที่ได้จากการเขียนโปรแกรมเชิงฟังก์ชันเท่านั้นหรือไม่ ก็ไม่ใช่เสียทีเดียว ในภาษาเชิงกระบวนการเองก็มีการแนะนำให้แยกคลาสและฟังก์ชันเป็นหน่วยผ่านแนวคิด dependency injection (ซึ่งเฟรมเวิร์กสมัยใหม่แทบทั้งหมดก็นำมาใช้เป็นพื้นฐานอยู่แล้ว) และในภาษา Rust ก็มีการกำหนดข้อจำกัดในระดับภาษาเพื่อให้มุ่งไปสู่การประมวลผลพร้อมกันที่สะดวก
สรุปแล้ว ภาษาเชิงฟังก์ชันเป็นทั้งภาษาที่ดีและเป็นวิธีวิทยาที่ดี แต่แทนที่จะ "เหนือกว่าในความหมายเชิงวิวัฒนาการ" ผมมองว่ามันเป็นเพียงภาษาแบบเดียวกับ Go หรือ Rust ที่ "พยายามตัดความเป็นไปได้ของความล้มเหลวออกไปตั้งแต่ในระดับภาษา แต่ก็เป็นภาษาที่ใช้งานยาก"
หมายความว่าแม้แต่ในภาษาเชิงกระบวนการก็สามารถทำสิ่งอย่างการประกอบฟังก์ชันได้ด้วยใช่ไหมครับ?
ถ้ามองนิยามของ 'การประกอบฟังก์ชัน' แบบแคบ ๆ ก็อาจคิดว่าใช้ได้เฉพาะในภาษาฟังก์ชันเท่านั้น แต่พอลองคิดดูดี ๆ การทำงานนั้นสุดท้ายก็รันอยู่บนภาษาเครื่องหรือแอสเซมบลีซึ่งเป็นภาษาเชิงกระบวนการอยู่ดีนั่นแหละ พูดอีกอย่างคือ มันไม่ใช่ปัญหาว่า 'ทำได้หรือทำไม่ได้' แต่เป็นเรื่องของ 'จุดสนใจ รสนิยม และปรัชญาของภาษา' มากกว่า
ถ้าขยายนิยามของ 'การประกอบฟังก์ชัน' จากความหมายแคบ ๆ ว่าเป็น 'ความสามารถเฉพาะของภาษาหนึ่ง' ให้กว้างขึ้นเป็น 'การประกอบกันระหว่างหน้าที่เชิงตรรกะ' ก็ทำได้อย่างสบาย ๆ และเพราะภาษาฟังก์ชันมีข้อดีอย่างชัดเจน จึงมีสิ่งอย่าง rxjs หรือ Spark ที่นำแนวคิดเหล่านี้มาใช้เชิงรุก
อย่างที่ทุกคนเรียนกันในภาควิชาคอมพิวเตอร์ ด้านล่างนี้ให้ผลลัพธ์เหมือนกัน ต่างกันแค่รูปแบบการเขียนเท่านั้น และแบบ prefix ก็มักถูกเรียกว่าเป็นแนวฟังก์ชัน
การเขียนแบบ prefix : + 1 1
การเขียนแบบ infix : 1 + 1
การเขียนแบบ postfix : 1 1 +