# Algorithm

## 😢 ปัญหา

หลายคนที่เรียน Computer Science หรือ Computer Engineering มาก็คงจะหนีไม่พ้นที่จะถูกบังคับให้เรียน **Data Structure & Algorithm** มาชิมิ แล้วพอมาอยู่ในโลกของการเขียนซอฟต์แวร์จริงๆก็อาจจะมีคำถามว่า ไอ้วิชาบร้านี้เรียนมาทำไมฟระ เสียเวลาชีวิตจุง 🤬&#x20;

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

{% hint style="danger" %}
**ฟหกดเอกอาสว!@#$%^&\* 😎**\
โครงสร้างซอฟต์แวร์จะเทพหรือกากมันคือเรื่องนี้เบย
{% endhint %}

## ❓ Data Structure & Algorithm คือไย ?

> ขอเกริ่นให้คนที่ไม่ได้เรียนวิชานี้ หรือลืมไปแบ้วนิสนุง (ใครจำได้ก็ข้ามไปดูด้านล่างโลด)&#x20;

### Algorithm

เวลาที่เราเจอปัญหาอะไรก็ตาม เช่น อยากให้โปรแกรมทำนั่นนู่นนี่ได้ สิ่งที่เราจะต้องทำก็คือ **หาวิธีการแก้ไขปัญหา** หรือนั่นก็คือ **`Algorithm`** นั่นเอง ซึ่งขั้นตอนนี้เราจะคิดออกมาเป็นขั้นตอน 1 2 3 4 โดยไม่ยึดติดว่ามันเป็นภาษาอะไรนั่นเอง ซึ่งปัญหาที่เราเจออาจจะมีวิธีการแก้ปัญหาหลายๆแบบก็ได้ (มี Algorithm มากกว่า 1 ตัว)

> **สรุปสั้นๆ**\
> Algorithms คือการ Define steps ที่ใช้ในการแก้ปัญหา

### Data Structure

หลังจากที่เรารู้แล้วว่าเราจะแก้ปัญหานั้นยังไง เราก็จะเลือกวิธีการแก้ปัญหาที่เราคิดว่าดีที่สุดมา แล้วเราก็จะเอามันไปออกแบบว่า ถ้าจะเขียนโค้ดเพื่อให้มันทำงานตาม Algorithm นั้นๆได้ เราจะออกแบบ class ต่างๆ module ต่างๆยังไง เพื่อให้มันทำงานตาม algorithm นันๆได้นั่นเอง และแน่นอนว่า 1 Algorithm ก็สามารถมี Data Structure ได้มากกว่า 1 แบบเช่นกัน

> **สรุปสั้นๆ**\
> Data Structure คือการ Define structure ที่ใช้ในการเขียนโค้ดให้ได้ตาม Algorithm นั้นๆ

จากที่มโนมาทั้งหมดเราก็จะเห็นว่า **Algorithm กับ Data Structure เป็นของที่ เกิดมาคู่กัน** โดยมันมีเป้าหมายหลักอันเดียวกันคือ แก้ไขปัญหาที่เรากำลังเจออยู่นั่นเอง ซึ่ง**แต่ละ Algorithm แต่ละ Data Structure ก็จะมีข้อดี ข้อเสียที่แตกต่างกันไป**

{% hint style="info" %}
**เพื่อให้เห็นภาพ**\
ลองทบทวนคณิตศาสตร์ประถมนิสนุงเรื่องการหา [**ห.ร.ม. (หารร่วมมาก)**](https://en.wikipedia.org/wiki/Greatest_common_divisor) ดูก็ได้ เราก็จะพบว่ามันมีวิธีการหา ห.ร.ม. ยั้วเยี๊ยเต็มไปหมด ซึ่งแต่ละวิธีก็จะมี ข้อดีข้อเสีย ที่แตกต่างกัน แต่ได้ผลลัพท์เดียวกันนั่นเอง
{% endhint %}

## 😅 มันจำเป็นต้องรู้ด้วยเหรอ?

นั่นซินะ! แมวน้ำพูดเต็มปากเลยว่า **ไม่จำเป็น** ถ้าซอฟต์แวร์ที่คุณจะสร้างมันไม่ได้มีอะไรซับซ้อนวุ่นวายอะไรนัก แต่มันจะ **โคตรจำเป็นถ้าคุณต้องการเขียนซอฟต์แวร์ที่มีความซับซ้อน หรือ ต้องการเป็น Software Architecture ที่ดี** ดังนั้นจะอ่านต่อหรือไม่อ่านต่อก็ขึ้นอยู่กับการเลือกตรงนี้ได้เลย

## 🤔 พูดให้เห็นภาพหน่อยได้ไหม?

จัดไป! ... **สมมุติว่าเราต้องเขียนเว็บง่ายๆ 1 ตัว แล้วให้มันมี ระบบนับยอดคนดู เราจะทำยังไง?**

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

![](https://479516123-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lm0_idNbY6k1lwp6hm4%2F-MDqzM6BTIjpcOVfPIG_%2F-MDr-rZ6kW_ALhwnDPun%2Fimage.png?alt=media\&token=2f5044bb-7439-4530-be03-6c3a7d15bc5a)

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

![](https://479516123-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lm0_idNbY6k1lwp6hm4%2F-MDqzM6BTIjpcOVfPIG_%2F-MDr1x24sc5hhExVoQSE%2Fimage.png?alt=media\&token=d8cc835e-f2bd-4a2b-b6d2-efbfdc95e7ea)

อะเช พอมาถึงจุดนี้ความสำคัญของ Algorithm & Data Structure มันจะเริ่มแผลงฤทธิ์ให้เราเห็นความสำคัญของมันมากขึ้นคือ โครงสร้างที่เป็น **Centralized system** แบบในรูปด้านบน มันจะมีคอขวดที่จะทำให้ระบบล่มได้ง่ายๆ เช่น สมมุติว่าตัว Database ที่เลือกใช้มีความสามารถรับการเขียนได้ 100 ครั้ง/วินาที แล้วจะเกิดอะไรขึ้นถ้ามีคนเข้าเว็บเกิน 100 คน/วินาทีกันล่ะ? . . . เมื่อหัวใจมันล่มระบบก็ตายนั่นเอง

{% hint style="danger" %}
**Single point of failure**\
จุดอ่อนของระบบที่เป็น Centralized System คือ ถ้าตัวกลางตาย ทั้งระบบก็จะมีปัญหา ซึ่งการแก้ปัญหาแบบกากสุดก็คือ เพิ่มตัวกลางหลายๆตัว ซึ่งมันก็จะมีปัญหาในอีกรูปแบบตามมา เช่นการทำ synchronization บลาๆ
{% endhint %}

จากที่ว่ามานี่คือตัว ขีดจำกัดของ Architecture ประเภทนี้ ดังนั้นถ้าเราอยากที่จะแก้ปัญหาที่เป็น Centralized System เราก็จะต้องเลือก Algorithm & Data Structure ที่เหมาะกับ Architecture ของมันนั่นเอง

## 😒 Algorithm มันเกี่ยวไร ?

จากปัญหาตัวนับคนที่ว่ามา ถ้าเราเลือก Algorithm ที่ต่างกัน ผลลัพท์กับ Architecture ก็จะไปกันคนละโลกเลย เช่น  เรายอมให้ตัวเลขคนเข้าเว็บมันคลาดเคลื่อนได้นะ แต่ถ้าปล่อยไว้ซักพักเดี๋ยวมันจะถูกเอง ซึ่งเราเรียกของแบบนี้ว่า [Eventual consistency](https://en.wikipedia.org/wiki/Eventual_consistency) นั่นเอง

{% hint style="success" %}
**Eventual consistency**\
เป็นหลักที่ยอมให้ไม่สอดคล้องกันได้ แต่สุดท้ายจะสอดคล้องกันเอง พูดแล้วอาจจะ งงๆ แต่ที่เราเคยเจอแน่ๆคือ ยอดคนดูวีดีโอของ Youtube ยังไงล่ะ มันไม่ใช่ยอดที่อัพตลอดเวลา ซึ่งวีดีโอเดียวกันอาจจะเห็นยอดคนดูต่างกันก็ได้ ซึ่งปล่อยทิ้งไว้ซักพัก เดี๋ยวเลขนั้นมันก็จะเป็นยอดคนดูที่ถูกต้องเอง ซึ่งแนวคิดนี้มาจากการทำ  Distrubuted System ยังงุยล่ะ
{% endhint %}

จากที่ว่ามาเมื่อเราเลือก Algorithm ที่เป็น Eventual consistency แล้ว เราก็ต้องมี Data Structure ที่เหมาะกับกับ Architecture ในลักษณะนั้นด้วยมันถึงจะทำงานร่วมกันได้ ตามรูปเลย

![เข้าใจหลักพื้นฐานนี้คได้ก็เริ่มอ่าน Blockchain ต่อได้เลยนะ หุหุ](https://479516123-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lm0_idNbY6k1lwp6hm4%2F-MDr74JYVJPwZk546CkK%2F-MDrFupndUZaiNPpGJxG%2Fimage.png?alt=media\&token=35ea6553-8683-4899-ae1c-45cb38cf51e0)

> **อธิบายรูปนิสนุง**\
> เซิฟเวอร์แต่ละตัวทำการนับยอดของใครของมัน ซึ่งเมื่อยอดตัวมันเองเปลี่ยน มันก็จะแจ้งไปบอกเพื่อนๆของมันด้วยเสมอ ทำให้แต่ละเซิฟเวอร์ทำงานแยกออกจากกันได้ ไม่เกิด Single point of failure ขึ้น

เหมือนเรื่องราวจะจบแล้ว แต่ยัง!! เพราะอย่างที่เคยบอกไปว่าทุก Algorithm **ทุก Architecture ย่อมมีข้อดี และ ข้อเสีย หรือ ขีดจำกัดทางสายเลือดของมันเสมอ** ซึ่งจากรูปด้านบน การทำงานของเซิฟเวอร์แต่ละตัวจะต้องส่งผ่าน network / internet ดังนั้นมันก็จะมีปัญหาเรื่อง ส่งถึงบ้างไม่ถึงบ้าง, ข้อมูลที่ส่งไปก่อนถาจจะถึงช้ากว่าตัวที่ส่งไปทีหลัง, Concurrency บลาๆ ซึ่งทั้งหมดทั้งมวลมันจะก่อให้เกิดสิ่งที่เรียกว่า **ความขัดแย้ง (Conflict)** ได้ เช่น เซิฟเวอร์ A บอกว่ายอดรวมตอนนี้เป็น 3 แสนคนนะ แต่ B บอกว่าไม่ใช่ 5 แสนต่างหาก ส่วน C บอกว่า 9 ล้านคนเฟร้ย และ D บอกว่าของตรูพึ่งนับได้ 1 พันคนเอง ... แล้วเราจะแก้ปัญหาความขัดแย้งนี้ยังไง?

{% hint style="success" %}
**Conflict**\
อย่างที่บอกว่าทุกอย่างย่อมมีปัญหาของมัน ซึ่งหนึ่งในการแก้ปัญหานี้ของ Distructured system คือการทำ [**Consensus algorithm**](https://www.saladpuk.com/cloud/blockchain/consensus-algorithm) (สนใจก็กดที่ชื่อมันไปอ่านต่อว่าทำยังไงเอานะ ผมอธิบายไว้ในบทความของ Blockchain พื้นฐานไว้ละ)
{% endhint %}

และจากที่เคยบอกว่า ปัญหา ไม่ได้มีคำตอบเดียวเสมอ และคำตอบแต่ละอันก็จะมีจุดเด่น/ข้อจำกัดที่ต่างกัน ดังนั้นถ้าเรารู้จัก Algorithms หลายๆแบบ เราก็จะสามารถ เลือกสิ่งที่เหมาะสมกับระบบได้อย่างมีประสิทธิภาพ เช่น ในตัวอย่างนี้ถ้าไม่อยากวุ่นวายเราก็สามารถทำ **Strong eventual consistency** ได้ แต่มันจะเหมาะสมกับหน้างานหรือเปล่า และข้อจำกัดของมันคืออะไร ก็ต้องว่ากันไปตามโจทย์ที่เราเจอ

## 🎯 บทสรุป

เวลาที่เจอโจทย์ **สิ่งที่โปรแกรมเมอร์ควรจะต้องทำไม่ใช่เขียนโค้ด แต่เป็นการมองหา Solution ที่เหมาะกับปัญหา และเลือก Data structure ที่เหมาะสมกับปัญหา + Architecture ที่เจอ** แล้วเราจะรู้ขีดจำกัดทางสายเลือดของมัน เพราะโปรแกรมเมอร์ที่เป็นตำแหน่งสูงขึ้นที่แท้จริงคือ ความแม่นยำในการออกแบบและตัดสินใจนั่นเอง

ยิ่งเรามีความรู้ของ Architecture & Algorithm ที่เยอะขึ้น เวลาที่มี feature ใหม่ๆเข้ามา เราก็จะรู้ได้ทันทีว่า Architecture ที่เรามีสามารถรองรับการทำงานพวกนั้นได้หรือเปล่า มิเช่นนั้นมันจะเหมือนกับเราจะขับรถไปญี่ปุ่น โดยที่ลืมคิดเลยว่า ญี่ปุ่นมันเป็นเกาะมีแต่ทะเลล้อมรอบ แล้วเราก็จะมีงานงอกเพื่อให้เราขับรถไปถึงญี่ปุ่นได้โดยไม่จำเป็น เพราะถ้าเรามองแต่แรกเราก็จะพบ Solution อื่นที่อาจจะดีกว่าก็ได้ เช่น นั่งเครื่องบิน

{% hint style="success" %}
**ท่องไว้จำจงดี**\
1 ซอฟต์แวร์ ➡️ มีหลายปัญหา (Problems)\
1 ปัญหา ➡️ มีหลายคำตอบ (Algorithms)\
1 คำตอบ ➡️ เขียนโค้ดได้หลายแบบ (Data Structure)\
\
**1 ปัญหา** ➡️ อาจเกิดจากหลาย Context หลาย Domain ดังนั้นตอนที่แก้ปัญหาต้องดูให้ครบทุก Context & Domain มิเช่นนั้น มันจะแก้ตรงนี้ได้ แต่มีปัญหางอกที่จุดอื่นที่เกี่ยวข้องกับมัน

**1 คำตอบ** ➡️ อาจเป็นวิธีที่ดีที่สุดสำหรับบางสถานะการณ์ และอาจเป็นวิธีที่ห่วยที่สุดในบางสถานะการณ์ก็ได้

**1 Data Structure** ➡️  อาจะเป็นวิธีที่เร็วที่สุด แต่อาจจะไม่เหมาะสมกับ Architecture ที่ใช้อยู่ก็ได้
{% endhint %}

![](https://479516123-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lm0_idNbY6k1lwp6hm4%2F-MDr_xQjdBhZWI_fJRUr%2F-MDrwPqd24wBbRtq21qk%2F1_bPpvELo9_QqQsDz7CSbwXQ.gif?alt=media\&token=10e19073-e9fa-429f-88d8-172e9443910e)
