แทบจะเป็นไปไม่ได้เลยที่เราจะเขียนโค้ดในระบบที่มีขนาดใหญ่พอสมควรโดยไม่มีเรื่องของ concurrency เข้ามาเกี่ยวข้อง มันอาจจะแสดงออกมาให้เห็นชัดเจน หรืออาจจะซ่อนอยู่ภายใน library ก็ได้ Concurrency เป็นสิ่งที่จำเป็นมากถ้าคุณต้องการให้ application สามารถรับมือกับโลกแห่งความเป็นจริงที่ทุกอย่างเป็น asynchronous ไม่ว่าจะเป็นตอนที่ user กำลังใช้งาน, กำลัง fetch data, หรือเรียกใช้ external service ต่างๆ ซึ่งทั้งหมดนี้เกิดขึ้นพร้อมกัน ถ้าคุณฝืนให้กระบวนการเหล่านี้ทำงานแบบ serial คือทำทีละอย่างเรียงกันไปเรื่อยๆ ระบบของคุณจะรู้สึกอืด (sluggish) และคุณก็น่าจะยังใช้พลังของ hardware ที่มีอยู่อย่างไม่คุ้มค่าเท่าที่ควร

ในบทนี้เราจะมาพูดถึงเรื่อง concurrency และ parallelism กันครับ

ปกติพวกเราเหล่า developer มักจะพูดถึงเรื่อง coupling ระหว่างโค้ดส่วนต่างๆ กันบ่อยๆ ซึ่งเรามักจะหมายถึงเรื่อง dependency และการที่มันทำให้การเปลี่ยนอะไรบางอย่างในโค้ดเป็นเรื่องยาก แต่ยังมี coupling อีกรูปแบบหนึ่งที่เรียกว่า temporal coupling ครับ ซึ่งมันจะเกิดขึ้นเมื่อโค้ดของคุณไปบังคับลำดับการทำงานของสิ่งต่างๆ โดยที่จริงๆ แล้วมันไม่ได้จำเป็นต่อการแก้ปัญหาเลย คุณจำเป็นต้องรอให้ “tick” มาก่อน “tock” หรือเปล่า? ถ้าอยากให้ระบบยืดหยุ่นก็ไม่ควรครับ หรือโค้ดของคุณเรียกใช้ back-end service หลายตัวแบบต่อคิวกัน (sequential) หรือเปล่า? ถ้าอยากรักษาฐานลูกค้าไว้ก็ไม่ควรทำแบบนั้นครับ ใน Topic 33 เรื่อง ​Breaking Temporal Coupling​ เราจะมาดูวิธีระบุเจ้า temporal coupling ประเภทนี้กัน

ทำไมการเขียนโค้ดแบบ concurrent และ parallel ถึงได้ยากนักล่ะ? เหตุผลหนึ่งก็เพราะเราเรียนรู้การเขียนโปรแกรมด้วยระบบแบบ sequential มาตลอด และภาษาที่เราใช้อยู่ก็มี feature ที่ปลอดภัยเมื่อใช้แบบลำดับขั้นตอน แต่พอกลายเป็นเรื่องที่ต้องทำสองอย่างพร้อมกันเมื่อไหร่ สิ่งเหล่านั้นจะกลายเป็นภาระทันที ตัวการสำคัญตัวหนึ่งเลยก็คือ shared state ครับ ซึ่งไม่ได้หมายความถึงแค่ global variable เท่านั้นนะ แต่มันหมายถึงตอนไหนก็ตามที่โค้ดตั้งแต่สองส่วนขึ้นไปมีการอ้างอิงถึงข้อมูลที่เปลี่ยนแปลงได้ (mutable data) ก้อนเดียวกัน นั่นแหละคือคุณมี shared state แล้ว และใน Topic 34 เรื่อง ​Shared State Is Incorrect State​ จะมาเล่าให้ฟังครับ ซึ่งในหัวข้อนี้จะอธิบายวิธีการแก้ปัญหาเบื้องต้นเอาไว้ แต่ท้ายที่สุดแล้ววิธีเหล่านั้นก็ยังเสี่ยงต่อการเกิด error อยู่ดี

ถ้าเรื่องนั้นทำให้คุณรู้สึกท้อใจ (sad) ก็อย่าเพิ่งหมดหวังครับ (nil desperandum!) ยังมีวิธีที่ดีกว่าในการสร้าง concurrent application อยู่ครับ หนึ่งในนั้นคือการใช้ actor model ซึ่งเป็นระบบที่แยก process ออกจากกันโดยสิ้นเชิง ไม่มีการแชร์ข้อมูลกัน แต่จะสื่อสารกันผ่าน channel ด้วยรูปแบบที่เรียบง่ายและชัดเจน เราจะมาคุยกันทั้งในเชิงทฤษฎีและปฏิบัติเกี่ยวกับแนวทางนี้ใน Topic 35 เรื่อง ​Actors and Processes​ ครับ

สุดท้าย เราจะไปดู Topic 36 เรื่อง ​Blackboards​ กันครับ ซึ่งเป็นระบบที่ทำงานเหมือนการเอา object store มาผสมกับ publish/subscribe broker ที่ฉลาดๆ ในตอนแรกเริ่มนั้น ระบบแบบนี้ไม่ค่อยได้รับความนิยมเท่าไหร่ แต่ในปัจจุบันเราเริ่มเห็นการเอาแนวคิดแบบ blackboard มาใช้ใน middleware layer มากขึ้นเรื่อยๆ ซึ่งถ้าใช้อย่างถูกวิธี ระบบประเภทนี้จะช่วยทำ decoupling ได้มหาศาลเลยทีเดียวครับ

แต่ก่อนการเขียนโค้ดแบบ concurrent และ parallel อาจจะดูเป็นเรื่องที่แปลกใหม่หรือเฉพาะทาง (exotic) แต่เดี๋ยวนี้มันกลายเป็นเรื่องที่เลี่ยงไม่ได้แล้วครับ