Mocking lớp bê tông - Không khuyến khích


11

Tôi vừa đọc một đoạn trích của cuốn sách "Phát triển phần mềm hướng đối tượng" giải thích một số lý do tại sao không khuyến khích lớp bê tông.

Dưới đây là một số mã mẫu của bài kiểm tra đơn vị cho lớp MusicCentre:

public class MusicCentreTest {
  @Test public void startsCdPlayerAtTimeRequested() {
    final MutableTime scheduledTime = new MutableTime();
    CdPlayer player = new CdPlayer() { 
      @Override 
      public void scheduleToStartAt(Time startTime) {
        scheduledTime.set(startTime);
      }
    }

    MusicCentre centre = new MusicCentre(player);
    centre.startMediaAt(LATER);

    assertEquals(LATER, scheduledTime.get());
  }
}

Và lời giải thích đầu tiên của anh ấy:

Vấn đề với cách tiếp cận này là nó để lại mối quan hệ giữa các đối tượng ngầm. Tôi hy vọng chúng ta đã nói rõ rằng ý định phát triển dựa trên thử nghiệm với các đối tượng giả là khám phá mối quan hệ giữa các đối tượng. Nếu tôi phân lớp, không có gì trong mã miền để hiển thị mối quan hệ như vậy, chỉ là các phương thức trên một đối tượng. Điều này làm cho khó khăn hơn để xem liệu dịch vụ hỗ trợ mối quan hệ này có thể có liên quan ở nơi khác hay không và tôi sẽ phải làm lại phân tích lần sau khi tôi làm việc với lớp.

Tôi không thể hiểu chính xác ý anh ta khi anh ta nói:

Điều này làm cho khó khăn hơn để xem liệu dịch vụ hỗ trợ mối quan hệ này có thể có liên quan ở nơi khác hay không và tôi sẽ phải làm lại phân tích lần sau khi tôi làm việc với lớp.

Tôi hiểu rằng dịch vụ tương ứng với MusicCentrephương thức được gọi startMediaAt.

Anh ta có ý gì bởi "nơi khác"?

Đoạn trích hoàn chỉnh có tại đây: http://www.mockobjects.com/2007/04/test-smell-mocking-concittle-classes.html


Đã thêm một bình luận trên blog của anh ấy, vì tôi không thể hiểu ý anh ấy từ những trích dẫn này.
oligofren

@oligofren Đó thực sự là một bí ẩn tuyệt vời :) ...
Mik378

Câu trả lời:


6

Tác giả của bài đăng đó đang thúc đẩy việc sử dụng Giao diện qua việc sử dụng các lớp thành viên.

It turns out that my MusicCentre object only uses the starting and stopping methods on the CdPlayer, the rest are used by some other part of the system. I'm over-specifying my MediaCentre by requiring it to talk to a CdPlayer, what it actually needs is a ScheduledDevice.

Mối quan hệ mà anh ấy lo lắng về việc khám phá lại sau này là thực tế là lớp MediaCentre không cần tất cả các đối tượng CdPlayer. Yêu cầu của ông là bằng cách sử dụng Giao diện (có lẽ chỉ giới hạn ở việc bắt đầu | dừng) mà dễ hiểu hơn về sự tương tác thực sự là gì.

"ở nơi khác" đơn giản có nghĩa là các đối tượng khác có thể có các mối quan hệ hạn chế tương tự và không yêu cầu đối tượng thành viên đầy đủ - một tập hợp con của chức năng được bao bọc thông qua Giao diện là đủ.

Khiếu nại bắt đầu có ý nghĩa hơn khi bạn khám phá tất cả các chức năng tiềm năng:

  • khởi đầu
  • dừng lại
  • tạm ngừng
  • ghi lại
  • thứ tự chơi ngẫu nhiên
  • bài hát mẫu, bắt đầu bài hát
  • bài hát mẫu, mẫu ngẫu nhiên của bài hát
  • cung cấp thông tin truyền thông
  • ...

Bây giờ tuyên bố của ông về "Tôi chỉ cần bắt đầu và dừng lại" có ý nghĩa hơn. Việc sử dụng đối tượng thành viên cụ thể thay vì Giao diện làm cho các nhà phát triển trong tương lai không rõ ràng về những gì thực sự cần thiết. Chạy thử nghiệm đơn vị từ MediaCentre trên tất cả các chức năng khác trong CdPlayer là một sự lãng phí nỗ lực thử nghiệm vì chúng thuộc về trạng thái "không quan tâm". Nếu Recordchức năng này không hoạt động trong trường hợp này, chúng tôi thực sự không quan tâm vì nó không bắt buộc. Nhưng một người duy trì trong tương lai sẽ không nhất thiết phải biết rằng dựa trên mã, như được viết.

Cuối cùng, tiền đề của tác giả là chỉ sử dụng những gì cần thiết và làm rõ cho những người bảo trì trong tương lai những gì được yêu cầu trước đó. Mục tiêu là để giảm thiểu việc làm lại / tái phân tích mô-đun mã trong quá trình bảo trì tiếp theo.


Cảm ơn câu trả lời tuyệt vời này. Tuy nhiên, bạn nói: "Chạy thử nghiệm đơn vị trên tất cả các chức năng khác là một sự lãng phí nỗ lực thử nghiệm vì chúng thuộc về trạng thái" không quan tâm "." Có phải là không: "Tạo giả cho mỗi chức năng khác là một sự lãng phí nỗ lực thử nghiệm vì chúng thuộc về trạng thái" không quan tâm "."?
Mik378

@ Mik378 - vâng, đó chính xác là những gì tôi đang nhận được, tôi chỉ nói theo cách khác. Và tôi đã cập nhật câu trả lời của mình để làm cho điều đó rõ ràng hơn.

Nhưng tôi thấy thuật ngữ "chạy thử nghiệm đơn vị" là khó hiểu. Điều đó có nghĩa là MusicCentre sắp kiểm tra đơn vị cộng tác viên của mình ... trong khi thực tế, MOCKS cộng tác viên của mình để kiểm tra đơn vị dịch vụ OWN của mình. Nhân tiện, giờ tôi đã hiểu ý nghĩa :)
Mik378

@ Mik378 - chúng tôi đang nói điều tương tự, và có lẽ tôi đang sử dụng ít thuật ngữ chính xác hơn để làm như vậy. Xin lỗi vì sự nhầm lẫn.

4

Điều này làm cho khó khăn hơn để xem liệu dịch vụ hỗ trợ mối quan hệ này có thể có liên quan ở nơi khác hay không và tôi sẽ phải làm lại phân tích lần sau khi tôi làm việc với lớp.

Sau khi suy nghĩ rất nhiều về nó, tôi nhận được một cách giải thích về trích dẫn này:

"Dịch vụ" được trích dẫn tương ứng với "thực tế lập kế hoạch". Điều này có thể được thể hiện bằng một giao diện có tên và "tập trung vào một vai trò" có tên là "Lịch trình" hoặc được thể hiện ngầm bằng cách triển khai phương thức cụ thể không phụ thuộc vào bất kỳ giao diện nào.

Trong mẫu ở trên, lập lịch biểu được thể hiện bởi toàn bộ đối tượng đầy đủ tính năng có tên CDPlayer. Do đó, nó vẫn dẫn đến mối quan hệ ngầm giữa MusicCentrevà "thực tế lập kế hoạch".

Vì vậy, nếu chúng ta bắt đầu tiêm các lớp bê tông và chế nhạo chúng vào các đối tượng cấp cao; Khi chúng tôi muốn kiểm tra những cái này, chúng tôi phải phân tích từng đối tượng "cụ thể" được tiêm để xem liệu nó có đưa ra một mối quan hệ cụ thể mà chúng tôi PHẢI MOCK bởi vì chúng là HIDDEN (ẩn). Ngược lại, mã hóa LUÔN LUÔN trên giao diện cho phép nhà phát triển tìm ra trực tiếp loại mối quan hệ nào sẽ được phục vụ bởi đối tượng cấp cao và do đó phát hiện các tính năng phải được chế giễu để cô lập thử nghiệm đơn vị.


Tôi nghĩ rằng bạn đã có nó ngay bây giờ. Thật không may, tôi đã không nhận được một thông báo về bình luận của bạn.
Steve Freeman

3

Dịch vụ tôi muốn nói ở đây là CDPlayer.scheduleToStartAt (). Đó là những gì MediaCentre gọi - cộng tác viên cần có để hoạt động. MediaCentre là đối tượng được thử nghiệm.

Ý tưởng là nếu tôi chỉ rõ ràng những gì MediaCentre phụ thuộc, không phải là một lớp triển khai, tôi có thể đặt tên cho vai trò phụ thuộc đó và nói về nó. Tất cả những gì MediaCentre cần biết là nó nói chuyện với lên lịch. Khi phần còn lại của hệ thống thay đổi, tôi sẽ không cần thay đổi MediaCentre trừ khi các tính năng của nó thay đổi.

cái đó có giúp ích không?


(tác giả của bài viết tuyệt vời này) với lớp ". Những loại phân tích? Thực tế phát hiện phương thức nào của đối tượng được cho là thực hiện mối quan hệ vì phương thức này được ẩn rõ ràng?
Mik378
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.