2010-10-19 29 views
8

Tôi mới sử dụng TDD và DDD và tôi có một câu hỏi đơn giản về phương pháp tĩnh nói chung. Hầu hết các chuyên gia của TDD đều nói rằng một phương pháp tĩnh là xấu (và chúng ta nên quên việc tạo ra hàng tấn các tiện ích tĩnh mà chúng tôi đã sử dụng trước đây vì chúng không thể kiểm tra được. không thể kiểm tra (một bài báo làm rõ tuyệt vời có thể được tìm thấy here cho những người quan tâm nhưng tôi đoán tôi là noob duy nhất ở đây :() nhưng tôi đã tự hỏi là có một hướng dẫn tốt đẹp và sạch sẽ cho việc sử dụng các số liệu thống kê từ điểm TDD của xem?Phương pháp tĩnh: Khi nào và khi nào không

Đây có thể là câu hỏi thực sự ngớ ngẩn đối với hầu hết các bạn nhưng một số mẹo sẽ tuyệt vời và tôi chỉ muốn biết các chuyên gia ở đây nghĩ về những thứ tĩnh như thế nào.Thông báo trước:

Sửa: Tìm kiếm câu trả lời tốt đẹp đề về việc sử dụng tĩnh (không phải TDD quan tâm mặc dù) mà tôi đoán là đọc tốt cho những người quan tâm (bao gồm cả tôi).

Trả lời

11

Tôi nghĩ rằng bạn có thể đã hơi hiểu lầm.

Phương pháp tĩnh có thể kiểm tra. Hãy phương pháp này như một ví dụ:

public static int Add(int x, int y) 
{ 
    return x + y; 
} 

Bạn có thể kiểm tra điều này bằng cách kiểm tra rằng giá trị trả về là những gì bạn mong đợi dựa trên những lập luận thông qua vào

đâu phương pháp tĩnh trở thành rắc rối khi thử nghiệm là khi bạn cần. để giới thiệu một mô hình.

Giả sử tôi có một số mã gọi phương thức tĩnh File.Delete(). Để kiểm tra mã của tôi mà không dựa vào hệ thống tệp, tôi sẽ muốn thay thế/giả lập cuộc gọi này bằng một phiên bản thử nghiệm để xác minh rằng nó đã được gọi từ mã đang được kiểm tra. Điều này là dễ dàng để làm nếu tôi đã có một thể hiện của một đối tượng mà trên đó Delete() đã được gọi. Hầu hết (tất cả?) Mocking khuôn khổ không thể giả lập phương pháp tĩnh, vì vậy bằng cách sử dụng một phương pháp tĩnh trong mã của tôi buộc tôi để kiểm tra nó một cách khác nhau (thường là bằng cách gọi phương pháp thực sự tĩnh).

Để kiểm tra một cái gì đó như thế này, tôi sẽ giới thiệu một giao diện:

interface IFileDeleter 
{ 
    void Delete(string file); 
} 

Mã của tôi sau đó sẽ mất một thể hiện của một đối tượng mà thực hiện giao diện này (hoặc trong các cuộc gọi phương pháp hay như một tham số trong constructor), và sau đó gọi phương thức Delete() của nó để làm xóa:

void MyMethod(string file) 
{ 
    // do whatever... 
    deleter.Delete(file); 
} 

để kiểm tra điều này, tôi có thể làm cho một mô hình của giao diện IFileDeleter và chỉ cần xác minh rằng phương pháp Delete() của nó đã được gọi. Điều này loại bỏ sự cần thiết phải có một hệ thống tập tin thực sự như là một phần của thử nghiệm.

Điều này có thể giống như mã phức tạp hơn (có nghĩa là nó), nhưng nó trả tiền cho chính nó trong việc làm cho nó dễ dàng hơn để kiểm tra.

+0

+1! Typemock có thể giả lập các phương thức tĩnh, nhưng tốt hơn là tránh chúng (khi chúng cần được chế nhạo). – TrueWill

+0

+1 Cảm ơn heaps cho một câu trả lời toàn diện. Tôi sẽ chờ thêm vài câu trả lời nữa (nếu có) trước khi chọn câu trả lời vì lợi ích của việc chia sẻ kiến ​​thức – MSI

+0

Hm những gì tôi hỏi thực sự hơi ngớ ngẩn khi tôi đọc câu trả lời của bạn. vâng bạn đúng, tôi đã bỏ lỡ điểm khi tôi đặt câu hỏi. Đó là chế giễu khi họ gặp rắc rối thực sự; không tự kiểm tra phương thức đặc biệt khi nó chỉ là một phương thức tiện ích. – MSI

7

Nói chung, nếu phương pháp:

  • là chậm
  • là dài
  • Có logic phức tạp
  • Sử dụng hệ thống tập tin
  • Kết nối với một cơ sở dữ liệu
  • kêu gọi một trang web dịch vụ

sau đó tránh làm cho nó tĩnh. (Xem câu trả lời của @adrianbanks để có một cuộc thảo luận tuyệt vời về những lý do đằng sau điều này và các giải pháp thay thế.)

Về cơ bản, chỉ làm cho nó tĩnh nếu đó là phương pháp tiện lợi trong bộ nhớ ngắn (như nhiều phương pháp mở rộng).

+0

Tôi thích câu trả lời của bạn rất nhiều. Nó có ý nghĩa, bạn có thể kiểm tra logic của tĩnh như một phần của SUT, để thuận tiện cho tiện ích Static mang đến cho bạn, nếu và chỉ khi nó không có bất kỳ đặc điểm nào bạn viết ra. Vì vậy, với phương thức tĩnh, đơn giản, có hiệu ứng phụ miễn phí, bạn giả sử nó là một nguyên thủy, một phần mở rộng của ngôn ngữ của bạn, và chỉ sử dụng nó trong các đơn vị của bạn mà không bị cô lập. –

8

Tránh thống kê chắc chắn là cách để đi, nhưng khi bạn không thể hoặc bạn đang làm việc với mã Legacy, tùy chọn sau có sẵn. Sau ngày từ adrianbanks trả lời ở trên, giả sử bạn có mã sau đây (xin lỗi, nó trong Java như tôi không biết C#):

public void someMethod() { 
    //do somethings 
    File.delete(); 
    //do some more things 
} 

bạn có thể cấu trúc lại các File.Delete() vào phương pháp riêng của mình như này:

public void someMethod() { 
    //do somethings 
    deleteFile(); 
    //do some more things 
} 

//protected allows you to override in a subclass 
protected void deleteFile() { 
    File.delete(); 
} 

và sau đó để chuẩn bị cho bài kiểm tra đơn vị của bạn tạo ra một lớp giả kéo dài một bản gốc và khai ra chức năng:

//Keep all the original functionality, but stub out the file delete functionality to 
//prevent it from using the real thing and while you're at it, keep a record that the 
//method was called. 
public class MockClass extends TheRealClass { 
    boolean fileDeleteCalled = false; 

    @Override 
    protected void deleteFile() 
     //don't actually delete the file, 
     //just record that the method to do so was called 
     fileDeleteCalled = true; 
    } 

    public boolean fileDeleteCalled() { 
     return fileDeleteCalled; 
    } 
} 

và cuối cùng trong thử nghiệm đơn vị của bạn:

//This would normally be instantiated in the @Before method 
private MockClass unitUnderTest = new MockClass(); 

@Test 
public void testFileGetsDeleted(){ 
    assertFalse(unitUnderTest.fileDeleteCalled()); 
    unitUnderTest.someMethod(); 
    assertTrue(unitUnderTest.fileDeleteCalled()); 
} 

Bây giờ bạn đã thực hiện tất cả chức năng của someMethod() mà không thực sự xóa tệp và bạn vẫn có khả năng xem phương thức đó đã được gọi hay chưa.

+0

+1 cho ý tưởng tuyệt vời. Cảm ơn mate – MSI

+0

ai đó cho anh ta nhiều upvotes xin vui lòng cho các ví dụ tốt đẹp và làm rõ – MSI

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