Trả lại một IQueryable từ một kho lưu trữ


8

Sử dụng mẫu Kho lưu trữ, có đúng không khi trả về IQueryable của tập dữ liệu (bảng), cho sử dụng chung?

Nó rất tiện dụng trong nhiều trường hợp, đặc biệt là khi sử dụng các thư viện bên ngoài tận dụng giao diện đó, ví dụ như một số plugin sắp xếp / lọc và liên kết với các phần tử ui.

Tuy nhiên, việc phơi bày một IQueryable đôi khi dường như khiến thiết kế dễ bị lỗi. Điều này, cùng với việc sử dụng sai tải lười biếng có thể dẫn đến các lượt truy cập hiệu suất nghiêm trọng.

Mặt khác, việc có các phương thức truy cập cho mỗi lần sử dụng có vẻ dư thừa và cũng rất nhiều công việc (xem xét các bài kiểm tra đơn vị, v.v.).


2
IMO: Ẩn công nghệ kiên trì (EF, NHibernate) từ các nhà phát triển là ý tưởng tồi. Chỉ cần phơi bày những gì công nghệ này tiếp xúc.
Euphoric

@Euphoric Ok, nhưng nếu trong ASP.NET MVC tôi có bộ điều khiển với 3000 dòng nơi mọi người vui vẻ tạo new DbContext()bất cứ khi nào họ cần và gọi SaveChanges()bất cứ khi nào họ muốn. Không thể kiểm tra bất cứ điều gì và chỉ có điều tôi có thể nghĩ là lớp bổ sung ẩn nó.
Mateusz

@Mateusz Đó không phải là vấn đề của công nghệ, mà là của con người. Bạn có nhà phát triển tào lao hoặc quản lý nhảm nhí, người không thể đào tạo các nhà phát triển nói đúng.
Euphoric

Câu trả lời:


12

Mark Seemann có một bài đăng blog tuyệt vời về chủ đề này: IQueryable là Kết nối chặt chẽ . Anh ấy tổng hợp nó một cách độc đáo trong phần cuối cùng (nhấn mạnh của tôi):

Bạn có thể nghĩ rằng đây là tất cả một bài tập lý thuyết, nhưng nó thực sự có vấn đề. Khi viết Clean Code, điều quan trọng là thiết kế API theo cách nó rõ ràng những gì nó làm.

Một giao diện như thế này đảm bảo sai:

public interface IRepository
{
    IQueryable<T> Query<T>();
}

Theo luật của LSP và Postel, dường như có thể đảm bảo rằng bạn có thể viết bất kỳ biểu thức truy vấn nào (dù phức tạp đến đâu) đối với trường hợp được trả về và nó sẽ luôn hoạt động .

Trong thực tế, điều này sẽ không bao giờ xảy ra.

Các lập trình viên xác định các giao diện như vậy luôn luôn có một ORM cụ thể và họ hoàn toàn có xu hướng ở trong giới hạn mà họ biết là an toàn cho ORM cụ thể đó. Đây là một sự trừu tượng bị rò rỉ.

Nếu bạn có một ORM cụ thể trong đầu, thì hãy nói rõ về nó. Đừng ẩn nó đằng sau một giao diện. Nó tạo ra ảo tưởng rằng bạn có thể thay thế một thực hiện bằng một thực hiện khác. Trong thực tế, điều đó là không thể. Hãy tưởng tượng bạn đang cố gắng cung cấp một triển khai trên Cửa hàng sự kiện.

Bánh là một lời nói dối.

ORM giống như Entity Framework là các triển khai của Kho lưu trữ và mẫu Đơn vị công việc. Không cần phải bọc chúng trong một cái khác.


Cảm ơn vi đa trả lơi. Có vẻ như mối quan tâm của tôi đã gặp những người của Seemann nhiều lần, nhưng tôi thực sự không dành thời gian để đọc anh ta, điều mà tôi dự định. Điều duy nhất tôi không đồng ý là kho lưu trữ - nếu được kết hợp mạnh mẽ - rất hữu ích để đóng gói logic kinh doanh, ngay cả khi ở cấp độ truy cập đơn giản hơn (ví dụ: VisibleItems, DeletingItems), v.v. và trợ giúp với khái niệm DRY.
Mihalis Bagos

@Kristof Chỉ cần một câu hỏi cho "Khung thực thể là các triển khai của Kho lưu trữ và mẫu Đơn vị công việc". Tôi có thể làm gì để mọi người không đặt new DbContext()bộ điều khiển và logic phức tạp vào một phương thức duy nhất trong MVC và sau đó không đặt một số logic trong các khung nhìn? Tôi có mã kế thừa nơi tôi không thể thực hiện bất kỳ thử nghiệm đơn vị nào. Để cho phép kiểm tra và ngăn mọi người thực hiện mã thực sự xấu, tôi cần lớp bổ sung. Do đó, tôi cần phải thực hiện các kho lưu trữ của riêng mình cho mục đích giáo dục.
Mateusz

Có các tùy chọn khác như các lớp dịch vụ hoặc các lớp lệnh và truy vấn.
Kristof Claes

1

Sẽ không có sự đồng thuận về điều này. Theo quan điểm và kinh nghiệm của tôi, một Kho lưu trữ sẽ trả về các đối tượng có cách sử dụng cụ thể. Tại leas nếu bạn sử dụng Mô hình kho lưu trữ như được xác định bởi Eric Evens trong DDD. Kho lưu trữ là "cầu nối" kết nối logic kinh doanh, sự bền bỉ và nhà máy.

Nếu bạn muốn truy cập vào sự kiên trì trực tiếp hơn, có thể bạn đang tìm kiếm Mẫu cổng.

Tuy nhiên, từ những gì bạn nói ở đây, bạn muốn che giấu sự tiếp xúc đó với sự kiên trì để Mẫu Proxy có thể giúp ích cho bạn.


Mặc dù tiếp xúc với sự kiên trì không phải là mối quan tâm chính, nhưng ít nhất một sự trừu tượng hóa ở mức cao nhất đối với các mẫu như các thực thể cha-con là bắt buộc. Tôi cũng sẽ xem xét các mẫu đó, cảm ơn bạn!
Mihalis Bagos
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.