02 March 2014

เขียนโปรแกรมให้เป็น คิดกันอย่างไร? แก้ปัญหากันอย่างไร? - ตอนที่ 2

Updated on

         ต่อจากความเดิมที่เคยพิมไว้ใน [Android Dev Tips] เขียนโปรแกรมให้เป็น คิดกันอย่างไร? แก้ปัญหากันอย่างไร? [ตอนที่ 1] คราวนี้ก็จะมาพิมต่อจากของเดิมเสียหน่อย

        จากเดิมที่จบท้ายไว้ว่าการจะเขียนโปรแกรมเป็นนั้นต้องเริ่มจากพื้นฐานที่ดีก่อน ถ้าพื้นฐานไม่แน่นหรือไม่ดีพอเวลาศึกษาต่อยอดหรือประยุกต์ใช้ก็จะลำบาก เปรียบเสมือนการเล่นเกม Puzzle ซักเกมนั่นเอง

        เกม Puzzle เกี่ยวกันตรงไหนเนี่ย ?

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

        พอลองมองเกม Puzzle เหมือนกับการเขียนโปรแกรมแล้ว เวลาผู้ที่หลงเข้ามาอ่านเขียนโปรแกรมซักตัวหนึ่ง ก็ต้องเริ่มสิ่งแรกคือ ศึกษาว่าภาษาโปรแกรมนั้นๆเขียนยังไง จากนั้นก็ดูว่ามีการใช้งานยังไง การเขียนโปรแกรมภาษานี้ทำอะไรได้บ้าง แล้วจึงเริ่มหัดเขียนจากโปรแกรมง่ายๆไปเรื่อยๆจนถึงโปรแกรมระดับยากๆ ซึ่งถ้าไม่เคยเขียนมาก่อนแล้วไม่คิดจะศึกษาพื้นฐานเลย เวลาเขียนโปรแกรมยากๆแล้วไม่เข้าใจการทำงานของมันก็ไม่ใชเรื่องแปลกแต่อย่างใด


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

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

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


        การศึกษาจากตัวอย่างมันง่ายและไวกว่านี่นา...

        ผู้ที่หลงเข้ามาอ่านหลายๆคนก็คงจะคิดแบบนี้กันอยู่ ซึ่งเจ้าของบล็อกก็เห็นด้วยเช่นกัน ว่าการศึกษาจากตัวอย่างมันช่วยให้เห็นภาพได้ง่ายขึ้น แต่ทว่า

        "วิธีที่ทำนั้นเป็นการศึกษาจากตัวอย่างจริงๆหรือ?"

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


มองให้ลึกลงไปกว่าที่เห็นอยู่

        การศึกษาจากตัวอย่างแท้จริงแล้วควรจะเป็นอย่างไร?

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


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

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

        แก้ปัญหาอย่างไรล่ะ?
     
        เจ้าของบล็อกก็คงบอกได้แค่ว่า "ไปศึกษาพื้นฐานมาสิ..." แต่พื้นฐานนั้นกว้างมาก เจ้าของบล็อกก็เข้าใจได้ว่าอาจจะไม่รู้ว่าจะไปศึกษาพื้นฐานเรื่องอะไรมาบ้าง ก็ใช้วิธีดูว่าในตัวอย่างนั้นมีอะไรที่ผู้ที่หลงเข้ามาอ่านไม่เข้าใจก็นำไปค้นหาเพื่อศึกษาต่อยอดไปเรื่อยๆก็ได้เช่นกัน (ขอเน้นว่าค้นหาแล้วศึกษาให้เข้าใจด้วย)


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


เวลาเขียนโปรแกรมควรคิดอย่างไร?

        การที่จะเริ่มเขียนโปรแกรมซักตัวนั้น ควรจะมีการวางแผนโดยขึ้นอยู่กับว่าโปรแกรมซับซ้อนมากแค่ไหน ยิ่งซับซ้อนมากเท่าไรการวางแผนก็ยิ่งจะเป็นสิ่งที่ขาดไม่ได้เท่านั้น

        ว่าแต่วางแผนยังไงล่ะ?

        มีไม่น้อยเช่นกันที่แม้แต่จะวางแผนโปรแกรมที่จะเขียนก็ยังทำไม่เป็น ไม่รู้ว่าโปรแกรมควรจะมีอะไรบ้าง เริ่มมาทำอะไร ขั้นต่อไปทำอะไร ที่เจ้าของบล็อกเจอบ่อยสุดเลยก็คือ "อยากทำโปรแกรม ...XXX.... ต้องทำอย่างไร"

        ใครๆก็ถามแบบนั้นเป็นปกตินี่? แล้วปัญหาคืออะไร?


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

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

        แล้วควรทำอย่างไรล่ะ?

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


        ยกตัวอย่างเป็นเรื่องที่เจ้าของบล็อกเจอบ่อยมากที่สุดละกัน เป็นเรื่องการปัก Marker บนแผนที่ Google Maps


        เจ้าของบล็อกมีตัวอย่างการปัก Marker ลงบนแผนที่ของ Google Maps ที่ทำไว้ให้ผู้ที่หลงเข้ามาอ่านที่ต้องการใช้งาน Google Maps ได้ดูเป็นตัวอย่าง แต่ทีนี้ก็จะเกิดคำถามต่อมาที่ว่า

        "อยากให้ปัก Marker ตามตำแหน่งที่เก็บไว้ในฐานข้อมูลจะต้องทำอย่างไร?"

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

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

        • อยากให้ผู้ใช้กรอกพิกัดแล้วปัก Marker ตามที่ผู้ใช้กำหนด

        • อยากให้ดึงตำแหน่งจากฐานข้อมูลมากำหนดพิกัดของ Marker

        • อยากให้ดึงข้อมูลจากตำแหน่งของผู้ใช้แล้วแสดงตำแหน่งนั้นๆเป็น Marker

        • อยากให้ดึงข้อมูลพิกัดจากเว็ปเซิฟเวอร์แล้วปัก Marker ตามตำแหน่งที่ดึงมา

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

        คุณอยากเขียนโปรแกรมเป็นหรือเขียนโปรแกรมได้ล่ะ?

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

        จากตัวอย่าง ตัวอย่างที่มีคือ "การปัก Marker ลงบนแผนที่"


        และความต้องการคือ "ดึงพิกัดจากฐานข้อมูลมากำหนดตำแหน่งของ Marker บนแผนที่" ดังนั้นจึงควรพิจารณาก่อนเป็นอย่างแรกว่าความต้องการนั้นประกอบไปด้วยขั้นตอนอะไรบ้าง? ควรทำคำสั่งอะไรก่อน จากนั้นทำคำสั่งอะไรตามลำดับบ้าง เมื่อพิจารณาแล้วก็จะสามารถแบ่งขั้นตอนได้ดังนี้


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

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

        ก็เหลือแค่ว่าเขียนคำสั่งดึงค่าดังกล่าวจากฐานข้อมูลได้หรือไม่ ถ้าเขียนไม่เป็นก็ไปศึกษาการดึงค่าจากฐานข้อมูลดู กำหนดค่าให้กับ Marker เป็นมั้ย ถ้าไม่เป็นก็ไปศึกษาการกำหนดค่าให้กับคลาส Marker ดู แล้วนำมาใช้งานร่วมกับตัวอย่างที่มีในตอนแรก เท่านี้ก็ได้โปรแกรมที่ต้องการแล้ว

        เมื่อคิดแบบนี้ได้ ก็จะสามารถค้นหาและศึกษาต่อด้วยตัวเองได้แล้ว ซึ่งการคิดแบบนี้จะไม่เกิดขึ้นเลยถ้าผู้ที่หลงเข้ามาอ่านไม่มีพื้นฐานมาก่อนและไม่พยายามทำความเข้าใจจากตัวอย่างที่มีอยู่ และจ้องจะมองหาแต่ตัวอย่างเท่านั้น


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


        แต่ก็ผู้ที่หลงเข้ามาอ่านมาถามเจ้าของบล็อกอีกว่า "ถ้าอยากให้ผู้ใช้กำหนดค่าที่นำไปคำนวณต้องทำยังไง?"

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



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

        อ้าว...พูดมาซะยืดยาว แล้วไหนล่ะ? ที่ว่า "การเขียนโปรแกรมควรคิดอย่างไร" ไม่เห็นจะพูดถึงเลย

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

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

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

        การเขียนโปรแกรมควรเริ่มจาก 0 1 2 3 4 5 6 ไปเรื่อยๆจนถึง 10 ถ้าเขียนโปรแกรมจาก 0 แล้วไปถึง 10 ในทันที นั่นไม่เรียกว่าการเขียนโปรแกรม เพราะผู้ที่หลงเข้ามาอ่านจะไม่รู้เลยว่า 1 2 3 4 5 6 7 8 9 คืออะไร ประกอบไปด้วยอะไรบ้าง และ 10 มาได้อย่างไร


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

        และขอสรุปบทความตอนนี้สั้นๆว่า

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


        เอาล่ะ จบตอนที่ 2 แล้วก็ลองไปอ่านต่อกันในตอนที่ 3 เลยคร้าบ [Android Dev Tips] เขียนโปรแกรมให้เป็น คิดกันอย่างไร? แก้ปัญหากันอย่างไร? [ตอนที่ 3]