เล่มที่ 25
การพัฒนาซอฟต์แวร์
สามารถแชร์ได้ผ่าน :
กระบวนการพัฒนาซอฟต์แวร์

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

            ถ้าพบข้อผิดพลาดช่วงแรกๆ ก็จะช่วยลดระยะเวลา และค่าใช้จ่าย ในการพัฒนาซอฟต์แวร์ได้มาก การศึกษาเรื่องค่าใช้จ่ายด้านซอฟต์แวร์ของบริษัทไอบีเอ็ม (IBM) บริษัทจีทีอี (GTE) และบริษัททีอาร์ดับเบิลยู (TRW) โดยนายแบรี่ บีม (Barry Boehm) ในปี ค.ศ. ๑๙๓๖ พบว่า ถ้าแก้ไขข้อผิดพลาด เมื่อพัฒนาซอฟต์แวร์เสร็จแล้ว แทนที่จะแก้ไขตั้งแต่ตอนที่กำหนดคุณลักษณะของซอฟต์แวร์ ก็จะต้องเสียค่าใช้จ่ายเพิ่มขึ้นเป็นร้อยเท่า ตัวอย่างของปัญหานี้เห็นได้อย่างชัดเจน ในการแก้ปัญหาคอมพิวเตอร์ ปี ค.ศ. ๒๐๐๐ หรือที่เรียกว่า ปัญหาวายทูเค (Y2K) บริษัที่ออกแบบซอฟต์แวร์ให้ใช้กับปีที่มีเลขสี่หลักตั้งแต่ต้นแทบจะไม่เดือดร้อนในการแก้ไขเลย แต่ซอฟต์แวร์อื่นๆ ที่ทั้งผู้ผลิตและผู้ใช้ต่างละเลยปัญหานี้ โดยยังคงใช้ปีเป็นเลขสองหลักอยู่ บางรายใช้อยู่เป็นสิบๆ ปี เมื่อถึงเวลาแก้ไขข้อผิดพลาดของซอฟต์แวร์ ก็ปรากฏว่าต้องใช้เงินเป็นจำนวนมากถึงหลายสิบล้านบาท ร้อยล้านบาท หรือมากกว่านั้น

การพัฒนาซอฟต์แวร์อย่างมีขั้นตอน

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

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

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

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

๑. กำหนดคุณลักษณะซอฟต์แวร์ (Definition)

            เน้นว่าจะ "สร้างอะไร" โดยให้คำตอบว่า "โจทย์ปัญหาที่ต้องการแก้คืออะไร" และ "สิ่งที่จะใช้แก้ปัญหานี้คืออะไร"

๒. สร้างซอฟต์แวร์ (Development)

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

๓. วิวัฒนาการของซอฟต์แวร์ (Evolution)

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

            แม่แบบของกระบวนการการพัฒนาซอฟต์แวร์ที่เป็นขั้นตอนที่เก่าแก่ที่สุดนั้น เรียกกันว่า แม่แบบแบบขั้นน้ำตก (Waterfall Model) ซึ่งเมื่อลากเส้นเชื่อมต่อแต่ละขั้นตอนลงไป จนถึงขั้นตอนสุดท้ายแล้ว ก็จะมีลักษณะคล้ายน้ำตก



แม่แบบแบบขั้นน้ำตก

ขั้นตอนหลักๆ ของแม่แบบขั้นน้ำตก มีดังนี้

๑. วิเคราะห์ความเป็นไปได้

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

๒. วิเคราะห์โจทย์หรือความต้องการของผู้ใช้

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

            เนื่องจากโจทย์ปัญหาดังกล่าวอาจจะเป็นปัญหาใหญ่ ดังนั้น จะต้องมีการวิเคราะห์ และแยกย่อยปัญหา (Problem Decomposition) กำหนดขอบเขตปัญหาที่จะให้ซอฟต์แวร์แก้ไข (software scope) และต้องทำความเข้าใจให้ได้ว่า ผู้ใช้ต้องการอะไร งานส่วนนี้จะเป็นประเด็นสำคัญในการวางแผนพัฒนาซอฟต์แวร์ รวมทั้งประเมินระยะเวลา และค่าใช้จ่ายด้วย

๓. เขียนคุณลักษณะซอฟต์แวร์

            คุณลักษณะซอฟต์แวร์ (Software Specification) เป็นข้อกำหนดลักษณะหน้าที่ และวิธีการทำงานของซอฟต์แวร์ว่า ซอฟต์แวร์นี้ต้องทำอะไรบ้าง จึงจะสนองความต้องการของผู้ใช้ เช่น จะต้องใช้ข้อมูลอะไร จะจัดเก็บข้อมูลอะไร จะผลิตหรือประมวลผลข้อมูลอะไร ลักษณะของข้อมูลเป็นอย่างไร มีขอบเขตข้อจำกัดอะไร ฯลฯ

            การกำหนดคุณลักษณะซอฟต์แวร์สามารถ ทำได้หลายวิธี เช่น
  • สอบถามผู้ใช้โดยตรงว่า ต้องการให้ซอฟต์แวร์ทำหน้าที่อะไรบ้าง การสอบถามต้องมีเทคนิคในการสื่อสารที่ดี โดยอาจจะมีการยกตัวอย่างสภาพการณ์ (scenario-based requirement analysis) ในแนวว่า "ถ้า (สถานการณ์) เกิดขึ้น จะทำอย่างไร" เช่น ถ้าโจทย์คือ การจัดการพัสดุของร้านค้า นักวิเคราะห์ระบบอาจถามว่า "ถ้าสินค้าที่สั่งซื้อไม่มาส่งตามกำหนด ทางร้านจะทราบได้เมื่อใด และจะดำเนินการอย่างไร"
  •  ศึกษาวิธีการดำเนินงานตามปกติก่อนนำคอมพิวเตอร์มาใช้ และหาจุดอ่อนที่จะต้องนำซอฟต์แวร์เข้ามาใช้ เพื่อเพิ่มประสิทธิภาพ 
  • สำรวจความต้องการของตลาดว่า คนส่วนใหญ่ต้องการให้คอมพิวเตอร์ช่วยงานด้านใด ในลักษณะใด และต้องการความบันเทิงจากคอมพิวเตอร์อย่างไร ฯลฯ 
  • ศึกษาจากลักษณะของซอฟต์แวร์เก่าที่ทำงานด้านนี้อยู่แล้ว ฯลฯ 
            สรุปผลการวิเคราะห์ข้อกำหนดลักษณะของซอฟต์แวร์สามารถแบ่งได้เป็น ๓ รูปแบบ คือ รูปแบบข้อมูล รูปแบบหน้าที่งาน และรูปแบบการทำงาน วิธีการนำเสนออาจแสดงเป็นแผนผังแบบต่างๆ เช่น แสดงด้วยแผนผังการไหลของข้อมูล (Data Flow Diagram) แสดงด้วยแผนผังความสัมพันธ์ของข้อมูล (Entity - Relationship Diagram) ฯลฯ ส่วนศัพท์ว่าข้อมูลใดคืออะไร จะต้องอธิบายอยู่ในพจนานุกรมข้อมูล (Data Dictionary)


๔. ออกแบบซอฟต์แวร์

            การออกแบบซอฟต์แวร์จะเริ่มเน้นด้านเทคนิค โดยรวมถึงการออกแบบโครงสร้างของซอฟต์แวร์หน่วยต่างๆ ของซอฟต์แวร์ ซึ่งสามารถนำเสนอได้ด้วยแผนผังหลายแบบ เช่น แผนผังโครงสร้างระบบ (Structure Chart) และรายละเอียดขั้นตอนในการแก้ปัญหา (algorithm) ของแต่ละหน่วย นอกจากนี้ ยังรวมถึงการออกแบบวิธีที่ซอฟต์แวร์จะสื่อสารกับผู้ใช้ เช่น ออกแบบหน้าจอ ออกแบบวิธีรับคำสั่งจากผู้ใช้ (จะให้ผู้ใช้พิมพ์คำสั่ง หรือกดปุ่มเรียก หรือพูดด้วย ฯลฯ)

๕. เขียนซอฟต์แวร์

            การเขียนซอฟต์แวร์ หรือโปรแกรม เป็นการเขียนชุดคำสั่งให้คอมพิวเตอร์ทำงาน ภาษาที่ใช้เขียนซอฟต์แวร์มีอยู่หลากหลาย ได้แก่ ภาษาเบสิก (BASIC) ภาษาฟอร์แทรน (FORTRAN) ภาษาโคบอล (COBOL) ภาษาซี (C) ภาษาวิชวลเบสิก (Visual Basic) ภาษาจาวา (Java) ภาษาเพิร์ล (PERL) ภาษาเดลไฟ (Delphi) ฯลฯ ซึ่งควรจะเขียนเป็น หน่วยเล็กๆ ก่อน โดยแต่ละภาษาอาจจะมีรูปแบบ หน่วยที่ต่างกัน

            เมื่อเขียนเสร็จแล้ว ก็ควรจะทดสอบความถูกต้องในการทำงานของแต่ละหน่วย ด้วยการทดสอบซอฟต์แวร์ (software testing) ว่าถูกต้องตามข้อกำหนด ตรงตามความต้องการของผู้ใช้ มีคุณภาพตามต้องการ และหาข้อผิดพลาด เพื่อแก้ไขชุดคำสั่งให้กำจัดข้อบกพร่องนั้นๆ (software debugging)

๖. รวมหน่วยย่อยของซอฟต์แวร์

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

๗. นำซอฟต์แวร์ไปใช้

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

๘. ใช้ซอฟต์แวร์ในการทำงานจริง

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

๙. ทำนุบำรุงซอฟต์แวร์

            ขณะที่ใช้ซอฟต์แวร์อยู่ ก็ยังต้องมีการทำนุบำรุงซอฟต์แวร์ เช่น

            (๑) แก้ไขซอฟต์แวร์ (correction) เมื่อพบข้อผิดพลาด
            (๒) ขยายหน้าที่ของซอฟต์แวร์ (enhancement) เมื่อผู้ใช้ปรับเปลี่ยนความต้องการไป
            (๓) ปรับให้ซอฟต์แวร์ทำงานในสภาพแวดล้อมที่เปลี่ยนไป (adaptation) เช่น มีกฎระเบียบใหม่ออกมา ทำให้โจทย์ปัญหาเปลี่ยนไป หรือคอมพิวเตอร์เปลี่ยนรุ่น ฯลฯ
            (๔) การรื้อแล้ว สร้างใหม่ (software re-engineering) เพื่อปรับโครงสร้างซอฟต์แวร์เก่า พัฒนาซอฟต์แวร์ใหม่ ให้มีคุณภาพ และทำให้การแก้-ขยาย-ปรับ ทำได้อย่างสะดวก และประหยัดในระยะยาว

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

วิธีการตรวจสอบแก้ไข

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

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

การทดสอบความต้องการ

            รวมถึงการจัดทำกรณีทดสอบ (test case) การทดสอบ และการหาจุดบกพร่องในโปรแกรม ที่ต้องแก้ไข กรณีทดสอบทั่วไปมักระบุข้อมูลขาเข้าที่เป็นอินพุต (input) ของซอฟต์แวร์ และระบุข้อมูลขาออก หรือลักษณะการโต้ตอบที่ควรเป็นเอาต์พุต (output) ของซอฟต์แวร์ การจัดทำกรณีทดสอบที่ดีควรครอบคลุม ทั้งภายนอก (Black - box testing) และภายใน (White-box testing) การทดสอบครอบคลุมภายนอก ถ้ามีการณีที่ทดสอบอินพุต และเอาต์พุต ทุกประเภท หรือการทดสอบครอบคลุมภายใน ถ้ามีกรณีที่ทดสอบทุกโปรแกรมย่อยภายใน โดยต้องทำให้ทุกคำสั่งในซอฟต์แวร์ถูกเรียกใช้

            การทดสอบให้ครอบคลุมมักมีกรณีทดสอบเป็นจำนวนมาก เทคนิคในการทดสอบ (testing technique) มักเสนอวิธีเลือกกรณีทดสอบให้มีพอประมาณ แต่ก็ยังครอบคลุมประเด็นหลักๆ อยู่ ตัวอย่างเช่น การทดสอบโปรแกรมหาเศษจากการหารเลขที่คืนค่าเศษที่เป็นเลขหลัก อินพุตจะ เป็นตัวตั้ง และตัวหาร ส่วนเอาต์พุตจะเป็นคำตอบ

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

            เอาต์พุต ทุกประเภทแยกได้เป็น ๓ กรณี คือ หารลงตัว หารไม่ลงตัว และหารไม่ได้

หากรวมการทดสอบทุกรูปแบบแล้ว ก็จะมี กรณีมากถึง ๓ x ๒ x ๓ x ๓ คือ ๕๔ กรณี แต่เนื่องจากระยะเวลาในการทดสอบมักมีจำกัด กรณีที่ทดสอบจริงอาจเลือกเพียง ๑๐ กรณี ได้แก่

            ๑. ตัวตั้งและตัวหารเป็นเลขหลักเดียว หารลงตัว
            ๒. ตัวตั้งและตัวหารเป็นเลขหลักเดียว หารไม่ลงตัว
            ๓. ตัวตั้งและตัวหารเป็นเลขหลายหลัก หารลงตัว
            ๔. ตัวตั้งและตัวหารเป็นเลขหลายหลัก หารไม่ลงตัว
            ๕. ตัวหารเป็นศูนย์ หารไม่ได้
            ๖. ตัวตั้งหรือตัวหารไม่ได้เป็นตัวเลข หารไม่ได้
            ๗. ตัวตั้งหรือตัวหารเป็นเลขติดลบ
            ๘. ตัวตั้งมีค่ามากกว่าตัวหาร
            ๙. ตัวตั้งมีค่าน้อยกว่าตัวหาร
            ๑๐. ตัวตั้งมีค่าเท่ากับตัวหาร

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