Tại sao tất cả các Active Record đều ghét? [đóng cửa]


103

Khi tôi ngày càng tìm hiểu nhiều hơn về OOP và bắt đầu triển khai các mẫu thiết kế khác nhau, tôi tiếp tục quay lại các trường hợp mà mọi người đang ghét trên Active Record .

Thông thường, mọi người nói rằng nó không mở rộng tốt (trích dẫn Twitter là ví dụ điển hình của họ) - nhưng không ai thực sự giải thích tại sao nó không mở rộng tốt; và / hoặc làm thế nào để đạt được ưu điểm của AR mà không có nhược điểm (thông qua một mẫu tương tự nhưng khác?)

Hy vọng rằng điều này sẽ không trở thành một cuộc thánh chiến về các mẫu thiết kế - tất cả những gì tôi muốn biết là **** cụ thể là **** Active Record có gì sai.

Nếu nó không mở rộng quy mô tốt, tại sao không?

Nó có những vấn đề gì khác?


9
Tôi đoán nói chung rất nhiều người ghét và không thích các mẫu thiết kế có liên quan đến việc sử dụng sai. Mọi người có xu hướng lạm dụng và sử dụng chúng trong bối cảnh sai lầm và kết thúc với một giải pháp phức tạp hơn so với bản gốc
terjetyl

1
Việc triển khai Active Record của Ruby giống một ORM hơn.
Jimmy T.

1
Có một hiện tượng xã hội là để có được sự đánh giá cao, được công nhận nhiều hơn, có vẻ thông minh hơn và dễ bị bắt gặp hơn, mọi người có xu hướng lặp lại một cách máy móc bất kỳ sự cường điệu phủ định nào của bất kỳ tiêu chuẩn, mô hình hiện tại, công nghệ được áp dụng rộng rãi nào, gây nhầm lẫn với cách mạng tiến tới làn sóng tiếp theo.
Andre Figueedlyo

Câu trả lời:


90

ActiveRecord the Design PatternActiveRecord the Rails ORM Library , và cũng có rất nhiều bản nhái cho .NET và các ngôn ngữ khác.

Đây là tất cả những thứ khác nhau. Họ chủ yếu tuân theo mẫu thiết kế đó, nhưng mở rộng và sửa đổi nó theo nhiều cách khác nhau, vì vậy trước khi bất kỳ ai nói "ActiveRecord Sucks", nó cần phải đủ điều kiện bằng cách nói "ActiveRecord, có đống nào?"

Tôi chỉ quen thuộc với ActiveRecord của Rails, tôi sẽ cố gắng giải quyết tất cả các khiếu nại đã được nêu ra trong bối cảnh sử dụng nó.

@BlaM

Vấn đề mà tôi thấy với Active Records là, nó luôn chỉ có một bảng

Mã:

class Person
    belongs_to :company
end
people = Person.find(:all, :include => :company )

Điều này tạo SQL với LEFT JOIN companies on companies.id = person.company_idvà tự động tạo các đối tượng Công ty được liên kết để bạn có thể làm people.first.companyvà nó không cần phải nhấn vào cơ sở dữ liệu vì dữ liệu đã có sẵn.

@ pix0r

Vấn đề cố hữu với Active Record là các truy vấn cơ sở dữ liệu được tự động tạo và thực thi để điền các đối tượng và sửa đổi bản ghi cơ sở dữ liệu

Mã:

person = Person.find_by_sql("giant complicated sql query")

Điều này không được khuyến khích vì nó xấu, nhưng đối với những trường hợp bạn chỉ cần viết SQL thô, nó sẽ dễ dàng thực hiện.

@Tim Sullivan

... và bạn chọn một số trường hợp của mô hình, về cơ bản bạn đang thực hiện "chọn * từ ..."

Mã:

people = Person.find(:all, :select=>'name, id')

Thao tác này sẽ chỉ chọn tên và cột ID từ cơ sở dữ liệu, tất cả các 'thuộc tính' khác trong các đối tượng được ánh xạ sẽ chỉ là con số không, trừ khi bạn tải lại đối tượng đó theo cách thủ công, v.v.


Hùng mạnh! Tôi không biết về tính năng cụ thể đó. Tuy nhiên, một lý lẽ ủng hộ AR khác để tôi đưa vào kho vũ khí của mình.
Tim Sullivan

Tham gia vượt ra ngoài mẫu Active Record.
Jimmy T.

"Person.find_by_sql" hoàn toàn không phải là mẫu Bản ghi Hoạt động. "Bản ghi hoạt động" của nó bị lỗi khá nhiều nên tôi cần phải vá nó theo cách thủ công.
magallanes

52

Tôi luôn thấy rằng ActiveRecord phù hợp với các ứng dụng dựa trên CRUD nhanh chóng trong đó Mô hình tương đối phẳng (như trong, không có nhiều phân cấp lớp). Tuy nhiên, đối với các ứng dụng có cấu trúc phân cấp OO phức tạp, DataMapper có lẽ là giải pháp tốt hơn. Mặc dù ActiveRecord giả định tỷ lệ 1: 1 giữa các bảng và đối tượng dữ liệu của bạn, nhưng loại mối quan hệ đó sẽ khó sử dụng với các miền phức tạp hơn. Trong cuốn sách của mình về các mẫu , Martin Fowler chỉ ra rằng ActiveRecord có xu hướng bị phá vỡ trong các điều kiện mà Mô hình của bạn khá phức tạp và đề xuất một DataMapper là lựa chọn thay thế.

Tôi đã thấy điều này đúng trong thực tế. Trong trường hợp bạn có nhiều quyền thừa kế trong miền của mình, việc ánh xạ kế thừa tới RDBMS của bạn sẽ khó hơn so với việc lập bản đồ các liên kết hoặc thành phần.

Cách tôi làm là có các đối tượng "miền" được bộ điều khiển của bạn truy cập thông qua các lớp DataMapper (hoặc "lớp dịch vụ") này. Chúng không phản ánh trực tiếp cơ sở dữ liệu, nhưng hoạt động như một đại diện OO của bạn cho một số đối tượng trong thế giới thực. Giả sử bạn có một lớp Người dùng trong miền của mình và cần có các tham chiếu đến hoặc các tập hợp các đối tượng khác, đã được tải khi bạn truy xuất đối tượng Người dùng đó. Dữ liệu có thể đến từ nhiều bảng khác nhau và mẫu ActiveRecord có thể làm cho nó thực sự khó khăn.

Thay vì tải trực tiếp đối tượng Người dùng và truy cập dữ liệu bằng API kiểu ActiveRecord, mã bộ điều khiển của bạn truy xuất đối tượng Người dùng bằng cách gọi API của phương thức UserMapper.getUser () chẳng hạn. Người lập bản đồ đó chịu trách nhiệm tải bất kỳ đối tượng nào được liên kết từ các bảng tương ứng của chúng và trả về đối tượng "miền" Người dùng đã hoàn thành cho người gọi.

Về cơ bản, bạn chỉ cần thêm một lớp trừu tượng khác để làm cho mã dễ quản lý hơn. Cho dù các lớp DataMapper của bạn có chứa SQL tùy chỉnh thô hay các lệnh gọi đến API lớp trừu tượng hóa dữ liệu, hoặc thậm chí tự truy cập vào mẫu ActiveRecord, không thực sự quan trọng đối với mã bộ điều khiển đang nhận một đối tượng Người dùng được phổ biến và đẹp mắt.

Dù sao thì, đó là cách tôi làm.


5
Có vẻ như bạn không quen với ActiveRecord. "ActiveRecord giả định tỷ lệ 1: 1 giữa các bảng của bạn". Đơn giản là không đúng chút nào. ActiveRecord có tất cả các loại phép thuật quan hệ tuyệt vời. Xem api.rubyonrails.org/classes/ActiveRecord/Associations/…
tybro0103 Ngày

16
@ JoãoBragança - có lẽ thay vì một bình luận châm biếm, bạn thực sự có thể giải thích những khó khăn xảy ra khi dữ liệu của một người bị chia nhỏ - vì vậy những người còn lại trong chúng ta có thể học được điều gì đó :)
Taryn East 22/11/11

11

Tôi nghĩ rằng có thể có một loạt lý do rất khác nhau giữa lý do tại sao mọi người "ghét" trên ActiveRecord và điều gì là "sai" với nó.

Về vấn đề ghét, có rất nhiều nọc độc đối với bất cứ thứ gì liên quan đến Rails. Đối với những gì sai với nó, có thể nó giống như tất cả các công nghệ và có những tình huống mà nó là một lựa chọn tốt và những tình huống có những lựa chọn tốt hơn. Theo kinh nghiệm của tôi, tình huống mà bạn không tận dụng được hầu hết các tính năng của Rails ActiveRecord là do cơ sở dữ liệu có cấu trúc không tốt. Nếu bạn đang truy cập dữ liệu mà không có khóa chính, với những thứ vi phạm biểu mẫu bình thường đầu tiên, nơi có rất nhiều thủ tục được lưu trữ cần thiết để truy cập dữ liệu, bạn tốt hơn nên sử dụng thứ gì đó không chỉ là trình bao bọc SQL. Nếu cơ sở dữ liệu của bạn có cấu trúc tương đối tốt, ActiveRecord cho phép bạn tận dụng lợi thế đó.

Để thêm vào chủ đề trả lời những người bình luận nói rằng mọi thứ khó khăn trong ActiveRecord với trình kết nối lại đoạn mã

@Sam McAfee Giả sử bạn có một lớp Người dùng trong miền của mình và cần có các tham chiếu đến hoặc các tập hợp các đối tượng khác, đã được tải khi bạn truy xuất đối tượng Người dùng đó. Dữ liệu có thể đến từ nhiều bảng khác nhau và mẫu ActiveRecord có thể làm cho nó thực sự khó khăn.

user = User.find(id, :include => ["posts", "comments"])
first_post = user.posts.first
first_comment = user.comments.first

Bằng cách sử dụng tùy chọn bao gồm, ActiveRecord cho phép bạn ghi đè hành vi tải lười mặc định.


8

Câu trả lời dài và muộn của tôi, thậm chí không đầy đủ, nhưng là một lời giải thích tốt TẠI SAO tôi ghét khuôn mẫu này, ý kiến ​​và thậm chí một số cảm xúc:

1) phiên bản ngắn: Active Record tạo ra một " lớp mỏng " " ràng buộc chặt chẽ " giữa cơ sở dữ liệu và mã ứng dụng. Giải quyết không logic, không có vấn đề gì, không có vấn đề gì cả. IMHO nó không cung cấp BẤT KỲ GIÁ TRỊ NÀO, ngoại trừ một số đường cú pháp cho lập trình viên (sau đó có thể sử dụng "cú pháp đối tượng" để truy cập một số dữ liệu tồn tại trong cơ sở dữ liệu quan hệ). Nỗ lực tạo sự thoải mái cho các lập trình viên nên (IMHO ...) tốt hơn nên được đầu tư vào các công cụ truy cập cơ sở dữ liệu cấp thấp, ví dụ như một số biến thể của hash_map get_record( string id_value, string table_name, string id_column_name="id" )các phương pháp đơn giản, dễ dàng, đơn giản và tương tự (tất nhiên, các khái niệm và sự sang trọng khác nhau rất nhiều với ngôn ngữ sử dụng).

2) phiên bản dài: Trong bất kỳ dự án nào dựa trên cơ sở dữ liệu mà tôi có quyền "kiểm soát khái niệm" của mọi thứ, tôi đã tránh AR, và điều đó là tốt. Tôi thường xây dựng một kiến trúc phân lớp (sớm hay muộn bạn cũng chia phần mềm của mình thành các lớp, ít nhất là trong các dự án quy mô vừa đến lớn):

A1) bản thân cơ sở dữ liệu, bảng, quan hệ, thậm chí một số logic nếu DBMS cho phép nó (MySQL hiện cũng đã phát triển)

A2) rất thường xuyên, có nhiều hơn một kho lưu trữ dữ liệu: hệ thống tệp (các đốm màu trong cơ sở dữ liệu không phải lúc nào cũng là một quyết định tốt ...), các hệ thống kế thừa (hãy tự tưởng tượng "cách" chúng sẽ được truy cập, nhiều loại có thể .. nhưng đó là không phải là vấn đề ...)

B) lớp truy cập cơ sở dữ liệu (ở cấp độ này, các phương thức công cụ, người trợ giúp dễ dàng truy cập dữ liệu trong cơ sở dữ liệu rất được hoan nghênh, nhưng AR không cung cấp bất kỳ giá trị nào ở đây, ngoại trừ một số cú pháp)

C) lớp đối tượng ứng dụng: "đối tượng ứng dụng" đôi khi là các hàng đơn giản của bảng trong cơ sở dữ liệu, nhưng hầu hết chúng đều là các đối tượng phức hợp và có một số logic cao hơn được đính kèm, vì vậy đầu tư thời gian vào các đối tượng AR ở cấp độ này rõ ràng là vô ích , lãng phí thời gian quý báu của lập trình viên, bởi vì "giá trị thực", "logic cao hơn" của các đối tượng đó cần phải được thực hiện trên các đối tượng AR - dù có và không có AR! Và, ví dụ, tại sao bạn muốn có một phần trừu tượng của "Đối tượng mục nhập nhật ký"? Mã logic ứng dụng ghi chúng, nhưng liệu mã đó có khả năng cập nhật hoặc xóa chúng không? nghe có vẻ ngớ ngẩn và App::Log("I am a log message")một số cường độ có dễ sử dụng hơnle=new LogEntry(); le.time=now(); le.text="I am a log message"; le.Insert();. Và ví dụ: sử dụng "Đối tượng nhập nhật ký" trong chế độ xem nhật ký trong ứng dụng của bạn sẽ hoạt động cho 100, 1000 hoặc thậm chí 10000 dòng nhật ký, nhưng sớm hay muộn bạn sẽ phải tối ưu hóa - và tôi cá là trong hầu hết các trường hợp, bạn sẽ chỉ sử dụng câu lệnh SQL SELECT nhỏ xinh đó trong logic ứng dụng của bạn (điều này hoàn toàn phá vỡ ý tưởng AR ..), thay vì gói câu lệnh nhỏ đó trong các khung ý tưởng AR cố định cứng nhắc với nhiều gói mã và ẩn nó. Thời gian bạn lãng phí với việc viết và / hoặc xây dựng mã AR có thể đã được đầu tư vào một giao diện thông minh hơn nhiều để đọc danh sách các mục nhập nhật ký (rất nhiều cách, bầu trời là giới hạn). Người lập trình nên dám phát minh ra các trừu tượng mới để nhận ra logic ứng dụng của họ phù hợp với ứng dụng dự định, và không triển khai lại các mẫu ngớ ngẩn một cách ngu ngốc, âm thanh tốt ngay từ cái nhìn đầu tiên!

D) logic ứng dụng - thực hiện logic của các đối tượng tương tác và tạo, xóa và liệt kê (!) Các đối tượng logic ứng dụng (KHÔNG, những tác vụ đó hiếm khi được neo trong chính các đối tượng logic ứng dụng: tờ giấy trên bàn của bạn cho biết tên và vị trí của tất cả các trang tính khác trong văn phòng của bạn? Hãy quên các phương pháp "tĩnh" để liệt kê các đối tượng, thật ngớ ngẩn, một sự thỏa hiệp tồi tệ được tạo ra để làm cho lối suy nghĩ của con người phù hợp với [một số-không-phải-tất-cả-AR-framework-like -] AR đang suy nghĩ)

E) giao diện người dùng - tốt, những gì tôi sẽ viết trong những dòng sau là rất rất, rất chủ quan, nhưng theo kinh nghiệm của tôi, các dự án được xây dựng trên AR thường bỏ qua phần giao diện người dùng của một ứng dụng - thời gian đã lãng phí vào việc tạo ra những điều trừu tượng khó hiểu . Cuối cùng, những ứng dụng như vậy đã lãng phí rất nhiều thời gian của người lập trình và cảm thấy giống như những ứng dụng từ người viết mã dành cho người lập trình, thiên về công nghệ bên trong và bên ngoài. Các lập trình viên cảm thấy tốt (công việc khó khăn cuối cùng đã hoàn thành, mọi thứ hoàn thành và chính xác, theo khái niệm trên giấy ...), và khách hàng "chỉ cần học rằng nó cần phải như vậy", bởi vì đó là "chuyên nghiệp" .. ok, xin lỗi, tôi lạc đề ;-)

Vâng, phải thừa nhận rằng tất cả điều này là chủ quan, nhưng đó là kinh nghiệm của tôi (loại trừ Ruby on Rails, nó có thể khác và tôi không có kinh nghiệm thực tế về cách tiếp cận đó).

Trong các dự án trả phí, tôi thường nghe thấy yêu cầu bắt đầu bằng việc tạo một số đối tượng "bản ghi hoạt động" như một khối xây dựng cho logic ứng dụng cấp cao hơn. Theo kinh nghiệm của tôi, điều này dễ thấy làlà một lý do nào đó để khách hàng (một công ty phát triển phần mềm trong hầu hết các trường hợp) không có một khái niệm tốt, một cái nhìn lớn, một cái nhìn tổng quan về sản phẩm cuối cùng nên là gì. Những khách hàng đó nghĩ theo khung cứng nhắc ("trong dự án mười năm trước nó hoạt động tốt .."), họ có thể làm thịt các thực thể, họ có thể xác định quan hệ thực thể, họ có thể phá vỡ quan hệ dữ liệu và xác định logic ứng dụng cơ bản, nhưng sau đó họ dừng lại và giao nó cho bạn, và nghĩ rằng đó là tất cả những gì bạn cần ... họ thường thiếu khái niệm đầy đủ về logic ứng dụng, giao diện người dùng, khả năng sử dụng, v.v. họ thiếu tầm nhìn rộng và họ thiếu tình yêu với và họ muốn bạn làm theo cách AR đó, bởi vì .. à, tại sao, nó hoạt động trong dự án đó nhiều năm trước, nó khiến mọi người bận rộn và im lặng? Tôi không biết. Nhưng "chi tiết" tách những người đàn ông khỏi những chàng trai, hoặc .. khẩu hiệu quảng cáo ban đầu như thế nào? ;-)

Sau nhiều năm (mười năm kinh nghiệm phát triển tích cực), bất cứ khi nào khách hàng đề cập đến "mẫu hồ sơ hoạt động", chuông báo thức của tôi đổ chuông. Tôi đã học được cách cố gắng đưa họ trở lại giai đoạn đặc biệt quan trọng đó , để họ suy nghĩ kỹ lưỡng, thử cho họ thấy những điểm yếu đặc biệt của họ hoặc chỉ tránh chúng nếu họ không quan tâm (cuối cùng, bạn biết đấy, một khách hàng chưa biết nó muốn gì, thậm chí có thể nghĩ nó biết nhưng không, hoặc cố gắng ngoại hóa công việc khái niệm cho TÔI một cách miễn phí, khiến tôi mất nhiều giờ, ngày, tuần và tháng quý giá trong thời gian của tôi, thời gian sống là quá ngắn ...).

Vì vậy, cuối cùng: TẤT CẢ ĐÂY là lý do tại sao tôi ghét "mô hình ghi hoạt động" ngớ ngẩn đó, và tôi đã và sẽ tránh nó bất cứ khi nào có thể.

CHỈNH SỬA : Tôi thậm chí sẽ gọi điều này là Không có khuôn mẫu. Nó không giải quyết bất kỳ vấn đề nào (các mẫu không có nghĩa là để tạo ra đường cú pháp). Nó tạo ra nhiều vấn đề: gốc rễ của tất cả các vấn đề của nó (được đề cập trong nhiều câu trả lời ở đây ..) là nó chỉ che giấu SQL cũ tốt được phát triển tốt và mạnh mẽ đằng sau một giao diện mà định nghĩa mẫu cực kỳ hạn chế.

Mô hình này thay thế sự linh hoạt bằng đường cú pháp!

Bạn thử nghĩ xem, AR giải quyết được vấn đề gì cho bạn?


1
Nó là một mẫu kiến ​​trúc nguồn dữ liệu. Có lẽ bạn nên đọc Các mẫu Kiến trúc Ứng dụng Doanh nghiệp của Fowler? Tôi đã có những suy nghĩ tương tự như bạn trước khi thực sự sử dụng mẫu / ORM và nhận thấy nó đã đơn giản hóa mọi thứ đến mức nào.
MattMcKnight

1
Tôi chia sẻ cảm xúc của bạn. Tôi cảm thấy có điều gì đó không ổn khi một khung công tác không hỗ trợ khóa ghép .... Tôi đã tránh bất kỳ loại ORM nào trước SQLAlchemy và chúng tôi thường sử dụng nó ở cấp thấp hơn, như một trình tạo SQL. Nó triển khai Data Mapper và rất linh hoạt.
Marco Mariani

1
Kể từ hai ngày tôi tham gia vào một dự án sử dụng ORM "hiện đại", có thể việc triển khai bây giờ đã hoàn thiện (so với những gì tôi đã làm với vài năm trước). Có lẽ, suy nghĩ của tôi sẽ thay đổi, chúng ta sẽ thấy trong ba tháng :-)
Frunsi

2
Dự án đã hoàn thành, và bạn biết gì không? ORM vẫn tệ, tôi đã lãng phí quá nhiều thời gian với các vấn đề ánh xạ dễ dàng được diễn đạt theo cách quan hệ với một loạt "mã hướng đối tượng". Vâng, tất nhiên ORM cung cấp các cách để diễn đạt các truy vấn theo kiểu OOP + SQL-Mix - tất nhiên là theo cú pháp giống OOP - nhưng điều đó chỉ tốn nhiều thời gian hơn là chỉ viết một truy vấn SQL. Phần tóm tắt bị rò rỉ, "OOPSQLExperiment" trên OOP - cho phép người dùng viết SQL theo cú pháp OOP là ý tưởng tồi tệ nhất từ ​​trước đến nay. Không, không bao giờ nữa.
Frunsi

1
Tôi đã viết SQL thô cho mọi thứ trong nhiều năm. Rails AR đôi khi làm tôi thất vọng và đối với truy vấn thụ động, tôi gần như đồng ý với bạn nhưng đây là những gì nó giải quyết được: 1) Làm cho việc lưu dữ liệu không được xác thực khó phù hợp. 2) Theo dõi những gì đã thay đổi trong bộ nhớ kể từ lần cuối cùng tồn tại. 3) Sử dụng điểm 2 để viết các lệnh before_savegọi lại hợp lý để duy trì tính nhất quán trong bản ghi 4) các after_commitmóc cho các trình kích hoạt dịch vụ bên ngoài. 5) Một DSL tốt để tổ chức các thay đổi DDL thành các tập thay đổi (di chuyển). (Vẫn còn đau ở đó nhưng không có mô hình là tồi tệ hơn khi> 1 nhà phát triển.)
Adamantish

6

Một số tin nhắn đang làm tôi bối rối. Một số câu trả lời sẽ là "ORM" so với "SQL" hoặc tương tự như vậy.

Thực tế là AR chỉ là một mẫu lập trình đơn giản hóa trong đó bạn tận dụng các đối tượng miền của mình để viết mã truy cập cơ sở dữ liệu vào đó.

Các đối tượng này thường có các thuộc tính nghiệp vụ (thuộc tính của bean) và một số hành vi (các phương thức thường hoạt động trên các thuộc tính này).

AR chỉ nói "thêm một số phương thức vào các đối tượng miền này" vào các tác vụ liên quan đến cơ sở dữ liệu.

Và tôi phải nói, từ quan điểm và kinh nghiệm của tôi, rằng tôi không thích khuôn mẫu.

Ngay từ cái nhìn đầu tiên, nó có thể nghe khá tốt. Một số công cụ Java hiện đại như Spring Roo sử dụng mẫu này.

Đối với tôi, vấn đề thực sự chỉ là mối quan tâm của OOP. Mô hình AR buộc bạn theo một cách nào đó để thêm phần phụ thuộc từ đối tượng của mình vào cơ sở hạ tầng đối tượng. Các đối tượng cơ sở hạ tầng này cho phép đối tượng miền truy vấn cơ sở dữ liệu thông qua các phương pháp được đề xuất bởi AR.

Tôi luôn nói rằng hai lớp là chìa khóa thành công của một dự án. Lớp dịch vụ (nơi chứa logic kinh doanh hoặc có thể được xuất thông qua một số loại công nghệ loại bỏ, chẳng hạn như Dịch vụ Web) và lớp miền. Theo ý kiến ​​của tôi, nếu chúng ta thêm một số phụ thuộc (không thực sự cần thiết) vào các đối tượng lớp miền để giải quyết mẫu AR, thì các đối tượng miền của chúng ta sẽ khó chia sẻ với các lớp khác hoặc (hiếm) các ứng dụng bên ngoài.

Việc triển khai Spring Roo của AR rất thú vị, bởi vì nó không dựa vào bản thân đối tượng, mà trong một số tệp AspectJ. Nhưng nếu sau này bạn không muốn làm việc với Roo và phải cấu trúc lại dự án, thì các phương thức AR sẽ được triển khai trực tiếp trong các đối tượng miền của bạn.

Một góc nhìn khác. Hãy tưởng tượng chúng ta không sử dụng Cơ sở dữ liệu quan hệ để lưu trữ các đối tượng của mình. Hãy tưởng tượng ứng dụng lưu trữ các đối tượng miền của chúng ta trong Cơ sở dữ liệu NoSQL hoặc chỉ trong các tệp XML chẳng hạn. Chúng ta có triển khai các phương thức thực hiện các tác vụ này trong các đối tượng miền của chúng ta không? Tôi không nghĩ như vậy (ví dụ, trong trường hợp của XM, chúng tôi sẽ thêm các phụ thuộc liên quan đến XML vào các đối tượng miền của chúng tôi ... Tôi nghĩ thật sự rất buồn). Tại sao chúng ta phải triển khai các phương thức DB quan hệ trong các đối tượng miền, như mẫu Ar đã nói?

Tóm lại, mô hình AR có vẻ đơn giản hơn và tốt cho các ứng dụng nhỏ và đơn giản. Tuy nhiên, khi chúng ta có các ứng dụng lớn và phức tạp, tôi nghĩ rằng kiến ​​trúc phân lớp cổ điển là một cách tiếp cận tốt hơn.


Chào mừng đến với SO. Đánh giá cao nhận xét của bạn nhưng câu hỏi này đã được NullUserException đóng lại là không mang tính xây dựng vào ngày 17 tháng 12 '11 lúc 1:17
Tony Rad

3

Câu hỏi là về mẫu thiết kế Active Record. Không phải là Công cụ orm.

Câu hỏi ban đầu được gắn thẻ với đường ray và đề cập đến Twitter được xây dựng bằng Ruby on Rails. Khung ActiveRecord trong Rails là một triển khai của mẫu thiết kế Active Record của Fowler.


2

Điều chính mà tôi đã thấy liên quan đến các phàn nàn về Active Record là khi bạn tạo một mô hình xung quanh một bảng và bạn chọn một số trường hợp của mô hình, về cơ bản bạn đang thực hiện "select * from ...". Điều này tốt cho việc chỉnh sửa bản ghi hoặc hiển thị bản ghi, nhưng nếu bạn muốn, chẳng hạn, hiển thị danh sách các thành phố cho tất cả các địa chỉ liên hệ trong cơ sở dữ liệu của bạn, bạn có thể thực hiện "chọn Thành phố từ ..." và chỉ lấy các thành phố . Thực hiện điều này với Active Record sẽ yêu cầu bạn chọn tất cả các cột, nhưng chỉ sử dụng City.

Tất nhiên, các triển khai khác nhau sẽ xử lý điều này theo cách khác nhau. Tuy nhiên, đó là một vấn đề.

Bây giờ, bạn có thể giải quyết vấn đề này bằng cách tạo ra một mô hình mới cho điều cụ thể mà bạn đang cố gắng làm, nhưng một số người sẽ cho rằng đó là nỗ lực nhiều hơn là lợi ích.

Tôi, tôi đào Active Record. :-)

HTH


2
"Làm điều này với Active Record sẽ yêu cầu bạn phải chọn tất cả các cột, nhưng chỉ sử dụng City." Nó thực sự cực kỳ dễ dàng để chỉ định một mệnh đề chọn.
MattMcKnight

1

Tôi thích cách SubSonic thực hiện điều chỉ một cột.
Hoặc

DataBaseTable.GetList(DataBaseTable.Columns.ColumnYouWant)

, hoặc là:

Query q = DataBaseTable.CreateQuery()
               .WHERE(DataBaseTable.Columns.ColumnToFilterOn,value);
q.SelectList = DataBaseTable.Columns.ColumnYouWant;
q.Load();

Nhưng Linq vẫn là vua khi nói đến tải lười biếng.


1

@BlaM: Đôi khi tôi chỉ thực hiện một bản ghi hoạt động cho kết quả của một phép nối. Không phải lúc nào cũng phải là Bảng quan hệ <--> Bản ghi Hoạt động. Tại sao không phải là "Kết quả của câu lệnh Tham gia" <--> Bản ghi Hoạt động?


1

Tôi sẽ nói về Active Record như một mẫu thiết kế, tôi chưa thấy ROR.

Một số nhà phát triển ghét Active Record vì họ đọc những cuốn sách thông minh về cách viết mã gọn gàng và sạch sẽ và những cuốn sách này tuyên bố rằng bản ghi hoạt động vi phạm nguyên tắc tương ứng đơn lẻ, vi phạm quy tắc DDD rằng đối tượng miền phải không biết cố định và nhiều quy tắc khác từ những loại sách này .

Đối tượng miền thứ hai trong Active Record có xu hướng là 1-1 với cơ sở dữ liệu, điều này có thể được coi là một hạn chế trong một số loại hệ thống (chủ yếu là n-tier).

Đó chỉ là những thứ trừu tượng, tôi chưa thấy ruby ​​trên đường ray thực hiện mô hình này.


0

Vấn đề mà tôi thấy với Active Records là, nó luôn chỉ có một bảng. Điều đó không sao cả, miễn là bạn thực sự chỉ làm việc với một bảng đó, nhưng khi bạn làm việc với dữ liệu trong hầu hết các trường hợp, bạn sẽ có một số kiểu kết hợp ở đâu đó.

Đúng, tham gia thường tệ hơn là không tham gia chút nào khi nói đến hiệu suất, nhưng tham gia thường tốt hơn tham gia "giả" bằng cách đọc toàn bộ bảng A và sau đó sử dụng thông tin thu được để đọc và lọc bảng B.


@BlaM: Bạn hoàn toàn đúng. Mặc dù tôi chưa bao giờ sử dụng Active Record, nhưng tôi đã sử dụng các hệ thống ORM hỗ trợ khác (đặc biệt là NHibernate) và có hai phàn nàn lớn mà tôi gặp phải: những cách ngớ ngẩn để tạo các đối tượng (tức là, các tệp .hbm.xml, mỗi tệp đều nhận được được biên dịch thành assembly của riêng chúng) và hiệu suất xảy ra khi tải các đối tượng (NHibernate có thể tăng đột biến một proc lõi đơn trong vài giây khi thực thi một truy vấn mà không tải gì cả, khi một truy vấn SQL tương đương hầu như không xử lý). Tất nhiên, không dành riêng cho Active Record, nhưng tôi thấy hầu hết các hệ thống ORM (và các hệ thống giống ORM) dường như
TheSmurf 11/08/08

Có nhiều lựa chọn thay thế để sử dụng tệp hbm.xml. Hãy xem ví dụ NHibernate.Mapping.Attributes và thông thạo-nhibernate.
Mauricio Scheffer

Về hiệu suất tạo đối tượng, tôi chưa bao giờ gặp phải các vấn đề về hiệu suất như vậy, bạn có thể muốn kiểm tra bằng một trình biên dịch.
Mauricio Scheffer

@mausch: Không cần hồ sơ. Đó là một vấn đề khá nổi tiếng. Không biết liệu nó có áp dụng cho phiên bản mới nhất (mà tôi đang làm việc chưa sử dụng). ayende.com/Blog/archive/2007/10/26/…
TheSmurf

4
Việc sử dụng: tham gia hoặc: bao gồm trong IE Customer.find tìm thấy (: tất cả,: bao gồm =>: danh bạ,: điều kiện => "hoạt động = 1") sẽ thực hiện một phép nối SQL chứ không phải quét toàn bộ bảng.
Tilendor

0

Vấn đề với ActiveRecord là các truy vấn mà nó tự động tạo cho bạn có thể gây ra các vấn đề về hiệu suất.

Cuối cùng, bạn phải thực hiện một số thủ thuật không trực quan để tối ưu hóa các truy vấn khiến bạn băn khoăn liệu có nên viết truy vấn bằng tay ngay từ đầu có hiệu quả hơn không.


0

Mặc dù tất cả các nhận xét khác liên quan đến việc tối ưu hóa SQL chắc chắn là hợp lệ, nhưng khiếu nại chính của tôi với mẫu bản ghi hoạt động là nó thường dẫn đến sự không khớp về trở kháng . Tôi muốn giữ cho miền của mình sạch sẽ và được đóng gói đúng cách, điều mà mẫu bản ghi hoạt động thường làm tiêu tan mọi hy vọng làm được.


ActiveRecord thực sự giải quyết vấn đề không khớp trở kháng bằng cách cho phép bạn viết mã theo kiểu OO dựa trên một lược đồ quan hệ.
Mauricio Scheffer

Chăm sóc công phu? Sự đồng thuận chung là các đối tượng được mô hình hóa sau cơ sở dữ liệu quan hệ, theo định nghĩa, không phải hướng đối tượng (vì cơ sở dữ liệu quan hệ không xoay quanh các khái niệm OO như kế thừa và đa hình).
Kevin Pang

Có ba cách đã biết để ánh xạ kế thừa vào một lược đồ quan hệ. Tham khảo: Castleproject.org/ActiveRecord/documentation/trunk/usersguide/…
Mauricio Scheffer

Tôi nghĩ rằng bạn đang nhầm dự án Castle Active Record OSS với Active Record mẫu thiết kế. Câu hỏi ban đầu (và câu trả lời của tôi) đề cập đến mẫu thiết kế. Dự án Castle Active Record có những thứ được đưa vào để giúp phát triển OO, nhưng bản thân mô hình thì không.
Kevin Pang

Tôi chỉ trích dẫn Castle để tham khảo. ActiveRecord ROR của thực đơn bảng thừa kế duy nhất ( martinfowler.com/eaaCatalog/singleTableInheritance.html ), nhưng các chiến lược khác đang được xem xét ( blog.zerosum.org/2007/2/16/... )
Mauricio Scheffer

0

Hãy thử thực hiện mối quan hệ đa hình từ nhiều đến nhiều. Không dễ thế đâu. Đặc biệt là khi bạn không sử dụng STI.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.