2008-09-24 39 views
6

This question about unit testing best practices đề cập đến việc thiết kế các lớp để tiêm phụ thuộc. Điều này khiến tôi suy nghĩ về chính xác điều đó có ý nghĩa gì.Hướng dẫn thiết kế các lớp cho tiêm phụ thuộc

Chỉ mới bắt đầu làm việc với đảo ngược các thùng chứa kiểm soát Tôi có một số ý tưởng về vấn đề này, vì vậy hãy để tôi ném chúng vào tường và xem những gì dính.

Cách tôi nhìn thấy, có ba loại phụ thuộc cơ bản mà một đối tượng có thể có.

  1. Đối tượng phụ thuộc - Đối tượng thực tế sẽ được lớp đó sử dụng. Ví dụ LogInVerifier trong một LogInFormController. Chúng nên được tiêm vào thông qua hàm tạo. Nếu lớp đó là đủ cao, nó đòi hỏi nhiều hơn 4 trong số các đối tượng này trong constructor xem xét phá vỡ nó lên hoặc ít nhất là bằng cách sử dụng một mẫu nhà máy. Bạn cũng nên xem xét việc cung cấp sự phụ thuộc với một giao diện và mã hóa dựa trên giao diện.
  2. Cài đặt đơn giản - Ví dụ: ngưỡng hoặc khoảng thời gian chờ. Các giá trị này thường có giá trị mặc định và được đặt thông qua trình tạo mẫu nhà máy. Bạn cũng có thể cung cấp quá tải khởi tạo để thiết lập chúng. Tuy nhiên, trong hầu hết các trường hợp, có lẽ bạn không nên ép buộc khách hàng phải thiết lập một cách rõ ràng.
  3. Đối tượng tin nhắn - Một đối tượng được chuyển từ lớp này sang lớp khác mà lớp nhận được có lẽ sử dụng cho logic nghiệp vụ. Một ví dụ sẽ là một đối tượng User cho một lớp LogInCompleRouter. Ở đây tôi thấy nó thường tốt hơn cho thông điệp không được chỉ định trong constructor vì bạn sẽ phải đăng ký cá thể User với IoC Container (làm cho nó toàn cục) hoặc không khởi tạo LogInCompleteRouter cho đến sau khi bạn có một cá thể của User (mà bạn không thể sử dụng DI hoặc ít nhất sẽ cần một sự phụ thuộc rõ ràng trên Container). Trong trường hợp này, tốt hơn là nên truyền đối tượng tin nhắn chỉ khi bạn cần nó cho lời gọi phương thức (ví dụ: LoginInCompleteRouter.Route (User u);).

Ngoài ra, tôi nên đề cập đến mà không mọi thứ nên DI'ed, nếu bạn có một chút đơn giản của chức năng đó chỉ là thuận tiện đến yếu tố ra một lớp ném đi, nó có lẽ là ok để nhanh chóng ngay tại chỗ. Rõ ràng đây là một cuộc gọi phán xét; nếu tôi thấy nó thích hợp để viết một lớp học như

class PasswordEqualsVerifier { 
    public bool Check(string input, string actual) { return input===actual;} 
} 

Tôi có thể sẽ không phụ thuộc vào việc tiêm nó và chỉ có một đối tượng khởi tạo trực tiếp bên trong khối sử dụng. Hệ quả là nếu nó là giá trị viết bài kiểm tra đơn vị cho, sau đó nó có thể là giá trị tiêm.

Vì vậy, các bạn nghĩ sao? Bất kỳ hướng dẫn bổ sung hoặc ý kiến ​​tương phản đều được hoan nghênh.

Trả lời

1

Điều quan trọng là cố gắng mã hóa các giao diện và yêu cầu các lớp của bạn chấp nhận các cá thể của các giao diện đó thay vì tự tạo các cá thể. Bạn rõ ràng có thể đi điên với điều này, nhưng đó là một thực hành tốt chung bất kể thử nghiệm đơn vị hoặc DI.

Ví dụ, nếu bạn có một Data Access Object, bạn có thể nghiêng để viết một cơ sở cho tất cả DAO như thế này:

public class BaseDAO 
{ 
    public BaseDAO(String connectionURL, 
        String driverName, 
        String username, String password) 
    { 
     // use them to create a connection via JDBC, e.g. 
    } 

    protected Connection getConnection() { return connection; } 
} 

Tuy nhiên, nó sẽ là tốt hơn để loại bỏ điều này từ lớp ủng hộ của một giao diện

public interface DatabaseConnection 
{ 
    Connection getConnection(); 
} 

public class BaseDAO 
{ 
    public BaseDAO(DatabaseConnection dbConnection) 
    { 
     this.dbConnection = dbConnection; 
    } 

    protected Connection getConnection() { return dbConnection.getConnection(); } 
} 

Bây giờ, bạn có thể thực hiện nhiều lần thực hiện DatabaseConnection. Thậm chí bỏ qua kiểm tra đơn vị, nếu chúng ta giả sử chúng ta đang sử dụng JDBC, có hai cách để có được một Connection: một nhóm kết nối từ vùng chứa hoặc trực tiếp thông qua việc sử dụng trình điều khiển. Bây giờ, mã DAO của bạn không được kết hợp với một trong hai chiến lược.

Để thử nghiệm, bạn có thể thực hiện MockDatabaseConnection kết nối với một số triển khai JDBC được nhúng với dữ liệu được đóng hộp để kiểm tra mã của bạn.

Các vấn đề liên quan