จัดระเบียบโปรแกรมโดยแยกข้อมูลกับฟังก์ชันให้เป็นสัดส่วน
Tags: programming
Published: 2021-08-25 13:13:58

---
title: จัดระเบียบโปรแกรมโดยแยกข้อมูลกับฟังก์ชันให้เป็นสัดส่วน
published: true
description: 
tags: programming
//cover_image: https://direct_url_to_image.jpg
---

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

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

จากความเข้าใจบ้าน ๆ ของผมในยุค 80s 90s คนก็ใช้ dBASE เป็นการบังคับจัดให้เป็นระเบียบระดับนึง ข้อมูลทั้งหมดเป็น table ที่เอาใส่ไฟล์ .dbf ไว้ โปรแกรมที่จะเขาไปอ่านไปแก้ข้อมูลอยู่ใน .prg แยกกันอย่างชัดเจน 

ปลาย ๆ ยุค 90s คนเริ่มนิยมใช้ database ที่รันต่างหากเป็นอีกโปรแกรมเลย แล้วแอปก็รันแยกต่างหากแล้วสื่อสารส่งข้อมูลกันข้าม process หรือกระทั่งผ่านระบบเครือข่าย พวกนี้ใช้ Visual Basic หรือ Delphi หรือ Tcl/Tk อะไรก็ว่ากันไป ไป แล้วไปต่อกับ Oracle หรือ SQL Server อีกที จะว่าคู่ขนาดกับเครื่องมือพวกนี้ทางค่าย NeXT ซึ่งถูก Apple ซื้อไปทีหลังเขาก็เอาความคิดแบบ MVC มาใช้แล้ว ตั้งแต่ยุค 80s แต่ถ้าสืบสาวไปไปจริง ๆ จะไปถึง Smalltalk-79 จาก Xerox ในยุค 70s แต่ว่าแถวบ้านผมยังไม่ไม่ใช่เทคนิคที่เป็นที่นิยม NeXT computer ผมได้แค่ไปลูบ ๆ เครื่องตัวโชว์ 

ยุคต่อมาจาก Visual Basic ก็ทำเป็นเว็บจะเอา Perl เขียน หรือใช้ PHP หรือใช้ ASP เขียน โครงสร้างยังเหมือนเดิมคือแบ่ง database ไปไว้เป็นบริการนึง แอปอีกบริการนึง แล้ว code ในแอปก็จะเห็นได้เลยว่าส่วนไหนเอาไว้แก้ข้อมูล เพราะในยุคนี้จะเห็นเลยใช้ภาษา SQL อยากดูว่า code ส่วนไหนแก้ข้อมูลก็หาคำว่า INSERT หรือ UPDATE ก็เจอแล้ว มันก็เป็นระเบียบขึ้น ยุคนี้ข้อดีคือ data อยู่เป็นที่ ส่วนที่กระจัดกระจายออกไปก็มันจะเป็น data อายุสั้นที่อายุมักจะไม่เกิน 10 วินาที

[mrbs](https://mrbs.sourceforge.io/) สำหรับผมเป็นตัวแทนของยุค 2000s เลยนะสำหรับผม เป็นโปรแกรมจองห้องโรงแรมมันก็คล้าย ๆ จองวัคซีนนะ อาจจะซับซ้อนกว่าด้วยซ้ำ เขียนด้วย PHP

โปรแกรมจัดระเบียบส่วนที่แก้ค่าต่าง ๆ อย่างชัดเจนคือ พวกที่แก้ database อยู่ในไฟล์ที่ลงท้ายด้วย [_handler.php](https://github.com/meeting-room-booking-system/mrbs-code/blob/main/web/edit_room_handler.php) ข้างในก็มี code สร้าง SQL มีคำสั่ง update ไม่ได้แสดงผลอะไรออกมา ส่วนไฟล์ที่ชื่อคล้าย ๆ กันแต่ไม่มี _handler ลงท้าย พวกนี้ก็เห็นคำสั่ง SELECT ข้างในแล้วก็ไปเรียก code ที่สร้าง HTML อีกที

ยุค 2000s ก็ไม่ใช่ว่าทุกคนทำแอปออกมาแล้วจะเป็นระเบียบแบบ mrbs ต้องอาศัยการวางโครงสร้างที่ดี กระทั่ง mrbs ยังจัดระเบียบให้มีสัดส่วนให้มากกว่านั้นได้อีก

ทำให้มี framework ที่ดังขึ้นมาในยุค 2010s คือ Ruby on Rails เอาแนวคิด MVC มาใช้ซึ่งเจ้าอื่นเขาก็ใช้มาตั้งแต่เริ่มยุค 80s หรือก่อนนั้นแล้ว

Ruby on Rails ตัวอย่างจาก code ของ [Mastodon](https://joinmastodon.org/) ส่วนที่แก้ค่าต่าง ๆ ก็อยู่ใน [model](https://github.com/mastodon/mastodon/tree/main/app/models) แยกเป็นเรื่องต่าง ๆ มี user  post แต่เรียก status เป็นต้น

นอกจากเรื่องประสิทธิภาพเวลารันแล้ว พวกแอปหลัง 2010 มีประเด็นที่ต้องจัดการคือ แอปบน smart phone; แอป web browser แทน server; โปรแกรมซับซ้อนแยกออกมา test เฉพาะส่วนยาก ไม่ว่าจะ automated test หรือ manual test 

สามเรื่องนี้ผมมองว่าเกี่ยวกัน ยุคต้น ๆ 2000s ใช้ http เป็นหลัก ระเบียบในการเปลี่ยนค่าคือ ทั้งหมดอยู่ใน database กลาง กับ session db ซึ่งอาจจะเป็น file หรือ database อีกตัวที่เน้นใช้ RAM ส่วนตัวแปรยิบย่อยที่ใช้งานระหว่าง HTTP ทำงานมันก็จะถูกไปในการเรียกครั้งเดียว

แต่พอมาทำแอปบน smartphone และบน web browser ตัวแปรบางตัวอาจจะอยู่ไปเลยทั้งวันก็ได้ หรือหลายวันก็ได้ แต่ว่าตัวอย่างนี้คงใช้กับพวกเว็บลงทะเบียนไม่ได้แล้ว เพราะเว็บลงทะเบียนควรจะลงเสร็จใน 10 นาที ส่วนของเว็บลงทะเบียนที่ต้องมีโปรแกรมบน web browser บ้างเช่น ถ้าเลือกสัญชาติเป็นกัมพูชาหน้าจอก็จะให้กรอกเลข passport แทนเลขบัตรประชาชน validator ก็ต้องเปลี่ยนให้ใส่ตัวอักษรโรมันได้ แทนที่จะเป็นตัวเลขอย่างเดียวแบบเลขประชาชน แต่ถ้าแอปเป็นอย่างอื่น เช่น ตลาดหุ้น คลาดสินทรัพย์ดิจิทัลต่าง ๆ มีกราฟมีราคาพวกนี้บางคนก็เปิดทิ้งไว้เป็นวันเป็นสัปดาห์เลยก็ได้ และสถานะมันก็เปลี่ยนไปตลอด จะมาหวังทำแบบสมัยที่เว็บโหลดมาทีละหน้าแล้วล้างสถานะไปหมดไม่ได้แล้ว

ทางด้าน backend ก็มี business rule หลาย ๆ อย่างที่แยกออกมา test ได้โดยที่ไม่ต้องไปรันกับ database หรือเว็บ แต่ถ้าไม่แยกออกมาแต่แรกต้องเรียกจาก controller หรือใน http handler แบบแยกไม่ออกก็กลายเป็นยากไป

พอมีความจำเป็นต้องแยกส่วนที่ว่าไม่ต้องไปรันกับ database ก็ได้ อันนี้ functional programming ก็กลายเป็นสำคัญขึ้นมา จริง ๆ แล้วก็เป็นเรื่องเก่า บางคนบอกว่าเก่าจนถึง 1920s ด้วยซ้ำ

ความคิดส่วนหนึ่งของ function programming คือการแยก pure function ออกมา พอเป็น pure function นี่เรา test ได้เลยทั้ง auto ทั้ง manual ไม่ต้องเอา database ใส่ 

ทั้ง Lisp ทั้ง Clojure ส่วนเด่น ๆ คือมันแถม immutable data structure มาให้ด้วย อันนี้ก็ทำให้เขียน pure function ง่ายขึ้น ไม่ต้องแก้ data structure ก้อนเดิม สร้างก็ใหม่ได้ได้เรื่อย ๆ โดยที่ไม่ได้ช้าหรือกินที่มาก 

แต่ถึงอย่างนั้น data structure ที่ว่าก็เอาใส่ภาษาอื่นก็ได้ เอา JavaScript ก็ได้ เอา Ruby ก็ได้

OCaml หรือภาษาตระกูล Meta-Language ทั้งหมด เท่าที่ผมเห็นคือทำได้หลาย ๆ อย่างแบบ Lisp มี data structure แบบเดียวกันเลย แต่ว่าใช้แบบ static-typing ได้ วงเล็บน้อยลง ผมเดาว่าคนคงจะบ่นเรื่องนี้เยอะ

ส่วน Haskell ส่วนที่พิเศษคือ ปกติ Lisp กับ OCaml นี่เวลาเขียน pure function นี่ programmer ก็ต้องดูเอาเองว่ามัน pure หรือเปล่า แต่ Haskell นี่บังคับ pure แต่ในความ pure ผมดูคร่าว ๆ มันก็จะมีสองแบบคือ function ที่รับค่าเข้าไปธรรมดา กับ function ที่มี monad อย่างหลังนี่ถ้าไปยุ่งกับ database หรือ IO หรือ State ก็จะกลายเป็นว่ามี monad ขึ้นมา

การแยก pure function ออกมาผมมองว่าพอเอาไปใช้กับ MVC แบบใน Ruby on Rails ผมเห็นว่ามันทำให้จัดระเบียบข้อมูลกับฟังก์ชันได้ดีขึ้นไปอีกขั้น ซึ่งตัวที่ผมเห็นว่าขนาดแนวคิดเรื่อง MVC และ pure function ให้เข้าได้ได้ดีเลยคือ [re-frame](https://github.com/Day8/re-frame) บน Clojure ขึ้นมา ก็เป็นการบังคับหรือกึ่ง ๆ บังคับให้ใช้ pure function มากขึ้น และแยก data ออกมารวมศูนย์กันเป็นสัดส่วน ข้อดีนอกจากจะ test ง่ายแล้ว ก็ทำ hot reload ง่ายขึ้นด้วย นอกจาก re-frame แล้ว Elm ก็น่าจะคล้าย ๆ กันแต่ผมยังไม่เคยใช้

สรุปว่าที่เล่ามาทั้งหมดการเขียนโปรแกรมตั้งแต่ 30-40 ปีทีแล้วจนถึงเดี๋ยวนี้ สิ่งที่ผมเห็นหลัก ๆ เลยก็คือการจัดระเบียบให้ data กับ function มันแยกกันเป็นสัดส่วน

ป.ล. ตรงไหนงงหรือว่าผมเขียนผิด ถ้าหากแจ้งมาจะขอบคุณมากครับ