ข้อเสียของรูปแบบ ActiveRecord คืออะไร


30

ฉันอยากรู้ว่าอะไรคือข้อเสียของการใช้รูปแบบ ActiveRecord สำหรับการเข้าถึงข้อมูล / วัตถุทางธุรกิจ คนเดียวที่ฉันสามารถนึกได้ว่าอยู่เหนือหัวของฉันคือมันละเมิดหลักการความรับผิดชอบเดียว แต่รูปแบบ AR เป็นเรื่องธรรมดาพอที่เหตุผลนี้เพียงอย่างเดียวดูเหมือนจะไม่ "ดีพอ" ที่จะพิสูจน์ว่าไม่ได้ใช้ (แน่นอน มุมมองอาจเบ้เพราะบ่อยครั้งที่ไม่มีรหัสที่ฉันทำงานด้วยตามหลักการ SOLID ใด ๆ )

โดยส่วนตัวฉันไม่ใช่แฟนของ ActiveRecord (ยกเว้นการเขียนแอพพลิเคชั่น Ruby on Rails ที่ AR ให้ความรู้สึก "เป็นธรรมชาติ") เพราะมันรู้สึกว่าคลาสทำมากเกินไปและการเข้าถึงข้อมูลไม่ควรขึ้นอยู่กับชั้นเรียน เพื่อจัดการ ฉันชอบใช้ที่เก็บที่ส่งคืนออบเจคทางธุรกิจ ส่วนใหญ่ของรหัสที่ฉันทำงานด้วยมีแนวโน้มที่จะใช้รูปแบบของ ActiveRecord ในรูปแบบของ (ฉันไม่ทราบว่าทำไมวิธีการเป็นบูลีน):

public class Foo
{
    // properties...

    public Foo(int fooID)
    {
        this.fooID = fooID;
    }

    public bool Load()
    {
        // DB stuff here...
        // map DataReader to properties...

        bool returnCode = false;
        if (dr.HasRows)
            returnCode = true;

        return returnCode;
    }
}

หรือบางครั้งวิธี "ดั้งเดิม" ที่มากขึ้นของการมีpublic static Foo FindFooByID(int fooID)วิธีการสำหรับผู้ค้นหาและบางสิ่งบางอย่างตามสายของpublic void Save()การบันทึก / ปรับปรุง

ฉันเข้าใจว่า ActiveRecord นั้นง่ายกว่าในการติดตั้งและใช้งาน แต่ดูเหมือนว่าจะง่ายเกินไปสำหรับแอพพลิเคชั่นที่ซับซ้อนและคุณอาจมีสถาปัตยกรรมที่แข็งแกร่งกว่าโดยการห่อหุ้มตรรกะการเข้าถึงข้อมูลของคุณใน Repository กลยุทธ์การเข้าถึงข้อมูลเช่นคุณใช้ Stored Procs + DataSets และต้องการเปลี่ยนเป็น LINQ หรือบางสิ่ง)

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

คำตอบ:


28

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

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


การให้วัตถุของคุณรู้เกี่ยวกับการคงอยู่ของพวกเขาหมายความว่าคุณต้องทำสิ่งต่าง ๆ เช่น:

  • มีการเชื่อมต่อฐานข้อมูลอย่างง่ายดายทุกที่ โดยทั่วไปแล้วสิ่งนี้นำไปสู่การเข้ารหัสฮาร์ดโค้ดที่น่ารังเกียจหรือการเชื่อมต่อแบบคงที่ที่ได้รับความนิยมจากทุกที่
  • วัตถุของคุณมักจะดูเหมือน SQL มากกว่าวัตถุ
  • ยากที่จะทำอะไรในแอปที่ถูกตัดการเชื่อมต่อเพราะฐานข้อมูลฝังแน่น

ท้ายที่สุดก็เป็นการตัดสินใจที่ไม่ดีอื่น ๆ ทั้งหมด


2
คุณสามารถอธิบายอย่างละเอียดเกี่ยวกับ "การตัดสินใจด้านการออกแบบที่ไม่ดีอื่น ๆ "
kevin cline

2
ขอบคุณ ฉันไม่พบปัญหาเหล่านี้เป็นปัญหาในการพัฒนา Ruby on Rails มันยังคงเป็นไปได้ที่จะทดสอบพฤติกรรมและการคงอยู่แยกกัน IMO ที่แยกการคงอยู่ออกจากพฤติกรรมมีค่าในทางปฏิบัติน้อย
kevin cline

@ เควิน: สิ่งเหล่านี้มีข้อเสียเปรียบน้อยกว่าด้วยคุณสมบัติทับทิมเช่นมิกซ์อินและการพิมพ์เป็ด ด้วยภาษาคงที่ - เช่น C # ซึ่งเป็นสิ่งที่ OP ใช้ในคำถามของเขา - มันเป็นการยากที่จะแยกทั้งสองออกจากกัน
ไวแอตต์บาร์เน็ตต์

@ Wayne: สำหรับฉันแล้วคลาสเป็นเพียงกล่องเพื่อวางวิธีการใน - ฉันสามารถแยกตรรกะทางธุรกิจออกจากการคงอยู่โดยใส่พวกเขาในชั้นเรียนที่แยกจากกันหรือฉันสามารถแยกพวกเขาในแนวความคิดโดยทำให้แน่ใจว่าวิธีการทางธุรกิจ ทุม ในภาษาที่มีการสนับสนุนการมอบหมายไม่ดี (เช่น Java) สิ่งนี้จะบันทึกรหัสจำนวนมาก OTOH ฉันเพิ่งเข้าสู่โหมดไฮเบอร์เนตดังนั้นฉันจึงผิดอย่างสมบูรณ์
kevin cline

4
ฉันจะเพิ่มสองสิ่ง; 1. การมีเพศสัมพันธ์กับกลไกการติดตาทำให้รหัสยากถ้าไม่เป็นไปไม่ได้ที่จะทดสอบหน่วยอย่างถูกต้อง 2. บันทึกที่ใช้งานอยู่จ้องมองรหัสของคุณกับความสัมพันธ์ในกลไกการคงอยู่แบบรวมศูนย์ทำให้เป็นการยากที่จะแยกเสาหินของคุณถ้าคุณตัดสินใจ
istepaniuk

15

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

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

นอกจากนี้ยังทำให้การปฏิบัติการปรมาณูยุ่งยาก หากกลุ่มวัตถุต้องถูกบันทึกในแบบทั้งหมดหรือไม่มีอะไร (เช่นใบแจ้งหนี้และ InvoiceLines และ / หรือลูกค้าและ / หรือรายการ GL) วัตถุหนึ่งจะต้องรู้เกี่ยวกับวัตถุอื่น ๆ เหล่านี้ทั้งหมดและควบคุมการคงอยู่ของพวกเขา ( ซึ่งขยายขอบเขตของวัตถุควบคุมนั้นระเบียนที่เชื่อมต่อระหว่างกันขนาดใหญ่สามารถกลายเป็น "พระเจ้าวัตถุ" ที่รู้ทุกอย่างเกี่ยวกับการอ้างอิงของพวกเขา) หรือการควบคุมการทำธุรกรรมทั้งหมดจะต้องได้รับการจัดการจากภายนอกโดเมน AR?)

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


ในรูบีซึ่งอาจมีการกำหนดหรือคงอยู่หลังคำหลักหรือคำสั่งที่ง่ายมากอาจเป็นปัญหาที่น้อยกว่า ใน. NET ซึ่งต้องใช้ LoC มากขึ้นในการตั้งค่ากลไกการคงอยู่ต่าง ๆ โดยปกติแล้วจะมีการสำรองการเชื่อมต่อ SQL สำหรับแต่ละวัตถุโดยเฉพาะอย่างยิ่งโดยเฉพาะอย่างยิ่งหากต้องบันทึกวัตถุหลายวัตถุในธุรกรรมอะตอมมิกเดียว การเชื่อมต่อกับฐานข้อมูลดูเหมือนว่าคุณกำลังบันทึกใบแจ้งหนี้หรือลูกค้า คุณสามารถย่อสิ่งทั่วไปลงในคลาสพื้นฐานทั่วไปสำหรับวัตถุ ActiveRecord ทั้งหมดใน codebase ของคุณหรือแยกไปยังคลาสของตัวเอง (Repository)
KeithS

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

2

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

ดังนั้นการแก้ปัญหาคือการใช้ประโยชน์จากการใช้Data Mapperของ ORM สิ่งนี้แยกเลเยอร์การคงอยู่ออกและตอนนี้เราเป็นศูนย์กลางของตรรกะทางธุรกิจของเอนทิตี หลักคำสอนคือData Mapper ORM

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

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

ตัวอย่างเช่นสำหรับUser EntityจะมีUserRepositoryที่แสดงการรวบรวมวัตถุผู้ใช้ประเภทเดียวกัน (ที่เก็บไว้ในตารางผู้ใช้) ที่คุณสามารถดำเนินการได้ เพื่อที่จะไปยังตารางแบบสอบถามผู้ใช้ก็จะทำให้การใช้งานของผู้ใช้ข้อมูล Mapperแต่มันแยกออกมารูปแบบผู้ใช้โดเมน

รูปแบบพื้นที่เก็บข้อมูลเป็นประเภทของData Access Layerส่วนที่อื่นคือData Access Objectเท่านั้นความแตกต่างที่เก็บมีคุณลักษณะAggregate Root


รูปแบบพื้นที่เก็บข้อมูลและรูปแบบDAOแตกต่างกัน DAO คือการเข้าถึงข้อมูลทั่วไปพื้นที่เก็บข้อมูลมีไว้เพื่อการเก็บรวบรวมของวัตถุประเภทเดียวกันทั้งหมด เช่นที่เก็บข้อมูลทั้งหมดควรมีอินเทอร์เฟซเดียวกัน (เช่นอาร์เรย์หรือรายการ) ราชาแห่งวิธีอื่น ๆไม่ได้เป็นของที่เก็บ DAO อยู่ในระดับต่ำกว่าพื้นที่เก็บข้อมูลอาจใช้ DAO บ่อยครั้งโปรแกรมเมอร์ (โดยเฉพาะ PHP) ใช้ Repository เป็น DAO แต่มันไม่ถูกต้อง
xmedeko
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.