การถกเถียงที่เพิ่มขึ้นในชุมชนโปรแกรมเมอร์มุ่งเน้นไปที่ข้อบกพร่องพื้นฐานในวิธีที่ภาษาโปรแกรมมิ่งสมัยใหม่จัดการกับข้อมูลประเภทต่างๆ การอภิปรายนี้เน้นย้ำว่าภาษาโปรแกรมมิ่งบังคับให้นักพัฒนาต้องประนีประนอมอย่างไม่เหมาะสมเมื่อต้องแสดงข้อมูลธรรมดาเทียบกับออบเจ็กต์ที่ซับซ้อนซึ่งมีพฤติกรรม
ปัญหาหลักเกิดจากภาษาโปรแกรมมิ่งที่ปฏิบัติต่อทุกสิ่งในแบบเดียวกัน ไม่ว่าจะเป็นตัวเลขธรรมดาที่ไม่เปลี่ยนแปลงหรือส่วนประกอบของระบบที่ซับซ้อนซึ่งรักษาสถานะตลอดเวลา แนวทางแบบเดียวสำหรับทุกสิ่งนี้สร้างความซับซ้อนที่ไม่จำเป็นและนำไปสู่การตัดสินใจด้านสถาปัตยกรรมที่ไม่ดีทั่วทั้งอุตสาหกรรมซอฟต์แวร์
เรื่องราวของสองกระบวนทัศน์การเขียนโปรแกรม
ชุมชนโปรแกรมเมอร์ได้ระบุแนวทางที่แตกต่างกันสองแนวทางที่ภาษาโปรแกรมมิ่งมักจะสนับสนุน ภาษาเชิงออบเจ็กต์อย่าง Java ผลักดันให้ทุกสิ่งเป็นออบเจ็กต์ แม้แต่ค่าธรรมดาอย่างตัวเลข สิ่งนี้สร้างภาระและความซับซ้อนในที่ที่ไม่ควรมี ในทางกลับกัน ภาษาเชิงฟังก์ชันอย่าง Haskell เก่งในการจัดการข้อมูลบริสุทธิ์ แต่ประสบปัญหาเมื่อต้องการส่วนประกอบที่มีสถานะซึ่งรักษาตัวตนตลอดเวลา
การอภิปรายของชุมชนเผยให้เห็นว่า C# ได้ก้าวหน้าอย่างมากในการแก้ไขช่องว่างนี้ แตกต่างจาก Java ตรงที่ C# แยกแยะระหว่างประเภทค่า (structs) สำหรับข้อมูลธรรมดาและประเภทอ้อิง (classes) สำหรับออบเจ็กต์ที่มีตัวตน การตัดสินใจในการออกแบบนี้ซึ่งมีอยู่ตั้งแต่เวอร์ชันแรกของภาษา ช่วยให้นักพัฒนาสามารถตัดสินใจอย่างมีสติเกี่ยวกับวิธีที่ข้อมูลของพวกเขาควรทำงาน
แนวทางของภาษาโปรแกรมมิ่งต่อการแยกแยะระหว่างข้อมูลและออบเจกต์
- C: การแยกแยะที่ชัดเจนด้วย value types (structs) เทียบกับ reference types (classes) ตั้งแต่เวอร์ชั่น 1
- Java: แนวทางทุกอย่างเป็นออบเจกต์ ค่อยๆ เพิ่ม value types ผ่าน Project Valhalla
- Haskell: รองรับข้อมูลอย่างแข็งแกร่งด้วย algebraic types แต่มีความสามารถคล้ายออบเจกต์อย่างจำกัด
- Scala: Case classes พยายามเชื่อมช่องว่างระหว่างข้อมูลและออบเจกต์
- Erlang / Elixir: รากฐานข้อมูลแบบ immutable ที่แข็งแกร่งพร้อมการจำลองออบเจกต์แบบ process-based
- Rust: พยายามให้ทั้งความปลอดภัยและประสิทธิภาพแต่มาพร้อมความซับซ้อนที่เพิ่มขึ้น
ผลกระทบในโลกแห่งความเป็นจริงต่อสถาปัตยกรรมระบบ
ความสับสนระหว่างข้อมูลและออบเจ็กต์ได้ส่งผลต่อแนวโน้มเทคโนโลยีหลักในทางที่ไม่คาดคิด การเคลื่อนไหว NoSQL ได้รับความนิยมบางส่วนเพราะฐานข้อมูลแบบดั้งเดิมประสบปัญหากับโครงสร้างข้อมูลแบบต้นไม้ ทำให้นักพัฒนาต้องหาทางแก้ไขข้อจำกัดเชิงสัมพันธ์ ในทำนองเดียวกัน REST APIs กลายเป็นที่นิยมเพราะช่วยให้ระบบแลกเปลี่ยนข้อมูลจริงเป็น JSON แทนที่จะต้องจัดการกับความซับซ้อนของแนวทางเชิงออบเจ็กต์ของ SOAP
ฉันไม่โทษใครสำหรับความตื่นเต้นที่ไม่มีเหตุผลเล็กน้อยหลังจากได้รับการปลดปล่อยจากข้อจำกัดนั้น มันช่างปลดปล่อยมากที่ได้จัดเก็บข้อมูลใช่ไหม
ชุมชนชี้ให้เห็นว่าปัญหาสถาปัตยกรรมบริการหลายอย่างเกิดจากความสับสนพื้นฐานนี้ นักพัฒนามักสร้างบริการที่เพียงแค่สับเปลี่ยนข้อมูลแทนที่จะให้พฤติกรรมที่มีความหมาย นำไปสู่รูปแบบต่อต้านที่คงอยู่ของบริการ CRUD ที่ที่ปรึกษาพยายามขจัดมานานกว่าทศวรรษ
ข้อพิจารณาด้านประสิทธิภาพและการปฏิบัติ
การถกเถียงขยายไปถึงผลกระทบด้านประสิทธิภาพเช่นกัน โครงสร้างข้อมูลที่ไม่เปลี่ยนแปลงซึ่งผู้สนับสนุนการเขียนโปรแกรมเชิงฟังก์ชันชื่นชอบ ให้การรับประกันความปลอดภัยและทำงานได้ดีในสภาพแวดล้อมแบบหลายเธรด อย่างไรก็ตาม สิ่งเหล่านี้มาพร้อมกับต้นทุนด้านประสิทธิภาพเมื่อเทียบกับการเปลี่ยนแปลงในที่เดิมที่ใช้ในสถานการณ์ที่ต้องการประสิทธิภาพสูงอย่างระบบเทรดดิ้งและเกมเอ็นจิน
ภาษาอย่าง Erlang และ Elixir แสดงให้เห็นประโยชน์ของรากฐานที่แข็งแกร่งด้วยข้อมูลที่ไม่เปลี่ยนแปลง แต่ขาดระบบประเภทแบบคงที่ซึ่งนักพัฒนาหลายคนถือว่าจำเป็นสำหรับโครงการขนาดใหญ่ ในขณะเดียวกัน ภาษาใหม่อย่าง Rust พยายามให้ทั้งความปลอดภัยและประสิทธิภาพ แม้ว่าจะมีความซับซ้อนเพิ่มขึ้นที่นักพัฒนาต้องเรียนรู้
การเปรียบเทียบลักษณะเฉพาะของ Data กับ Objects
ด้าน | Data | Objects |
---|---|---|
ความเท่าเทียม | อิงตามค่า: 1 ใดๆ ก็เท่ากับ 1 | อิงตามตัวตน: 1 นี้ ≠ 1 นั้น |
การคัดลอก | คัดลอกได้อย่างอิสระ เป็นเพียงไบต์ | Serialization สร้างตัวตนใหม่ |
ความสามารถในการเปลี่ยนแปลง | ไม่สามารถเปลี่ยนแปลงได้โดยธรรมชาติ | มักสามารถเปลี่ยนแปลงได้เพื่อการจัดการสถานะ |
ส่วนภายใน | เปิดเผย สอดคล้องกับ schema | ห่อหุ้มไว้พร้อมการเข้าถึงที่ควบคุม |
ความสามารถในการขยาย | รูปแบบคงที่ ฟังก์ชันไม่จำกัด | การดำเนินการคงที่ รูปแบบขยายได้ |
เส้นทางสู่อนาคต
ชุมชนโปรแกรมเมอร์ยิ่งตระหนักมากขึ้นว่าการออกแบบภาษาในอนาคตควรสนับสนุนทั้งสองกระบวนทัศน์อย่างชัดเจนแทนที่จะบังคับให้ทุกสิ่งอยู่ในโมเดลเดียว นักพัฒนาต้องการเครื่องมือที่ให้พวกเขาเลือกอย่างมีสติระหว่างการแสดงสิ่งใดสิ่งหนึ่งเป็นข้อมูลบริสุทธิ์หรือเป็นออบเจ็กต์ที่มีพฤติกรรมและตัวตน
ภาษาบางภาษากำลังพัฒนาไปในทิศทางนี้ Java ค่อยๆ เพิ่มประเภทค่าผ่าน Project Valhalla ในขณะที่ case classes ของ Scala ให้จุดกึ่งกลางระหว่างข้อมูลบริสุทธิ์และออบเจ็กต์เต็มรูปแบบ อย่างไรก็ตาม โซลูชันเหล่านี้มักรู้สึกเหมือนการแก้ไขบนระบบที่มีอยู่แล้วมากกว่าหลักการออกแบบพื้นฐาน
การอภิปรายแนะนำว่าการออกแบบภาษาโปรแกรมมิ่งที่ดีกว่าสามารถป้องกันปัญหาสถาปัตยกรรมหลายอย่างได้โดยทำให้การเลือกระหว่างข้อมูลและออบเจ็กต์ชัดเจนและสนับสนุนทั้งสองรูปแบบอย่างเท่าเทียมกัน สิ่งนี้จะช่วยให้นักพัฒนาตัดสินใจในการออกแบบอย่างมีสติมากขึ้นและหลีกเลี่ยงความสับสนที่กำลังรบกวนสถาปัตยกรรมซอฟต์แวร์ในปัจจุบัน
อ้างอิง: Data, objects, and how we're railroaded into poor design