Tóm tắt DAL - Sử dụng giao diện với lớp bên trong?


8

Chúng tôi có một lớp logic nghiệp vụ (BLL) được kết hợp chặt chẽ với lớp truy cập dữ liệu của chúng tôi (DAL). Chúng tôi thực hiện cuộc gọi như thế này:

using (FooData data = new FooData())
{
  data.DoSomething();
}

Điều quan trọng cần lưu ý là tất cả các lớp dữ liệu của chúng tôi đều internalở trong cùng một nhóm với các lớp logic, do đó chỉ BLL mới có thể truy cập DAL.

Để tách riêng những điều này (để giúp tạo điều kiện kiểm tra đơn vị), một ý tưởng là tạo các giao diện IDataClass, như IFooData. Lúc đầu, tôi nghĩ nó có thể là một vấn đề vì chúng ta phải công khai các lớp dữ liệu của mình để thực hiện các giao diện. Nhưng chúng ta có thể giữ các lớp dữ liệu bên trong, mặc dù chúng ta vẫn cần các phương thức được công khai:

public interface IFooData
{
  void DoSomething();
}

internal class FooData : IFooData  // Notice the class is internal
{
  public void DoSomething();  // Method is public, but that's ok because class is internal
}

Vì vậy, mặc dù phương thức này là công khai, vì bản thân lớp là nội bộ, chúng ta vẫn chỉ cho phép truy cập BLL của mình.

Có bất cứ điều gì vốn đã sai với phương pháp này? Có cách nào tốt hơn để trừu tượng hóa DAL, để thử nghiệm đơn vị, mà không cần mở DAL ra thế giới bằng cách công khai nó không?


1
Bạn đang cố gắng đạt được điều gì bằng cách giữ DAL của bạn bị khóa như thế này? Tại sao phải giữ bí mật? Nó cho thấy một loạt các phương thức, nó không quan tâm chính xác ai đang gọi chúng. Nếu bạn gặp sự cố với nó được gọi từ sai vị trí thì bạn có vấn đề xem lại mã.
sên

Bằng cách làm cho các phương thức bên trong, chỉ BLL có thể truy cập nó, điều này buộc tất cả các nhà phát triển phải thông qua BLL. Khi bạn có một nhóm lớn các nhà phát triển, bất cứ điều gì bạn có thể làm để giúp giảm thiểu sai lầm là một điều tốt.
Bob Horn

Tôi nhận ra rằng bạn đang cố gắng thực hiện một số lần nắm tay nhất định đối với các nhà phát triển sử dụng mã, nhưng khi làm như vậy bạn đã tạo cho mình một vấn đề khác. Đó là lý do tại sao tôi đưa ra nhận xét của mình - không có gì sai khi công khai các phương thức (đó là một thực tế bình thường). Nếu mọi người đang sử dụng chúng sai cách thì bạn có vấn đề xem lại mã.
sên

Tôi không đồng ý. Tại sao có sửa đổi nội bộ và tư nhân sau đó? Tại sao không chỉ làm cho mọi thứ công khai?
Bob Horn

Bob bạn đã hoàn toàn bỏ lỡ điểm. DAL trưng bày các nội dung công khai thông qua HỢP ĐỒNG là giao diện của bạn. Thực hành OO tiêu chuẩn có nghĩa là nó không biết ai đang gọi nó. Hãy nói thêm một lần nữa: bạn có thể biến lớp bên trong, nhưng bạn không cần . Phần còn lại của thế giới quản lý để có được bằng cách tiếp cận này, tại sao bạn không? Bạn cũng đã tự bắn vào chân mình ngay khi bạn có một BL hoặc dịch vụ khác cần gọi cùng một DAL - bạn có định tiếp tục thêm các hội đồng bạn bè không?
sên

Câu trả lời:


13

Trích xuất một giao diện và đảm bảo BLL chỉ sử dụng các loại giao diện là một cách tốt để chuyển BLL có thể kiểm tra mà không cần cơ sở dữ liệu.

Những gì bạn đang làm là hoàn toàn tốt.


3
Tôi sẽ nói thêm rằng những gì bạn đang làm là tốt, nhưng đó chỉ là bước đầu tiên. Nếu những gì bạn đang làm bây giờ là using (IFooData data = new FooData())trong BLL của bạn, bạn thực sự đã không thực hiện bất kỳ thay đổi nào ngoại trừ việc giới thiệu giao diện. Bây giờ bạn sẽ phải tìm cách khởi tạo IFooDatabên ngoài, nếu không các bài kiểm tra BLL của bạn vẫn sẽ được kết hợp với DAL.
Avner Shahar-Kashtan

Đã đồng ý. Bây giờ tôi thực sự đang làm một cái gì đó như thế này:DataAccessFactory.GetDataInterface<IFooData>().DoSomething();
Bob Horn

1

Bạn có thể sử dụng InternalsVisibleToAttributeđể tách DAL ra khỏi Lớp nghiệp vụ của mình, nhưng vẫn giữ các phương thức DAL bên trong. Cuối cùng bạn sẽ tạo DAL của bạn như một hội đồng bạn bè .

Đây có thể không phải là một cách tiếp cận tuyệt vời vì bạn sẽ phải chỉ định trong Assembly.cstệp DAL của mình mà các hội đồng có thể truy cập DAL. Vì vậy, vẫn còn một số khớp nối liên quan (DAL biết về BLL).

Vì vậy, để trả lời câu hỏi của bạn, không có gì sai với cách tiếp cận của bạn. Nhưng việc tận dụng các hội đồng bạn bè có thể cung cấp cho bạn sự trừu tượng hơn một chút và có thể giúp bạn giải quyết vấn đề.

Tôi hi vọng cái này giúp được.


Tôi thực sự không cần phải xóa DAL khỏi BLL; Tôi chỉ cần thực hiện một giao diện.
Bob Horn

Nhân tiện, cảm ơn. Tôi đã quen thuộc InternalsVisibleTovà nếu tôi cần chuyển DAL sang một tổ hợp khác, điều đó thực sự có ích.
Bob Horn

@BobHorn, vì vậy tôi không nhận được nó. Vấn đề gì để biến các lớp dal của bạn thành nội bộ? Bạn thậm chí có thể làm cho các giao diện DAL của bạn như là nội bộ. Tôi không thấy vấn đề ở đây.
Marcelo De Zen

Có các lớp DAL là nội bộ là những gì chúng ta hiện đang có, và những gì chúng ta muốn có trong tương lai. Các giao diện sẽ cần được công khai để BLL có thể yêu cầu một nhà máy triển khai cụ thể và không quan tâm đó là DAL thật hay giả. Tôi đoán toàn bộ câu hỏi của tôi thực sự là một kiểm tra sự tỉnh táo. Tôi có thiếu một cách tốt hơn để làm điều này?
Bob Horn

1

Bạn dường như bất động trước những ý tưởng của mình mà bạn đã giải thích trong câu hỏi của mình, nhưng dù sao tôi cũng sẽ trả lời một câu trả lời - ai đó có thể thấy nó hữu ích trong tương lai.

Nếu bạn khăng khăng giữ DAL của mình bên trong nhưng vẫn muốn đạt được nó với một số bài kiểm tra đơn vị và không bận tâm sử dụng các công cụ Kiểm tra Đơn vị của Microsoft, thì hãy thử phương pháp PrivateObject . Đây là một trình bao bọc cho sự phản chiếu mà bạn luôn có thể tự viết mã, nhưng nó giúp bạn tiết kiệm một vài dòng gõ.

Lưu ý rằng sử dụng InternalsVisibleTo một cách tiếp cận khả thi, nhưng thật vụng về - nếu bạn đang sử dụng thì bạn có thể đã xuống dốc nhanh. internalcó nghĩa là một cái gì đó chỉ công khai trong giới hạn lắp ráp của nó, công cụ sửa đổi đó thường được sử dụng vì bạn không muốn những thứ có thể sử dụng được từ bên ngoàihội nghị đó, sau đó bạn nhanh chóng quay lại và vi phạm khái niệm đó bằng cách tuyên bố một InternalsVisibleTo ... đó là một lá cờ đỏ lớn bẩn thỉu đang hét lên cho một số tái cấu trúc. Decoupling là một sự lãng phí thời gian khi chỉ có một hội đồng gọi cho nhau, bạn cũng có thể dán chúng lại với nhau. Việc tách riêng các phần tử mà nhiều hội đồng đang gọi mục tiêu (giới thiệu thử nghiệm đơn vị không được tính vào 'bội số' vì có nhiều cách để đến hội đồng mục tiêu như tôi đã đề cập).


Tại sao tôi dường như bất động về ý tưởng của mình? Tôi sẵn sàng đồng ý với bạn; Tôi chỉ cần một cuộc thảo luận để thuyết phục tôi trước. Và đừng nói với tôi rằng tôi vi phạm khái niệm này bằng cách sử dụng InternalsVisibleTo. Tôi không sử dụng nó. Vì một số lý do, bạn cho rằng tôi đang sử dụng nó. Tôi không hiểu tại sao.
Bob Horn

Nhân tiện, tôi đánh giá cao quan điểm của bạn vì nó khiến tôi phải xem xét lại quan điểm của mình. Tuy nhiên, hãy nhớ rằng tôi cũng được phép có ý kiến ​​của mình. Không cần phải trở nên lén lút vì tôi không đồng ý ngay với bạn.
Bob Horn

@Bob, xin lỗi, tôi đã bị cuốn vào góc độ cụ thể đó, tôi thấy từ nhận xét của bạn 'và nếu tôi cần chuyển DAL sang một hội đồng khác' thì DAL của bạn có thể đúng khi tôi đề xuất nó nên dành cho một mục nội bộ. Khi bạn đã quyết định phải làm gì, hãy chắc chắn rằng bạn viết nó lên đây (nếu không có câu trả lời nào phù hợp), sẽ rất thú vị để xem cuối cùng bạn nghĩ ra điều gì.
sên

1

Về mặt kỹ thuật, không có gì sai với thiết kế của bạn.

Tuy nhiên, tôi sẽ xem xét một cách tiếp cận khác: thay vì tách BLL khỏi DAL của bạn, tốt hơn là tách DAL của bạn khỏi cơ sở dữ liệu của bạn. Cho phép tạo các đối tượng DAL trong bộ nhớ và nếu BLL của bạn cần tải các đối tượng DAL từ một nơi nào đó, hãy sử dụng mẫu kho lưu trữ (xem tại đây ) để tránh tiếp xúc trực tiếp của BLL với cơ sở dữ liệu. Bằng cách đó, bạn có thể

  • tạo các bài kiểm tra đơn vị cho các đối tượng DAL của bạn một cách dễ dàng mà không cần cơ sở dữ liệu
  • tạo các thử nghiệm đơn vị cho BLL của bạn bằng cách cung cấp các đối tượng DAL được tạo trong bộ nhớ thông qua kho lưu trữ giả làm dữ liệu thử nghiệm (ok, bạn có thể tranh luận ngay bây giờ nếu các thử nghiệm đó thực sự được gọi là thử nghiệm đơn vị )

Trong thực tế, những gì bạn mất là khả năng thử nghiệm BLL với giả DAL. Nhưng trong thực tế, những đối tượng giả DAL đó thường sẽ trông rất giống các đối tượng DAL thực sự của bạn để cung cấp cơ sở cho các thử nghiệm hữu ích về BLL. IMHO nó tránh được rất nhiều sự trùng lặp mã và nỗ lực không cần thiết khi sử dụng lại các đối tượng DAL thực sự của bạn để kiểm tra BLL tự động.


0

Cách tiếp cận giao diện là một phương pháp tốt / chính thống để loại bỏ DAL của bạn trong quá trình thử nghiệm người tiêu dùng như BLL.

Tuy nhiên, một điều cần lưu ý là bằng cách làm cho các lớp bê tông DAL của bạn bên trong, là bạn có thể làm cho DAL cụ thể của bạn khó kiểm tra trực tiếp hơn, vì điều này bây giờ ngụ ý rằng các bài kiểm tra đơn vị DAL của bạn cũng phải được lắp ráp mà không cần sử dụng cửa sau như phản xạ.

Ngoài ra, tại một thời điểm nào đó trong tương lai, bạn có thể cân nhắc sử dụng bộ chứa IoC để xây dựng triển khai đằng sau một giao diện, cũng có thể gặp sự cố bên trong.

Bạn có thể bắt chước việc đóng gói mà bạn đang cố gắng đạt được với 'chỉ nội bộ' bằng cách thêm quy tắc / LINT rằng BLL / các lớp khác của bạn phải ghép với DAL thông qua giao diện, chứ không phải trên triển khai cụ thể.


Cảm ơn, nhưng các bài kiểm tra đơn vị Visual Studio thực sự có thể kiểm tra các phương thức nội bộ và riêng tư trong các hội đồng khác.
Bob Horn
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.