การพัฒนาระบบด้วยแนวคิดเชิงวัตถุตามแพลตฟอร์ม Microsoft.NET


การพัฒนาระบบด้วยแนวคิดเชิงวัตถุตามแพลตฟอร์ม Microsoft.NET

1. การออกแบบโปรแกรมเชิงวัตถุ

เนื่องจากปัจจุบันแพลตฟอร์ม Microsoft.NET ได้รับความนิยมอย่างสูงในการนำมาสร้างโปรแกรมประยุกต์เนื่องจากผู้เขียนโปรแกรมสามารถเลือกเขียนโปรแกรมได้หลากหลายภาษาเช่นภาษา VB.NET ภาษา C# ภาษา JavaScript.NET และอื่นๆ เพื่อสร้างโปรแกรมสำเร็จรูปที่สามารถนำไปใช้งานข้ามภาษาได้ (Cross-Language) ซึ่งจะทำให้ทีมงานพัฒนาระบบที่หลากหลายสามารถสร้างสรรค์ผลงานได้ด้วยภาษาโปรแกรมที่ตนเองถนัดและนำมารวมเข้าด้วยกันให้กลายเป็นระบบขนาดใหญ่ได้
อย่างไรก็ตามไม่ว่าจะใช้ภาษาโปรแกรมภาษาใดก็ตาม โปรแกรมที่พัฒนาขึ้นจาก Microsoft.NET จะยังคงทำงานร่วมกันได้เสมอเนื่องจากทำงานอยู่บนตัวรันไทม์ที่เรียกว่า CLR (Common-Language Runtime) และไม่ว่าผู้เขียนโปรแกรมจะใช้ภาษาใดก็ตามที่ .NET จัดเตรียมไว้ให้ ผู้เขียนจะต้องมีความรู้เกี่ยวกับการโปรแกรมเชิงวัตถุด้วยเสมอ เนื่องจากภาษาทุกภาษาใน .NET จะมีคุณลักษณะเชิงวัตถุเป็นพื้นฐานองค์ประกอบในการสร้างโปรแกรม
การออกแบบโปรแกรมเชิงวัตถุเป็นพื้นฐานของการสร้างระบบโปรแกรมประยุกต์ขนาดใหญ่ให้มีความยืดหยุ่นสูง ระบบสารสนเทศที่เกิดขึ้นจะมีลักษณะแบบองค์ประกอบโดยจะประกอบขึ้นจากส่วนประกอบย่อยเช่นเดียวกับการสร้างผลิตภัณฑ์ในทางอุตสาหกรรม ดังนั้นแม้ว่าโปรแกรมจะมีขนาดใหญ่และซับซ้อนแต่หากเป็นโปรแกรมเชิงวัตถุแล้วก็จะทำให้เราสามารถปรับเปลี่ยนแก้ไขคุณสมบัติของระบบได้โดยเลือกต่อเติมหรือถอดถอนองค์ประกอบย่อยๆในโปรแกรมได้โดยแทบไม่มีผลกระทบกับโปรแกรมส่วนอื่น ซึ่งก็คือทำให้ระบบที่เกิดขึ้นง่ายต่อการบำรุงรักษาและปรับเปลี่ยนให้ตรงกับความต้องการของผู้ใช้ที่อาจจะแปรเปลี่ยนไปในอนาคตได้

2. องค์ประกอบของวัตถุ

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

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

3. การสร้างคลาสเพื่อใช้เป็นแม่แบบของวัตถุ

การเขียนโปรแกรมเชิงวัตถุจะเริ่มจากการสร้างคลาส (Class) ซึ่งคลาสจะทำหน้าที่เป็นประเภทหรือแม่แบบให้กับวัตถุ ดังนั้นเมื่อผู้ออกแบบระบบพิจารณาแล้วว่าในระบบควรจะมีวัตถุชนิดใดบ้างก็จะนำมาเขียนเป็นคลาสโปรแกรม โดยในคลาสจะจำลองส่วนข้อมูลและส่วนดำเนินงานไว้ในรูปแบบตัวแปรและฟังก์ชัน เราเรียกตัวแปรที่ใช้เก็บข้อมูลประจำตัวของวัตถุนี้ว่าตัวแปรอินสแตนซ์ (Instance Variable) หรือตัวแปรสมาชิก (Member Variable) และเรียกฟังก์ชันที่วัตถุใช้ดำเนินงานว่าเมธอด (Method) หรือฟังก์ชันสมาชิก (Member Function)
ตัวอย่างโปรแกรมต่อไปนี้แสดงการสร้างคลาสโดยใช้ภาษา C# เพื่อจำลองวัตถุประเภทพนักงาน
ซอร์สโค้ด 1 ตัวอย่างการสร้างคลาสในภาษา C#
class Employee
{
    public String firstName;
    public String surname;
    public String code;
    public String status;

 

    public void checkIn()
    {
        status = "working";
    }

    public void checkOut()
    {
        status = "leave";
    }
}
คลาสที่ถูกสร้างขึ้นจะนำมาใช้ประโยชน์สองอย่างคือ นำมาใช้เป็นชนิดของตัวแปรสำหรับอ้างอิงวัตถุ หรือนำมาใช้สร้างชิ้นวัตถุ โดยคลาสหนึ่งคลาสสามารถนำมาสร้างวัตถุขึ้นได้หลายชิ้น การนำคลาสมาสร้างเป็นวัตถุปกติจะใช้คำสั่ง new และตามด้วยชื่อคลาส เช่นหากเรามีคลาส Employee เหมือนกับในตัวอย่างข้างต้น เราสามารถนำมาสร้างเป็นวัตถุได้ดังนี้
ซอร์สโค้ด 2 ตัวอย่างการสร้างวัตถุด้วยภาษา C#
Employee emp1;
emp1 = new Employee();

Employee emp2 = new Employee();
ตัวอย่างข้างต้นเป็นการเขียนโปรแกรมโดยใช้คำสั่ง new เพื่อสร้างวัตถุ Employee ขึ้นมา 2 ชิ้น สังเกตได้จากมีการใช้คำสั่ง new ปรากฏให้เห็น 2 จุดคือที่บรรทัดที่ 2 และที่บรรทัดที่ 3 ในทางปฏิบัติการใช้คำสั่ง new สร้างวัตถุจะเป็นการจัดสรรหน่วยความจำขึ้นเพื่อใช้สำหรับเก็บข้อมูลให้กับวัตถุแต่ละตัว หน่วยความจำที่ใช้วางวัตถุเราเรียกว่าหน่วยความจำฮีป (Heap Memory) เช่นในตัวอย่างนี้ เมื่อทำงานโปรแกรมจนจบ 3 บรรทัด จะได้วัตถุ Employee 2 ชิ้นอยู่ในหน่วยความจำฮีปดังนี้

รูปภาพ 2 การสร้างวัตถุด้วยคำสั่ง new และการจัดสรรหน่วยความจำเพื่อเก็บข้อมูลประจำตัววัตถุ
จะสังเกตเห็นว่าวัตถุทุกตัวที่ถูกสร้างขึ้นด้วยคำสั่ง new จะอาศัยอยู่ในหน่วยความจำฮีปเสมอ แต่การเข้าถึงวัตถุเหล่านี้จะต้องสั่งงานผ่านทางตัวแปรอ้างอิง (Reference Variable) เช่นในภาพข้างต้นนี้เรามีตัวแปร emp1 และ emp2 เป็นตัวแปรอ้างอิง วัตถุที่ไม่มีตัวแปรอ้างอิงแม้แต่ตัวเดียว จะเป็นวัตถุที่ไม่สามารถเข้าถึงและสิ้นเปลืองหน่วยความจำฮีปไปโดยเปล่าประโยชน์ ซึ่งวัตถุพวกนั้นเราเรียกว่าขยะ (Garbage) และหากปล่อยทิ้งไว้สักครู่ระบบจัดเก็บขยะ (Garbage Collection) ก็จะมาทำลายวัตถุและนำหน่วยความจำฮีปกลับคืนมาใช้งานดังเดิม
เราสามารถนำข้อมูลไปเก็บไว้ในวัตถุแต่ละชิ้นได้ โดยอาศัยการเขียนโปรแกรมสั่งงานผ่านทางตัวแปรอ้างอิง เช่นหากเราต้องการให้วัตถุ emp1 ในภาพข้างต้นเก็บชื่อ “Somchai” และให้วัตถุ emp2 เก็บชื่อ “Somying” ก็สามารถเขียนโปรแกรมได้ดังนี้
ซอร์สโค้ด 3 การเก็บข้อมูลไว้ในวัตถุ
emp1.firstName = "Somchai";
emp1.surname = "Rukdee";
emp1.code = "1234";

emp2.firstName = "Somying";
emp2.surname = "Rukchart";
emp2.code = "2431";
หากโปรแกรมทำงานจนครบทั้ง 6 บรรทัดนี้ จะทำให้ข้อมูลในวัตถุ emp1 และ emp2 มีค่าแตกต่างกันดังนี้

รูปภาพ 3 การเก็บข้อมูลไว้ในตัวแปรสมาชิกของวัตถุ
ในการเขียนโปรแกรมเชิงวัตถุจริง โปรแกรมหนึ่งโปรแกรมอาจจะประกอบด้วยวัตถุมากกว่า 1 ชนิดที่มีความสัมพันธ์กัน เพื่อให้เกิดเป็นแบบจำลอง (Model) ที่ใกล้เคียงกับความต้องการของผู้ใช้มากที่สุด เช่นในตัวอย่างข้างต้นนี้ หากผู้ออกแบบระบบพบว่าพนักงานทุกคนจะต้องทำงานภายใต้แผนกใดแผนกหนึ่ง ดังนั้นแบบจำลองเชิงวัตถุที่เกิดขึ้นอาจจะกำหนดให้พนักงานสัมพันธ์กับแผนก โดยมีคลาสชื่อว่า Department เป็นตัวแทนของวัตถุแผนกดังนี้
ซอร์สโค้ด 4 คลาส Department เป็นตัวแทนของแผนก
class Department
{
    public String name;
    public String code;
}
หากแก้ไขคลาส Employee โดยเพิ่มตัวแปรอ้างอิงชื่อว่า department ให้มีชนิดเป็น Department จะทำให้เราสามารถเก็บความสัมพันธ์ระหว่างพนักงานกับแผนกไว้ได้ดังนี้
ซอร์สโค้ด 5 คลาส Employee ที่เพิ่มตัวแปรสมาชิก department สำหรับเก็บความสัมพันธ์ระหว่างพนักงานกับแผนก
class Employee
{
    public String firstName;
    public String surname;
    public String code;
    public String status;
    public Department department;

    public void checkIn()
    {
        status = "working";
    }

    public void checkOut()
    {
        status = "leave";
    }
}
หากเราจำลองให้มีแผนกหนึ่งชื่อว่า Accouting และต้องการให้พนักงาน Somchai และ Somying อยู่ในแผนก Accounting ก็สามารถเขียนโปรแกรมเพื่อเชื่อมโยงตัวแปรอ้างอิงที่อยู่ในวัตถุได้ดังนี้
ซอร์สโค้ด 6 ตัวอย่างการเขียนโปรแกรมเพื่อสร้างความสัมพันธ์ระหว่างวัตถุ
Department dept1 = new Department();
dept1.name = "Accounting";
dept1.code = "AC";

emp1.department = dept1;
emp2.department = dept1;
เมื่อโปรแกรมทำงานผ่านคำสั่ง 5 บรรทัดข้างต้นนี้จะทำให้เกิดวัตถุชนิด Department ขึ้นมาใหม่ 1 ชิ้น และวัตถุ emp1 และ emp2 จะมีตัวแปรสมาชิกชื่อว่า department อ้างอิงไปที่แผนกของตนเองดังภาพต่อไปนี้

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

4. การเข้าถึงและสั่งงานวัตถุ

วัตถุที่สร้างขึ้นด้วยคำสั่ง new จะถูกเข้าถึงผ่านทางตัวแปรอ้างอิงที่เรียกว่า Reference Variable หน้าที่ของตัวแปรอ้างอิงคือใช้กำกับและชี้ตัววัตถุ เพื่อให้โปรแกรมสามารถเลือกได้ว่าจะควบคุมวัตถุตัวไหน ผู้เขียนโปรแกรมจำเป็นต้องแยกความแตกต่างระหว่างตัวแปรอ้างอิง กับชิ้นวัตถุที่เกิดขึ้น เนื่องจากบางครั้งในโปรแกรมอาจจะมีแต่ตัวแปรอ้างอิงแต่ยังไม่ได้กำกับชี้ไว้ที่วัตถุชิ้นใดเลยก็ได้ เช่นการเขียนโปรแกรมเช่นนี้
Employee emp1;
Employee emp2 = new Employee();
ตัวแปร emp1 เป็นเพียงตัวแปรอ้างอิงที่ไม่ได้ชี้ไว้ที่วัตถุ Employee ตัวใดเลย ซึ่งตัวแปรอ้างอิงแบบนี้เราเรียกว่า Null Pointer และเป็นตัวแปรที่ไม่มีวัตถุให้เข้าถึง เราจึงไม่สามารถเขียนโปรแกรม emp1.firstName = “Somchai” ได้ เพราะระบบจะไม่รู้ว่า firstName นั้นเป็นของวัตถุไหน เพราะตัวแปร emp1 ไม่ได้ชี้วัตถุใดเลย
แต่ตัวแปร emp2 เป็นตัวแปรที่อ้างอิงและชี้ไว้ที่วัตถุที่สร้างขึ้นมาด้วยคำสั่ง new ดังนั้นเราสามารถนำข้อมูลไปเก็บในวัตถุได้ด้วยคำสั่ง emp2.firstName = “Somying” ภาพต่อไปนี้แสดงความแตกต่างระหว่างตัวแปรอ้างอิงที่ไม่ชี้วัตถุ กับตัวแปรอ้างอิงที่ชี้วัตถุ

รูปภาพ 5 ตัวแปรอ้างอิงและการชี้วัตถุ
หากเปรียบเทียบกับในโลกความจริงของเรา ตัวแปรอ้างอิงอาจจะเปรียบเหมือนกับแผ่นป้ายทะเบียนรถยนต์ แต่ไม่ใช่ตัวรถยนต์ ดังนั้นการมีแต่ตัวแปรอ้างอิงจึงเปรียบเหมือนกับเรามีเพียงป้ายทะเบียน แต่แน่นอนว่าเพียงแค่ป้ายทะเบียนซึ่งไม่ใช่รถยนต์จริงๆ เราย่อมไม่สามารถใช้ป้ายทะเบียนเป็นยานพาหนะขับบนถนนได้เพราะนั่นไม่ใช่ตัวรถยนต์จริง เราจำเป็นต้องนำป้ายทะเบียนไปติดกับตัวรถเสียก่อนจึงจะครบถ้วนสมบูรณ์และขับออกถนนได้ เช่นเดียวกันกับการเขียนโปรแกรมเชิงวัตถุ โปรแกรมจำเป็นต้องมีครบทั้งตัวแปรอ้างอิงและชิ้นวัตถุที่ตัวแปรอ้างอิงกำกับอยู่ จึงจะสามารถทำงานได้อย่างถูกต้อง
ตัวแปรอ้างอิง 1 ตัวสามารถใช้ชี้วัตถุได้เพียง 1 ชิ้นเท่านั้น แต่วัตถุ 1 ชิ้นสามารถมีตัวแปรอ้างอิงชี้ได้มากกว่าหนึ่งตัว เช่นหากเราเขียนโปรแกรมเช่นนี้
Employee emp1;
Employee emp2 = new Employee();
emp1 = emp2;
บรรทัดที่เขียนว่า emp1 = emp2 หมายถึงให้ตัวแปรอ้างอิง emp1 อ้างอิงไปที่วัตถุตัวที่ emp2 กำลังชี้อยู่ ดังนั้นวัตถุ Employee ที่สร้างขึ้นจะมีตัวแปรอ้างอิงกำกับไว้ 2 ตัวคือทั้ง emp1 และ emp2 ดังภาพต่อไปนี้

รูปภาพ 6 ตัวแปรอ้างอิงหลายตัวสามารถชี้ไปที่วัตถุตัวเดียวกันได้
ตัวแปรอ้างอิงเป็นเพียงทางเข้าไปที่วัตถุเท่านั้น ดังนั้นหากในภาพข้างต้น ไม่ว่าเราจะเข้าถึงวัตถุผ่านทางตัวแปร emp1 หรือตัวแปร emp2 ย่อมจะได้ผลลัพธ์เทียบเท่ากัน เนื่องจากวัตถุที่ตัวแปรทั้งคู่ชี้อยู่เป็นวัตถุตัวเดียวกัน
Employee emp1;
Employee emp2 = new Employee();
emp1 = emp2;
emp1.code = "4455";
Console.WriteLine(emp2.code); // ย่อมได้ค่ามาเป็น 4455 เพราะเป็นวัตถุตัวเดียวกันกับที่ emp1 ชี้อยู่

5. เมธอด

เมธอด (Method) ใช้เก็บชุดคำสั่งโปรแกรม (Code) ที่เป็นการทำงานของวัตถุ วัตถุสามารถทำงานอะไรก็ได้ เพื่อให้เกิดผลลัพธ์ตรงตามวัตถุประสงค์การใช้งานของผู้ใช้ แต่การออกแบบเชิงวัตถุที่ดีเมธอดควรจะทำงานกับข้อมูลที่อยู่ภายในวัตถุของตัวมันเองเท่านั้น เพราะจะทำให้เกิดเอกภาพและความเป็นเนื้อเดียวกัน (Cohesion) เมื่อเมธอดทำงานจนจบผลลัพธ์ที่เกิดขึ้นอาจจะยังคงเก็บค้างอยู่ในวัตถุ หรือส่งกลับออกมาให้ภายนอกวัตถุนำไปใช้งานต่อก็ได้
ตัวอย่างต่อไปนี้เป็นเมธอดชื่อว่า compute ที่อยู่ในคลาส Rectangle เพื่อใช้ดำเนินการคำนวณพื้นที่รูปสี่เหลี่ยม
ซอร์สโค้ด 7 คลาส Rectangle และเมธอด compute()
class Rectangle
{
    public double width;
    public double height;
    public double area;

    public void compute()
    {
        area = width * height;
    }
}
หากเรานำเอาคลาส Rectangle มาสร้างเป็นวัตถุเพื่อเป็นตัวแทนรูปสี่เหลี่ยมขนาด 100 x 50 และต้องการหาพื้นที่รูปสี่เหลี่ยมจะสามารถเขียนโปรแกรมฝั่งผู้ใช้งาน (Client Code) ได้ดังนี้
Rectangle rect = new Rectangle();
rect.width = 100;
rect.height = 50;
rect.compute();
Console.WriteLine(rect.area);
สังเกตว่าเมธอด compute() ไม่จำเป็นต้องรับอาร์กิวเมนต์ (Argument) เข้าเป็นอินพุตให้กับการคำนวณ เนื่องจากอินพุตที่จำเป็นสำหรับการคำนวณคือ width และ height ได้ถูกเก็บและจดจำไว้ในตัววัตถุเรียบร้อยแล้ว และเมธอด compute() จะคำนวณพื้นที่โดยอาศัยค่าที่เก็บอยู่ในตัวแปรสมาชิกของวัตถุเป็นอินพุต

6. ความแตกต่างระหว่างเชิงฟังก์ชันและเชิงวัตถุ

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

รูปภาพ 7 ความแตกต่างระหว่างการเขียนโปรแกรมเชิงวัตถุและโปรแกรมเชิงฟังก์ชัน
จากภาพข้างต้น (ที่หมายเลข 1 และ 2) จะเห็นว่าเมธอดที่ออกแบบมาในลักษณะโปรแกรมเชิงวัตถุจะไม่จำเป็นต้องรับอาร์กิวเมนต์ใดมาเป็นข้อมูลเข้าสำหรับการคำนวณอีก เนื่องจากข้อมูลที่จำเป็นถูกจดจำไว้ภายในตัววัตถุเรียบร้อยแล้ว นอกจากนี้เมื่อคำนวณเสร็จผลลัพธ์ที่เกิดขึ้นก็จะเก็บไว้ในตัววัตถุด้วยเช่นกัน ในทางตรงข้ามหากโปรแกรมถูกออกแบบโดยใช้แนวคิดเชิงฟังก์ชัน โปรแกรมจะออกมาคล้ายกับในภาพหมายเลข 3 และ 4 ซึ่งเมธอดจะรับอาร์กิวเมนต์จำนวนมากมาเป็นอินพุต เมื่อคำนวณเสร็จก็จะส่งผลลัพธ์กลับออกไปทางค่าส่งกลับ (Return Value) โดยวัตถุไม่มีความสำคัญและไม่ได้จดจำข้อมูลใดๆไว้ในตัววัตถุ
การสร้างระบบขนาดใหญ่จำเป็นต้องผสมผสานระหว่างแนวคิดเชิงฟังก์ชันและแนวคิดเชิงวัตถุเนื่องจากจะเห็นว่าการออกแบบโปรแกรมทั้ง 2 แบบมีมุมมองแตกต่างกันขึ้นอยู่กับว่าผู้ใช้คลาส (Client Code) เป็นใคร หากผู้ใช้คลาสเป็นโปรแกรมเมอร์ที่นำเอาคลาสไปรวบรวมและสร้างเป็นระบบสารสนเทศมักต้องการรูปแบบเชิงวัตถุเนื่องจากสามารถปรับแต่งค่าก่อนการคำนวณได้ง่ายและมีลักษณะโปรแกรมเป็นแบบละเอียด (Fine-Grain) ที่สามารถอ่านไล่ดูขั้นตอนได้ทีละบรรทัด แต่หากผู้ใช้คลาสไม่ได้เป็นโปรแกรมเมอร์ แต่เป็นเพียงผู้เชื่อมต่อระบบ (Integrator) ซึ่งไม่ต้องการรู้รายละเอียดภายในระบบแต่ต้องการเพียงส่งข้อมูลรับและรับผลลัพธ์กลับไปเท่านั้น มักจะนิยมการออกแบบแนวฟังก์ชัน เพราะเห็นได้ชัดเจนว่าเป็นการดำเนินการอะไร มีข้อมูลอะไรเป็นอินพุตและมีข้อมูลอะไรเป็นเอาท์พุต

7. การปิดซ่อน (Encapsulation)

จากตัวอย่างที่ผ่านมาจะเห็นว่า ตัวแปรสมาชิกในคลาส Employee หรือ Rectangle ถูกกำหนดระดับการเข้าถึงไว้เป็น public ซึ่งระดับการเข้าถึง public นี้หมายความว่าโปรแกรมภายนอกสามารถมองเห็นตัวแปรสมาชิก และเปลี่ยนแปลงค่าในตัวแปรสมาชิกได้โดยตรง ตัวอย่างเช่น การกำหนดค่าโดยเครื่องหมายเท่ากับ = (Assignment Operator)
Rectangle rect = new Rectangle();
rect.width = 100;
rect.height = 50;
rect.area = 300;
คลาส Rectangle มีตัวแปรสมาชิก width, height และ area เป็น public ทำให้ไคลเอ็นต์โค้ดสามารถเข้าถึงตัวแปรเหล่านี้ได้โดยตรงผ่านทางเครื่องหมาย = การเปลี่ยนแปลงค่าตัวแปรสมาชิกโดยตรงเช่นนี้อาจจะดูเหมือนไคลเอ็นต์โค้ดได้รับความสะดวก แต่ในความเป็นจริงแล้วถือว่าเป็นการออกแบบเชิงวัตถุที่ไม่ดี เนื่องจากหากวัตถุยินยอมให้โปรแกรมภายนอกมาเปลี่ยนค่าในตัววัตถุได้โดยตรงโดยไม่มีการควบคุม อาจจะมีค่าที่ผิดเพี้ยนใส่เข้าไปในวัตถุ และทำให้วัตถุอยู่ในสถานะที่ไม่ถูกต้อง ส่งผลให้โปรแกรมมีข้อผิดพลาดตามมา เช่น ในตัวอย่างข้างต้นจะเห็นว่า rect.area = 300 ไม่สอดคล้องกับความกว้างและความสูง เนื่องจากความกว้าง 100 และความสูง 50 ควรจะมีพื้นที่เป็น 5000 เป็นต้น
ในความเป็นจริงเราไม่ควรจะให้โปรแกรมภายนอกเข้าถึงข้อมูล area ของคลาส Rectangle เพราะ area เป็นค่าที่เกิดจากการคำนวณด้วย width และ height ดังนั้นเราจำเป็นต้องปิดซ่อนตัวแปร area ไม่ให้ไคลเอ็นต์โค้ดมองเห็นและกำหนดค่าผ่านทางเครื่องหมายเท่ากับได้
ซอร์สโค้ด 8 การปิดซ่อนตัวแปรสมาชิกด้วย private และการสร้างพร็อพเพอตี (Property) get สำหรับดึงค่าออกจากวัตถุ
class Rectangle
{
    public double width;
    public double height;
    private double area;
 

    public double Area
    {
        get { return area; }
    }

    public void compute()
    {
        area = width * height;
    }
}
หากกำหนดระดับการเข้าถึงให้เป็น private จะเป็นการซ่อนไม่ให้ภายนอกมองเห็นสมาชิกเหล่านี้ ทำให้ไม่สามารถกำหนดค่าใส่เข้าไปในตัวแปร area ได้ด้วยเครื่องหมายเท่ากับอีกต่อไป ดังนั้นต่อไปนี้ไคลเอ็นต์โค้ดจะไม่สามารถเขียนโปรแกรมเอาค่าใส่ให้กับตัวแปร area เช่นนี้ได้
Rectangle rect = new Rectangle();
rect.area = 300;
เพราะจะทำให้เกิดคอมไพล์โปรแกรมไม่ผ่าน (Compile Error)  วิธีการเช่นนี้ช่วยให้ผู้ออกแบบคลาสสามารถมั่นใจได้ว่าข้อมูลที่ใช้ดำเนินงานอยู่ภายในตัววัตถุจะคงอยู่ในสถานะที่ถูกต้องเสมอ
อย่างไรก็ตามในบางครั้งเราต้องการเก็บผลลัพธ์ที่วัตถุดำเนินการไว้กลับออกมาใช้งานต่อ แต่หากผลลัพธ์นั้นเป็นตัวแปร private ย่อมทำให้ไม่สามารถเข้าถึงได้จากภายนอก ดังนั้นผู้ออกแบบคลาสจำเป็นต้องเตรียม Property get เอาไว้เพื่อให้โปรแกรมภายนอกสามารถดึงค่าที่วัตถุเก็บไว้ในตัวแปร private กลับออกไปใช้งานได้ด้วย เช่นในตัวอย่างข้างต้นจะเห็นว่า คลาส Rectangle ได้เตรียม Property get ไว้ชื่อว่า Area และส่งค่าตัวแปรสมาชิก area ที่ได้จากการคำนวณกลับออกไปให้ซึ่งจะทำให้โปรแกรมภายนอกสามารถใช้งานคลาส Rectangle ได้ดังนี้
Rectangle rect = new Rectangle();
rect.width = 100;
rect.height = 50;
double a = rect.Area;
เนื่องจากคลาส Rectangle ได้จัดเตรียมไว้ให้แต่ Property get ดังนั้นผู้ใช้งานคลาสจะไม่สามารถกำหนดค่า (set) ใส่เข้าไปในพร็อพเพอตี Area ได้ และหากพยายามเขียนโปรแกรมกำหนดค่าด้วยเครื่องหมายเท่ากับก็จะทำให้เกิด Compile Error
rect.Area = 300;
หากพยายามกำหนดค่า 300 ใส่เข้าไปในวัตถุ Rectangle เช่นนี้ จะทำให้เกิด Compile Error เนื่องจากคลาส Rectangle ไม่ได้จัดเตรียม Property set สำหรับ Area ไว้ให้
จากตัวอย่างการใช้ private และ Property get ข้างต้นเราจะได้แนวคิดของการปิดซ่อน (Encapsulation) ที่เป็นหลักสำคัญในการออกแบบเชิงวัตถุ โดยแนวคิดนี้จะพยายามปิดบังซ่อนความซับซ้อนภายในตัววัตถุไว้ และเปิดให้โปรแกรมภายนอกเห็นเฉพาะสิ่งที่จำเป็นเท่านั้น การออกแบบตามแนวคิด Encapsulation นี้เป็นเช่นเดียวกันกับการออกแบบผลิตภัณฑ์ที่จะปิดซ่อนความซับซ้อนไว้ภายใต้ตัวถังหรือกรอบ และเปิดให้เห็นเฉพาะปุ่มกดที่ใช้เปิดปิดหรือสั่งงานเท่าที่จำเป็นเท่านั้น

8. การสืบทอด (Inheritance)

แม้ว่าวัตถุจะมีหลากหลายชนิดแต่ในความจริงเรามักจะพบวัตถุที่มีลักษณะใกล้เคียงกัน เช่น รถยนต์ กับ รถกระบะ ต่างก็เป็นรถเหมือนกัน หรือ พนักงานประจำ กับ พนักงานชั่วคราว ต่างก็เป็นพนักงานเหมือนกัน เป็นต้น วัตถุที่มีลักษณะส่วนใหญ่คล้ายคลึงกันเช่นนั้นเราเรียกว่ามันมีคุณสมบัติพื้นฐานเหมือนกัน (Common Characteristic) การออกแบบเชิงวัตถุจะพยายามจัดกลุ่มคลาสที่มีคุณสมบัติพื้นฐานเหมือนกัน ให้เป็นคลาสแม่ (Superclass) และคลาสที่มีลักษณะพิเศษ (Specialize) ให้เป็นคลาสลูก (Subclass) เมื่อเราสามารถแยกประเภทได้แล้วว่าคลาสใดเป็นคลาสแม่ ซึ่งก็คือประเภทใหญ่ หรือ คลาสใดเป็นคลาสลูก ซึ่งก็คือประเภทย่อย ก็จะทำให้เราได้โครงสร้างการสืบทอด (Inheritance Hierarchy) ที่แบ่งประเภทของวัตถุออกตามความคล้ายคลึง และทำให้เราสามารถออกแบบระบบขนาดใหญ่ได้
ตัวอย่างของการออกแบบโดยอาศัยโครงสร้างการสืบทอด เช่น หากเรากำลังออกแบบระบบพนักงาน และพบว่าพนักงานทั้ง 2 ประเภทคือ พนักงานประจำ และ พนักงานชั่วคราว ต่างก็เป็นพนักงานของบริษัท จะทำให้เราสามารถออกแบบคลาสได้ดังนี้

รูปภาพ 8 ตัวอย่างแผนผังการสืบทอดเพื่อจำแนกประเภทคลาสพนักงาน
คลาสลูกที่สืบทอดมาจากคลาสแม่จะได้รับคุณสมบัติทุกอย่างมาจากคลาสแม่ และสามารถต่อเติมคุณสมบัติพิเศษของตนเองเข้าไปได้อีก เช่นในที่นี้กล่าวได้ว่าคลาส PermanentEmployee มีคุณสมบัติทุกอย่างเทียบเท่า Employee แต่มีคุณสมบัติพิเศษบางอย่างเป็นของตนเองเพิ่มขึ้นมาด้วย
การเขียนโปรแกรมโดยอาศัยการสืบทอดจะช่วยให้โปรแกรมเมอร์ที่โปรแกรมคลาสลูกประหยัดเวลาในการเขียนโปรแกรมเนื่องจากหากโปรแกรมส่วนใหญ่คลาสแม่ได้เขียนไว้สมบูรณ์ดีแล้ว เพียงแต่ขาดฟังก์ชันเสริมพิเศษบางอย่าง โปรแกรมเมอร์สามารถสร้างคลาสของตนเองสืบทอดเอาจากคลาสแม่และเพิ่มเมธอดหรือตัวแปรสมาชิกเข้าไปเพื่อให้เกิดฟังก์ชันพิเศษที่เพิ่มเข้ามาได้อีก โดยยังคงเอาคุณสมบัติส่วนใหญ่ตามคลาสแม่เดิมที่มีอยู่
ด้วยวิธีการสืบทอดและเพิ่มเติมคุณสมบัติเช่นนี้จะทำให้เราเห็นว่าในปัจจุบันโปรแกรมระบบขนาดใหญ่ที่ขึ้นรูปแล้ว สามารถพัฒนาและออกเป็นโปรแกรมเวอร์ชันใหม่ได้อย่างรวดเร็วเนื่องจากไม่จำเป็นต้องย้อนกลับไปเขียนส่วนคลาสแม่ใหม่ แต่จะเขียนโปรแกรมเฉพาะบริเวณคลาสลูกที่เป็นความสามารถของเวอร์ชันใหม่เท่านั้น
ในทางปฏิบัติผู้เขียนโปรแกรมด้วย Microsof.NET C# สามารถสร้างคลาสแม่และคลาสลูกได้ด้วยเครื่องหมายโคลอน : (รับเอามาจากเดิมของภาษา C++) เช่นหากต้องการสร้างโครงสร้างคลาสที่มีการสืบทอดเหมือนกับในภาพข้างต้นจะเขียนโปรแกรมได้ดังนี้

รูปภาพ 9 การสร้างโครงสร้างการสืบทอดในภาษา C#
 จากภาพข้างต้นทำให้เราทราบว่าคลาส PermanentEmployee สามารถเก็บข้อมูลได้ 6 อย่างคือ firstName, surname, code และส่วนในคลาสตัวเองคือ taxRate, socialTax และ salary จะเห็นว่าผู้สร้างคลาส PermanentEmployee จะได้รับตัวแปรสมาชิกที่เป็นคุณสมบัติดั้งเดิมมาจากคลาส Employee ที่เป็นคลาสแม่ ทำให้ไม่ต้องสร้างตัวแปรสมาชิก firstName, surname และ code ใหม่
ในมุมมองของโปรแกรมเมอร์ผู้ใช้งานคลาสจะยังคงใช้งานคลาสตามปกติ เช่นในที่นี้ก็สามารถนำคลาส PermantentEmployee มาสร้างวัตถุและเก็บข้อมูลไว้ในวัตถุได้
PermanentEmployee emp = new PermanentEmployee();
emp.firstName = "Somchai";
emp.surname = "Rukdee";
emp.code = "1234";
emp.taxRate = 0.3;
emp.socialTax = 1000;
emp.salary = 30000;

9. การเลือกทำตามประเภทวัตถุ (Polymorphism)

การเลือกทำตามประเภทวัตถุเป็นแนวคิดชั้นสูงของการออกแบบเชิงวัตถุ ซึ่งจะช่วยลดความซับซ้อนของโปรแกรมโดยแยกการดำเนินการที่แตกต่างไปตามประเภทของวัตถุ แต่อาศัยชื่อกระบวนการที่เป็นชื่อเดียวกัน การใช้ Polymorphism จะช่วยให้ผู้ออกแบบโปรแกรมไม่จำเป็นต้องแยกการดำเนินการด้วยคำสั่ง if … else … เนื่องจากเส้นทางของโปรแกรมจะแตกแขนงไปตามประเภทของวัตถุในขณะรันไทม์โดยอัตโนมัติ
ตัวอย่างต่อไปนี้แสดงให้เห็นว่าหากเราออกแบบระบบเพื่อคำนวณค่าแรงของพนักงาน 2 ประเภทคือพนักงานประจำ และ พนักงานชั่วคราว โดยวิธีการคำนวณค่าแรงแตกต่างกัน โดยพนักงานประจำจะคำนวณจากอัตราเงินเดือน ส่วนพนักงานชั่วคราวจะคำนวณจากจำนวนชั่วโมงทำงานคูณด้วยอัตราผลตอบแทนรายชั่วโมง หากเราไม่ใช้แนวคิดของ Polymorphism โปรแกรมการคำนวณผลตอบแทนของพนักงาน อาจจะถูกเขียนออกมาดังนี้
ซอร์สโค้ด 9 ตัวอย่างการเขียนโปรแกรมที่ไม่ใช้คุณสมบัติ Polymorphism
private double computeWage(Employee emp)
{
    if (emp is PermanentEmployee)
    {
        PermanentEmployee e = (PermanentEmployee)emp;
        return e.salary;
    }
    else if(emp is FreelanceEmployee)
    {
        FreelanceEmployee e = (FreelanceEmployee)emp;
        return e.wagePerHour * e.hour;
    }
    return 0;
}
สังเกตว่าโปรแกรม computeWage ข้างต้นจำเป็นต้องตรวจสอบก่อนว่า emp มีชนิดเป็น PermanentEmployee หรือ FreelanceEmployee แล้วจึงสามารถเลือกคำนวณได้ถูกต้องตามสูตร วิธีการเขียนโปรแกรมเช่นนี้ ถือว่าผิดหลักการเชิงวัตถุ 2 อย่างคือ อย่างแรกการดำเนินการคำนวณใดๆก็ตามทำกับข้อมูลในวัตถุควรจะเป็นเมธอดที่อยู่ในตัววัตถุ ดังนั้นแทนที่เรียกใช้เมธอด computeWage(employee) ในความเป็นจริงควรจะเรียกใช้เป็น employee.computeWage() อย่างที่สองก็คือโปรแกรมมีการใช้งาน if … else และ is เพื่อแยกดำเนินการตามประเภทของวัตถุนั่นแสดงให้เห็นว่าโปรแกรมไม่ยืดหยุ่น หากในอนาคตมีประเภทวัตถุเพิ่มขึ้นอีกโปรแกรมเมอร์จำเป็นต้องแก้ไขบริเวณ if … else นี้เพื่อให้รองรับวัตถุประเภทอื่นๆที่มีการคำนวณแตกต่างกันไป
ในความเป็นจริงเราสามารถเปลี่ยนโปรแกรมข้างต้นให้ไปอยู่ในตัวคลาส Employee และทำให้เกิด Polymorphism ได้โดยเขียนโปรแกรมใหม่ดังนี้

รูปภาพ 10 การสร้างคลาสและเมธอดเพื่อให้เป็นไปตามหลักการ Polymorphism ตามแนวคิดเชิงวัตถุ
เมื่อเราจัดโครงสร้างคลาสให้สืบทอดและให้คลาสลูกโอเวอร์ไรด์ (Override) เมธอดที่คลาสแม่เตรียมไว้ ย่อมทำให้ในขณะรันโปรแกรม โปรแกรมจะไหลเข้าไปที่เมธอดตามชนิดของวัตถุที่กำลังดำเนินการอยู่ โดยที่เราไม่จำเป็นต้องเขียนโปรแกรม if … else เพื่อตรวจสอบว่าเป็นวัตถุชนิดใด และเมื่อไหลเข้าสู่เมธอดของคลาสลูก การดำเนินการย่อมเป็นลักษณะเฉพาะของคลาสลูกตัวนั้น ก็จะทำให้โปรแกรมแปรเปลี่ยนไปเองได้ตามประเภทของวัตถุ
PermanentEmployee emp1 = new PermanentEmployee();
emp1.firstName = "Somchai";
emp1.surname = "Rukdee";
emp1.code = "1234";
emp1.taxRate = 0.3;
emp1.socialTax = 1000;
emp1.salary = 30000;

FreelanceEmployee emp2 = new FreelanceEmployee();
emp2.firstName = "Somying";
emp2.surname = "Rukchart";
emp2.code = "4231";
emp2.hour = 30;
emp2.wagePerHour = 300;

// คำนวณค่าแรงของพนักงานทั้ง 2 คน (เรียกใช้เมธอดชื่อเดียวกัน แต่การดำเนินการต่างกัน)
Console.WriteLine("Somchai's wage = " + emp1.computeWage());
Console.WriteLine("Somying's wage = " + emp2.computeWage());
ข้อดีของการ Polymorphism ก็คือ นอกจากช่วยลด if … else ที่ไม่จำเป็นแล้ว โปรแกรมที่เรียกใช้งานยังอยู่ในรูปแบบง่าย เนื่องจากผู้ใช้สามารถจดจำชื่อเมธอดเพียงชื่อเดียว เช่นในที่นี้ใช้เมธอดชื่อว่า computeWage() แต่โปรแกรมจะทำงานแตกต่างกันไปเองขึ้นอยู่กับว่าเป็น computeWage() ของวัตถุประเภท PermanentEmployee หรือประเภท FreelanceEmployee
แนวคิด Polymorphism เป็นหัวใจสำคัญของการโปรแกรมเชิงวัตถุเนื่องจากในโครงสร้างของระบบขนาดใหญ่ ที่มีวัตถุหลากหลายประเภทรวมกันอยู่และทำงานร่วมกัน ระบบย่อมไม่สามารถรวมกันได้หากวัตถุแต่ละชนิดมีชื่อเมธอดที่แตกต่างกันไป วิธีการ Polymorphism เป็นการจัดมาตรฐานให้วัตถุที่เป็นประเภทเดียวกันต้องมีชื่อเมธอดเหมือนกัน แม้ว่าภายในจะมีการทำงานที่แตกต่างกันก็ตาม ซึ่งจะช่วยให้ระบบที่รวบรวมวัตถุเหล่านั้นไว้สามารถควบคุมวัตถุย่อยๆได้ด้วยแนวทางเดียวกันตลอดทั่วทั้งระบบ

10. รายการวัตถุ (Collection)

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

รูปภาพ 11 การเก็บวัตถุไว้ในรายการเพื่อประมวลผลรวมทั้งรายการ
ใน Microsoft.NET ใช้คลาส List เพื่อเก็บรวบรวมวัตถุไว้ เช่นเราสามารถนำวัตถุพนักงานหลายๆชิ้นมารวมไว้ใน List เพื่อคำนวณผลรวมค่าแรงของทุกคนได้ดังนี้
PermanentEmployee emp1 = new PermanentEmployee();
emp1.firstName = "Somchai";
emp1.surname = "Rukdee";
emp1.code = "1234";
emp1.taxRate = 0.3;
emp1.socialTax = 1000;
emp1.salary = 30000;

FreelanceEmployee emp2 = new FreelanceEmployee();
emp2.firstName = "Somying";
emp2.surname = "Rukchart";
emp2.code = "4231";
emp2.hour = 30;
emp2.wagePerHour = 300;


 


List<Employee> empList = new List<Employee>();
empList.Add(emp1);
empList.Add(emp2);

// คำนวณผลรวมค่าแรงของพนักงานทุกคน
double sum = 0.0;
foreach(Employee emp in empList)
{
    sum += emp.computeWage();
}
Console.WriteLine("Total wage : " + sum);
นอกจากการใช้ List เพื่อรวบรวมและนำมาคำนวณเช่นในตัวอย่างข้างต้นนี้ เรายังสามารถใช้ List เพื่อสร้างความสัมพันธ์แบบ หนึ่งต่อหลาย (one-to-many) ในกรณีที่วัตถุใหญ่ประกอบด้วยวัตถุย่อยๆ เช่น ในที่นี้หากเราต้องการออกแบบให้วัตถุ Department เป็นแผนกงาน และต้องการคำนวณค่าแรงแยกตามแผนก เราจะให้วัตถุ Department สัมพันธ์กับวัตถุ Employee แบบหนึ่งต่อหลาย โดยวัตถุ Department หนึ่งชิ้นสามารถประกอบด้วยวัตถุ Employee ได้หลายชิ้น เช่นเดียวกับที่แผนกหนึ่งมีพนักงานเข้าไปทำงานได้หลายคน

รูปภาพ 12 การออกแบบความสัมพันธ์ระหว่างวัตถุแบบหนึ่งต่อหลาย (one-to-many)
เพื่อให้เกิดความสัมพันธ์แบบหนึ่งต่อหลาย เราจำเป็นต้องใช้ List เพื่อเก็บวัตถุตัวย่อยเอาไว้ในตัวใหญ่ เช่นในที่นี้เราจะนำ List ไปใช้ในคลาส Department เพื่อเก็บวัตถุ Employee ได้ดังนี้
class Department
{
    public String name;
    public String code;
    private List<Employee> member = new List<Employee>();


    public void Add(Employee e)
    {
        member.Add(e);
    }

    public double computeWage()
    {

        // คำนวณผลรวมค่าแรงของพนักงานทุกคนในแผนกนี้
        double sum = 0.0;
        foreach (Employee emp in member)
        {
            sum += emp.computeWage();

        }
        return sum;
    }
}
โปรแกรมที่ใช้งานคลาส Department และ Employee จะนำวัตถุ Employee ใส่เข้าไปใน Department ก่อนที่จะสั่งคำนวณผลรวมของค่าแรงทั้งหมดในแผนกนั้น โดยเขียนเป็นโปรแกรมได้ดังนี้
PermanentEmployee emp1 = new PermanentEmployee();
emp1.firstName = "Somchai";
...

FreelanceEmployee emp2 = new FreelanceEmployee();
emp2.firstName = "Somying";
...

Department dept = new Department();

dept.name = "Accounting";
dept.code = "AC";
dept.Add(emp1);
dept.Add(emp2);

// คำนวณผลรวมค่าแรงของพนักงานทุกคนในแผนก AC
double sum = dept.computeWage();
Console.WriteLine("Total wage : " + sum);
ในระบบขนาดใหญ่เราสามารถออกแบบให้มีความสัมพันธ์แบบ one-to-many ซ้อนกันได้หลายชั้น แล้วแต่ขนาดของระบบ ยิ่งระบบมีขนาดใหญ่และซับซ้อนสูงยิ่งประกอบด้วยวัตถุหลายหลายประเภทที่ซ้อนอยู่ภายใต้วัตถุตัวที่ใหญ่กว่า ในรอบนอกสุดของระบบจะเป็นวัตถุที่มีความซับซ้อนต่ำสุดและมีการทำงานได้ตรงตามความต้องการของผู้ใช้ ส่วนในชั้นที่ลึกเข้าไปข้างในจะประกอบด้วยวัตถุที่มีความสามารถเฉพาะตัวและทำงานเฉพาะด้านใดด้านหนึ่ง การออกแบบเช่นนี้จะทำให้เกิดสถาปัตยกรรมระบบ (System Architecture) ที่เป็นองค์รวมได้ในที่สุด

รูปภาพ 13 การออกแบบระบบขนาดใหญ่ตามแนวคิดเชิงวัตถุเพื่อให้มีความยืดหยุ่นสูง

11. บทสรุป

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


ความคิดเห็น

โพสต์ยอดนิยมจากบล็อกนี้

การออกแบบระบบโดยใช้ UML (Unified Modeling Language)

แนวคิดการออกแบบซอฟแวร์เชิงวัตถุ (Object-Oriented Software Design)