03 กุมภาพันธ์, 2558

ทำไมถึงต้องเขียนโปรแกรมแบบ OOP กัน? เขียนแบบซัดโค้ดตู้มเดียวที่เคยทำตอนเริ่มเรียนเขียนโปรแกรมไม่ได้เหรอ

ตั้งแต่ปีใหม่ เหมือนตัวเองเขียนแต่บล๊อกแปลบทความ ยังไม่มีบทความออริจินอลเลย คิดไปคิดมาเขียนเรื่อง OOP ดีกว่า เพราะช่วงนี้ไปดูโค้ดน้องหลายคนแล้วเขียนกันแบบ Structure ตรงๆ ซึ่งช่วยแก้ได้ยากมาก มาเขียน OOP กันเถอะเพื่อชีวิตที่ดีขึ้น (มั้งตัวเองและผู้อื่นเลยนะ)

ก่อนอื่นต้องมาทำความเข้าใจคำว่า OOP กันก่อนนะ

OOP ย่อมาจาก Object Oriented Programming แปลเป็นไทยว่า "การเขียนโปรแกรมแบบวัตถุ" ! ห๊ะ...แปลออกมายิ่งงงเข้าไปใหญ่

งั้นขอย้อนกลับไปหน่อย ปกติแล้วทุกคนมักจะเรียนเขียนโปรแกรมครั้งแรกอาจจะเป็นภาษา C, Java (หรือภาษาอะไรก็ตามเถอะ) ตอนนั้นเรายังไม่สนใจว่าภาษาโปรแกรมที่เราเรียนกันอยู่นั่นน่ะเป็นภาษาแบบไหนเพราะแค่ทำความเข้าใจ if-else loop function อะไรพวกนั้นก็เต็มหัวไปหมดแล้ว

ขอยกตัวอย่างภาษา C ละกัน สำหรับคนที่เคยเขียนมาแล้วน่าจะคุ้นกับเจ้านี่
void main()
{
    //เราจะซัดโค้ดทั้งโปรแกรมลงในนี้แหละ
}
จริงมั้ยล่ะ ตอนเรียน C ไม่ว่าจะเขียนโปรแกรมเล็กแบบ Hello World หรือโปรแกรมใหญ่ๆ ระดับ Final Project ตอนท้ายเทอมเป็นพันบรรทัดเราก็ยัดมันลงไปใน void main นี่แหละ (ถ้าใครเก่งหน่อยก็อาจจะมีการแยกโค้ดออกมาเป็น function บ้าง แต่คิดว่ารุ่นนึงน่าจะมีไม่เยอะที่ทำ) แต่โดยรวมก็คือเขียนคำสั่งต่อเนื่องไปเรื่อยๆ อาจจะมีบางส่วนที่ชวนปวดหัวบ้าง แต่ก็ยังไปถึงปลายทางได้แหละน่า


อ่านมาถึงตรงนี้อาจจะมีคำถามเกิดขึ้นว่า แล้วมันไม่ดียังไงเหรอ? เขียนออกมาแล้วโค้ดก็ทำงานได้นะ

โอเค โค้ดทำงานได้แต่ต้องมีอะไรที่มันไม่ดีแน่ๆเขาถึงคิดวิธีการเขียนโปรแกรมแบบอื่นขึ้นมาใช้แทน

Structure VS Object

รู้ไหมว่าการเขียนโปรแกรมโดยซัดโค้ดทุกอย่างลงไปกระจุกอยู่ใน void main ตัวเดียวเนี่ยเขาเรียกว่าการเขียนโปรแกรมแบบ "Structure Programming"
อธิบายง่ายๆ คือเขียนโค้ดทีละบรรทัดเพื่อบอกให้คอมพิวเตอร์ทำอะไรไปเรื่อยๆ วิธีนี้เป็นวิธีที่เคยฮิตสมัยเพิ่งมีภาษา C แน่นอนว่าสำหรับยุคนี้มันเก่าไปแล้ว

เหตุผลล่ะ?

ทำงานเป็นทีมได้ยาก

เรื่องแรกที่เป็นจุดอ่อนของ Structure Programming คือมันทำงานเป็นทีมได้ยาก เคยทำงานเป็นคู่หรือเป็นกลุ่มไหม ตอนที่ต้องเขียนโปรแกรมมากกว่า 1 คนคุณทำยังไงล่ะ

อืม... ทางเลือกมันก็มีไม่เยอะนักหรอกนะ คือไม่นั่งสุมหัวช่วยกันเขียนบทคอมเครื่องเดียว คุณก็แยกงานกันทำแล้วพอเอามาโค้ดมารวมกันก็ระเบิดจ้า!

อ่านไม่รู้เรื่อง / เอาโค้ดมาใช้ใหม่ไม่ได้

ตอนเขียนโปรแกรมแบบ Structure เราอยากทำอะไรก็ทำใช่ไหม อยากประกาศตัวแปรเพิ่มก็ประกาศ ตรงนี้เกิดปัญหา งั้นวาง if ดักไว้ละกัน โค้ดตรงนี้เป็นส่วนแสดงผลนะ และอื่นๆ อีกมากมาย
คือมันให้เราทำอะไรก็ได้ ดังนั้นมันจึง "อ่านยาก"

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

อีกเรื่องหนึ่งคือเอาโค้ดที่เคยเขียนมาแล้วมาใช้ใหม่ไม่ได้ อยากเราเคยเขียนโปรแกรมหาค่าเฉลี่ยคะแนนนักเรียนไปเมื่อสองวันก่อน วันนี้ต้องมาเขียนโปรแกรมหาค่าเฉลี่ยเงินเดือนพนักงาน เอ๊ะ! มันคล้ายๆ กันนะ ใช้โค้ดเก่าเลยได้มั้ย ... จากนั้นก็เปิดงานเก่า copy+paste ซะแล้วก็ปรับๆ อีกนิดหน่อย ถ้าปรับได้ก็ดีไป ถ้าไม่ได้ยิ่งปรับยิ่งเละกว่าเดิมจนถึงระดับที่คิดได้ว่าเขียนใหม่มันดีกว่า

....


เอาล่ะ แค่สองเหตุผลที่ว่าไปเมื่อกี้ก็เพียงพอละที่จำทำให้โปรแกรมเมอร์สมัยก่อนเขาคิดเรื่อง Object กันขึ้นมาเพื่อแก้ปัญหาพวกนั้น (แต่สำหรับคนไม่เข้าใจ Object มักจะติดว่าแกนั่นแหละคือปัญหา)


ถึงเวลาแล้วที่เราจะมองทุกสิ่งเป็น Object!

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

แล้วอะไรคือมองโค้ดเป็นพันๆ บรรทัดพวกนั้นให้เป็นก้อนๆ ลองดูตัวอย่างต่อไปเลย

Ex. มีโจทย์ให้เราเขียนโปรแกรมสำหรับดึงข้อมูลนักเรียนทุกคนออกมาจากไฟล์ excel แล้วเอามาแสดงเป็นกราฟแท่งว่านักเรียนที่ได้คะแนนแบบนี้ๆๆๆ มีกี่คนยังไงบ้างอะไรแบบนั้น

สำหรับโปรแกรมเมอร์มือใหม่ที่เขียนเป็นแต่ C มาก็จำมีความคิดประมาณนี้
void main()
{

    1.1 ก็ต้องเขียนโค้ดอ่านไฟล์ excel ซะก่อนนะ
    1.2 สร้างตัวแปรเอาไว้อ่านไฟล์ขึ้นมาก่อน
    1.3 ให้ตัวแปรนั้นชี้ไปที่ไฟล์ excel ซะ
    1.4 ก็ต้องวนลูปอ่านข้อมูลเข้ามาสินะ
    1.5 เอาข้อมูลที่อ่านเข้ามา เก็บไว้ในตัวแปร A ละกัน ยังชิวๆ อยู่
   
    2.1 เขาอยากให้เราแสดงผลคะแนนแบบนั้นๆๆๆ เราก็ต้องเอาตัวแปร A มาทำแบบนี้ๆๆๆ ซะก่อนสินะ
    2.2 อ่ะ ก็วนลูปทำไปสิ
    2.3 ผลลัพท์ที่ได้เก็บไว้ในตัวแปร B ละกัน
   
    3.1 แล้วก็เอาข้อมูลมาวาดกราฟสินะ ต้องใช้ข้อมูล B ที่ผ่านการคิดมาแล้ว
    3.2 แต่เอ๊ะ! เราต้องใช้ข้อมูลจาก A มาวาดด้วยนี่นา
    3.3 งั้นก็เขียนโค้ดแปลงตรงนี้หน่อยละกัน
    3.4 โค้ดตรงนี้มึนจัง ตัวแปร C นี่มันโผล่มาตั้งแต่เมื่อไหร่
    3.5 แต่ไม่เป็นไร ทำแบบ @#$%&* คงแก้ได้
    3.6 เย่ ในที่สุดก็ได้ออกมาเป็นกราฟแล้ว
}
หลังจากเขียนโปรแกรมอยู่หลายวัน (?) ในที่สุดเราก็เอาไปส่งได้ โอ๊ย น้ำตาจะไหล

แต่ทว่า!!!

โจทย์มีการเปลี่ยนแปลงล่ะ! เขาไม่อยากให้เราอ่านข้อมูลคะแนนนักเรียนจาก "ไฟล์excel" ซะแล้ว แต่ให้ไปอ่านจาก Database แทน

ป.ล. จงคิดไว้ว่า โจทย์ (Requirement) นั้นมีโอกาสเปลี่ยนได้เรื่อยๆ ไม่ว่าตอนเรียนหรือในชีวิตจริงขณะทำงานแล้ว

เอาละสิ เพื่อคะแนน (และเงิน) เราก็ต้องกลับไปแก้โค้ดที่เราเขียนมา เปิดโค้ดมาดูใหม่อีกรอบ ช่วง 1.1 - 1.5 นั่นเป็นส่วนอ่านข้อมูลเข้านี่นา แก้แค่นี้ก็พอมั้ง เริ่มมีความหวังว่ามันจะเสร็จ

แล้วพอลงมือทำก็เริ่มตระหนักได้ว่าข้อมูลที่มาจาก Database มันคนละแบบกับข้อมูลจากไฟล์excelล่ะ ต้องเก็บในตัวแปร A อีกแบบกับวิธีแรก

โอ๊ะโอ! งั้นตรงโค้ดส่วน 2.1 ก็ต้องไปแก้ด้วยสิ เพราะจะได้ B มาต้องมี A ก่อน T_____T



โค้ดมั่วซั่วซับซ้อนยังกะรางรถไฟ เหมือนจะแก้ได้ แต่ก็ไม่ได้ซะที
สรุป ทำไปทำมา เขียนใหม่ดีกว่า...

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


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

ในตัวอย่างนี้เรามองว่าถ้าคนคุยกันเองว่าวิธีการเขียนโปรแกรมนี้ทำอย่างไรบ้างก็คงได้ว่า จะต้องมี
- ตัวจัดการข้อมูล ที่ไม่ว่าข้อมูลจะมาในรูปแบบไหน เจ้านี้จัดการได้หมด จะคะแนนนักเรียน หรือ เงินเดือนพนักงาน อันไหนก็ได้เลย
- ตัวอ่านข้อมูล ในเมื่อข้อมูลอาจจะมาจากหลาย resource ก็ให้เป็นหน้าที่ของเจ้านี่ไปจัดการละกัน ถ้าครั้งนี้เราต้องอ่านไฟล์excelก็ให้มันใช้โค้ดชุดอ่านไฟล์ ถ้าโจทย์เปลี่ยนว่าอยากดึงข้อมูลจาก Database ก็เพิ่มโค้ดอ่านข้อมูลจาก Database ให้มัน
- ในเมื่อเราพบปัญหาเมื่อกี้ว่าข้อมูลจากไฟล์กับ Database มันอยู่ในรูปแบบที่ไม่เหมือนกัน เอาไปใช้ไม่ได้ ก็มองว่ามันเป็น ก้อนข้อมูล อะไรสักอย่างแทนดีกว่า
- ตอนแสดงผล output มีหลายรูปแบบที่เขาอยากได้ งั้นให้เป็นหน้าที่ของ ตัวแสดงผล ดีกว่านะ
- แต่เตรียมทุกอย่างเสร็จแล้วเจ้าพวกนั้นคงไม่ทำงานแน่ ต้องมีคนสั่งให้พวกมันทำงานด้วย

พอเอามาเรียงกันแล้วก็จะออกมาหน้าตาประมาณนี้

(เราจะยังไม่พูดถึงเรื่องโค้ดนะว่าแผนภาพนี้แปลงไปเป็นโค้ดแล้วมันจะออกมาหน้าตาประมาณไหน แต่อ่านเข้าใจง่ายกว่าแบบ Structure แน่ๆ)

ถ้าใครเคยเขียนภาษา Java, C# ที่เป็นภาษาแบบ OOP น่าจะรู้จักกับ Class + Object มาบ้างแล้ว แต่ละก้อนนี่แหละคือ Object หนึ่งตัว ซึ่งเจ้า Object ที่ว่านี่มันจะทำงานเหมือนกับโค้ดที่เราเขียนอยู่ใน Class ของมันนั่นแหละ

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

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

ดังนั้นใครที่คิดว่า OOP เป็นปัญหาอยู่ลองมองมันใหม่นะ มันไม่ได้แย่อย่างที่คิด (แต่ต้องเรียนมันให้เข้าใจก่อน 55)



1 ความคิดเห็น:

  1. ขอบคุณมากค่ะ คือหนูงง oop มานานมากเพราะติดการเขียนแบบ structure อ่านบทความพี่แล้วช่วยได้เยอะเลยคะ

    ตอบลบ