Tôi có nên tránh các phương pháp riêng tư nếu tôi thực hiện TDD?


100

Tôi mới học TDD. Theo hiểu biết của tôi, các phương thức riêng tư là không thể kiểm chứng và không nên lo lắng vì API công khai sẽ cung cấp đủ thông tin để xác minh tính toàn vẹn của đối tượng.

Tôi đã hiểu OOP một thời gian. Theo hiểu biết của tôi, các phương thức riêng tư làm cho các đối tượng được gói gọn hơn, do đó có nhiều khả năng chống lại sự thay đổi và sai sót hơn. Vì vậy, chúng nên được sử dụng theo mặc định và chỉ những phương thức quan trọng đối với máy khách mới được công khai.

Chà, tôi có thể tạo ra một đối tượng chỉ có phương thức riêng tư và tương tác với các đối tượng khác bằng cách lắng nghe các sự kiện của họ. Điều này sẽ được gói gọn, nhưng hoàn toàn không thể kiểm chứng.

Ngoài ra, nó được coi là thực hành xấu để thêm các phương pháp cho mục đích thử nghiệm.

Điều này có nghĩa là TDD có mâu thuẫn với việc đóng gói? Sự cân bằng thích hợp là gì? Bây giờ tôi có xu hướng công khai hầu hết hoặc tất cả các phương pháp của mình ...


9
Thực tiễn xấu và thực tế trong ngành công nghiệp phần mềm là những động vật khác nhau. Một tình huống lý tưởng thường không phải là một thực tế bị bóp méo trong thế giới kinh doanh. Làm những gì có ý nghĩa và gắn bó với nó trong suốt ứng dụng. Tôi thà có một thực hành tồi tại chỗ hơn là hương vị của tháng trải đều trên ứng dụng.
Aaron McIver

10
"Phương pháp riêng tư là không thể kiểm chứng"? Ngôn ngữ nào? Trong một số ngôn ngữ, nó bất tiện. Trong các ngôn ngữ khác, nó hoàn toàn đơn giản. Ngoài ra, bạn đang nói rằng nguyên tắc thiết kế đóng gói phải luôn được thực hiện với nhiều phương thức riêng tư? Điều đó có vẻ hơi cực đoan. Một số ngôn ngữ không có phương thức riêng tư, tuy nhiên, dường như vẫn có các thiết kế được gói gọn.
S.Lott

"Theo hiểu biết của tôi, các phương thức riêng tư làm cho các đối tượng được đóng gói nhiều hơn, do đó có khả năng chống thay đổi và lỗi cao hơn. Do đó, chúng nên được sử dụng theo mặc định và chỉ những phương thức quan trọng đối với khách hàng mới được công khai." Điều này đối với tôi giống như quan điểm phản biện về những gì TDD đang cố gắng đạt được. TDD là phương pháp phát triển dẫn bạn tạo ra thiết kế đơn giản, khả thi và dễ thay đổi. Nhìn "từ riêng tư" và "chỉ công khai ..." được quay lại hoàn toàn. Quên có một thứ như một phương pháp riêng để nắm lấy TDD. Sau đó, làm chúng khi cần thiết; như một phần của tái cấu trúc.
Herby


Vì vậy, @gnat bạn nghĩ rằng điều này nên được đóng lại như là một bản sao của câu hỏi phát sinh từ câu trả lời của tôi cho câu hỏi này? * 8 ')
Đánh dấu gian hàng

Câu trả lời:


50

Thích thử nghiệm giao diện hơn thử nghiệm trên thực hiện.

Theo hiểu biết của tôi thì phương pháp riêng tư là không thể đo lường được

Điều này phụ thuộc vào môi trường phát triển của bạn, xem bên dưới.

[phương thức riêng tư] không nên lo lắng vì API công khai sẽ cung cấp đủ thông tin để xác minh tính toàn vẹn của đối tượng.

Đúng vậy, TDD tập trung vào kiểm tra giao diện.

Các phương thức riêng là một chi tiết triển khai có thể thay đổi trong bất kỳ chu kỳ tái tạo yếu tố nào. Có thể tính lại yếu tố mà không thay đổi giao diện hoặc hành vi hộp đen . Trên thực tế, đó là một phần lợi ích của TDD, việc bạn có thể tạo sự tự tin khi thay đổi nội bộ thành một lớp sẽ không ảnh hưởng đến người dùng của lớp đó.

Chà, tôi có thể tạo ra một đối tượng chỉ có phương thức riêng tư và tương tác với các đối tượng khác bằng cách lắng nghe các sự kiện của họ. Điều này sẽ được gói gọn, nhưng hoàn toàn không thể kiểm chứng.

Thậm chí nếu lớp không có phương pháp nào, đó là xử lý sự kiện là nó public interface , và nó chống lại rằng giao diện nào mà bạn có thể kiểm tra.

Vì các sự kiện là giao diện nên nó là các sự kiện mà bạn sẽ cần tạo để kiểm tra đối tượng đó.

Nhìn vào việc sử dụng các đối tượng giả làm keo cho hệ thống thử nghiệm của bạn. Có thể tạo một đối tượng giả đơn giản tạo ra một sự kiện và chọn ra sự thay đổi trạng thái kết quả (có thể bởi một đối tượng giả khác của người nhận).

Ngoài ra, nó được coi là thực hành xấu để thêm các phương pháp cho mục đích thử nghiệm.

Tuyệt đối, bạn nên rất cảnh giác khi phơi bày trạng thái nội bộ.

Điều này có nghĩa là TDD có mâu thuẫn với việc đóng gói? Sự cân bằng thích hợp là gì?

Tuyệt đối không.

TDD không nên thay đổi việc triển khai các lớp của bạn ngoài việc đơn giản hóa chúng (bằng cách áp dụng YAGNI từ một điểm trước đó).

Thực hành tốt nhất với TDD giống hệt với thực tiễn tốt nhất mà không có TDD, bạn chỉ cần tìm hiểu tại sao sớm hơn, bởi vì bạn đang sử dụng giao diện khi bạn đang phát triển nó.

Bây giờ tôi có xu hướng công khai hầu hết hoặc tất cả các phương pháp của mình ...

Điều này sẽ tốt hơn là ném em bé ra ngoài với nước tắm.

Bạn không cần phải công khai tất cả các phương thức để bạn có thể phát triển theo cách TDD. Xem ghi chú của tôi dưới đây để xem các phương pháp riêng tư của bạn thực sự là không thể kiểm chứng.

Một cái nhìn chi tiết hơn về thử nghiệm phương pháp riêng tư

Nếu bạn hoàn toàn phải kiểm tra đơn vị một số hành vi riêng tư của một lớp, tùy thuộc vào ngôn ngữ / môi trường, bạn có thể có ba tùy chọn:

  1. Đặt các bài kiểm tra trong lớp bạn muốn kiểm tra.
  2. Đặt các bài kiểm tra trong một tệp lớp / nguồn khác và hiển thị các phương thức riêng tư mà bạn muốn kiểm tra như các phương thức công khai.
  3. Sử dụng một môi trường thử nghiệm cho phép bạn tách riêng mã thử nghiệm và mã sản xuất, nhưng vẫn cho phép mã thử nghiệm truy cập vào các phương thức riêng của mã sản xuất.

Rõ ràng là lựa chọn thứ 3 cho đến nay là tốt nhất.

1) Đặt các bài kiểm tra trong lớp bạn muốn kiểm tra (không lý tưởng)

Lưu trữ các trường hợp thử nghiệm trong cùng một tệp lớp / nguồn như mã sản xuất được thử nghiệm là tùy chọn đơn giản nhất. Nhưng không có nhiều chỉ thị hoặc chú thích của bộ xử lý trước, bạn sẽ kết thúc với mã kiểm tra làm phồng mã sản xuất của mình một cách không cần thiết, và tùy thuộc vào cách bạn đã cấu trúc mã của mình, cuối cùng bạn có thể vô tình phơi bày việc triển khai nội bộ cho người dùng mã đó.

2) Đưa ra các phương thức riêng tư mà bạn muốn kiểm tra như các phương thức công khai (thực sự không phải là một ý tưởng hay)

Theo đề xuất, đây là cách thực hành rất kém, phá hủy đóng gói và sẽ phơi bày việc triển khai nội bộ cho người dùng mã.

3) Sử dụng môi trường thử nghiệm tốt hơn (tùy chọn tốt nhất, nếu có)

Trong thế giới Eclipse, 3. có thể đạt được bằng cách sử dụng các đoạn . Trong thế giới C #, chúng ta có thể sử dụng các lớp một phần . Các ngôn ngữ / môi trường khác thường có chức năng tương tự, bạn chỉ cần tìm nó.

Giả sử mù quáng 1. hoặc 2. là các tùy chọn duy nhất có thể dẫn đến việc phần mềm sản xuất bị đầy mã kiểm tra hoặc các giao diện lớp khó chịu có thể giặt đồ vải bẩn ở nơi công cộng. *số 8')

  • Tất cả trong tất cả - tốt hơn hết là không kiểm tra chống lại việc thực hiện riêng tư.

5
Tôi không chắc chắn tôi đồng ý với bất kỳ một trong ba lựa chọn mà bạn đề xuất. Sở thích của tôi sẽ chỉ kiểm tra giao diện công cộng như bạn đã nói trước đó, nhưng đảm bảo rằng bằng cách đó, các phương thức riêng tư được thực hiện. Một phần lợi thế của việc làm này là tìm mã chết, điều này khó có thể xảy ra nếu bạn buộc mã kiểm tra của mình phá vỡ cách sử dụng thông thường của ngôn ngữ.
Magus

Phương pháp của bạn nên làm một điều, và một bài kiểm tra không nên xem xét việc thực hiện theo bất kỳ cách nào. Phương pháp riêng là chi tiết thực hiện. Nếu chỉ kiểm tra các phương thức công cộng có nghĩa là các kiểm tra của bạn là kiểm tra tích hợp, thì bạn có vấn đề về thiết kế.
Magus

Điều gì về việc làm cho phương thức mặc định / được bảo vệ và tạo một thử nghiệm trong một dự án thử nghiệm với cùng một gói?
RichardCypher 27/2/2015

@RichardCypher Điều đó thực sự giống như 2) vì bạn đang thay đổi thông số kỹ thuật phương pháp của bạn là lý tưởng để phù hợp với sự thiếu hụt trong môi trường thử nghiệm của bạn, vì vậy chắc chắn vẫn còn thực hành kém.
Đánh dấu gian hàng ngày

75

Tất nhiên bạn có thể có các phương thức riêng tư, và tất nhiên bạn có thể kiểm tra chúng.

một số cách để chạy phương thức riêng tư, trong trường hợp đó bạn có thể kiểm tra theo cách đó hoặc không có cách nào để chạy riêng tư, trong trường hợp đó: tại sao bạn lại cố gắng kiểm tra nó, chỉ là xóa cái thứ chết tiệt đó đi

Trong ví dụ của bạn:

Chà, tôi có thể tạo ra một đối tượng chỉ có phương thức riêng tư và tương tác với các đối tượng khác bằng cách lắng nghe các sự kiện của họ. Điều này sẽ được gói gọn, nhưng hoàn toàn không thể kiểm chứng.

Tại sao điều đó là không thể kiểm chứng? Nếu phương thức được gọi trong phản ứng với một sự kiện, chỉ cần có thử nghiệm cung cấp cho đối tượng một sự kiện thích hợp.

Đó không phải là không có phương pháp riêng tư, mà là về việc không phá vỡ đóng gói. Bạn có thể có các phương thức riêng tư nhưng bạn nên kiểm tra chúng thông qua API công khai. Nếu API công khai dựa trên các sự kiện, thì hãy sử dụng các sự kiện.

Đối với trường hợp phổ biến hơn của các phương thức trợ giúp riêng, chúng có thể được kiểm tra thông qua các phương thức công khai gọi chúng. Cụ thể, vì bạn chỉ được phép viết mã để vượt qua bài kiểm tra thất bại và các bài kiểm tra của bạn đang kiểm tra API công khai, tất cả mã mới bạn viết thường sẽ được công khai. Các phương thức riêng tư chỉ xuất hiện do kết quả của Tái cấu trúc phương thức trích xuất , khi chúng được rút ra khỏi một phương thức công khai đã tồn tại. Nhưng trong trường hợp đó, thử nghiệm ban đầu kiểm tra phương thức công khai vẫn bao gồm cả phương thức riêng tư, vì phương thức công khai gọi phương thức riêng.

Vì vậy, thông thường các phương thức riêng tư chỉ xuất hiện khi chúng được trích xuất từ ​​các phương thức công khai đã được thử nghiệm và do đó cũng đã được thử nghiệm.


3
Kiểm tra thông qua các phương pháp công cộng hoạt động tốt 99% thời gian. Thách thức là 1% thời gian khi phương thức công khai duy nhất của bạn có hàng trăm hoặc hàng nghìn dòng mã phức tạp đằng sau nó và tất cả các trạng thái trung gian đều được triển khai cụ thể. Một khi nó đủ phức tạp để cố gắng đánh tất cả các trường hợp cạnh từ phương pháp công khai trở nên đau đớn nhất. Cách khác, kiểm tra các trường hợp cạnh bằng cách phá vỡ đóng gói và phơi bày nhiều phương thức là riêng tư hoặc bằng cách sử dụng một phép thử để gọi các phương thức riêng trực tiếp dẫn đến các trường hợp kiểm tra dễ vỡ ngoài việc xấu.
Dan Neely

24
Phương pháp riêng lớn, phức tạp là một mùi mã. Một triển khai phức tạp đến mức không thể phân tách hữu ích thành các bộ phận cấu thành (với giao diện công cộng) là một vấn đề trong khả năng kiểm tra cho thấy các vấn đề về thiết kế và kiến ​​trúc tiềm năng. 1% các trường hợp mã riêng là rất lớn thường sẽ được hưởng lợi từ việc làm lại để phân hủy và phơi bày.
S.Lott

13
@Dan Mã đơn giản như thế là không thể kiểm chứng bất kể - và một phần của việc viết bài kiểm tra đơn vị đang chỉ ra điều này. Loại bỏ các trạng thái, phá vỡ các lớp, áp dụng tất cả các phép tái cấu trúc điển hình và sau đó viết các bài kiểm tra đơn vị. Ngoài ra với TDD, làm thế nào bạn thậm chí đạt được điểm đó? Đây là một trong những lợi thế của TDD, việc viết mã kiểm tra trở nên tự động.
Bill K

Ít nhất internalcác phương thức hoặc phương thức công khai trong internalcác lớp nên được kiểm tra trực tiếp khá thường xuyên. May mắn thay .net hỗ trợ InternalsVisibleToAttribute, nhưng không có nó, thử nghiệm các phương pháp đó sẽ là PITA.
CodeInChaos

25

Khi bạn tạo một lớp mới trong mã của mình, bạn thực hiện nó để trả lời một số yêu cầu. Các yêu cầu nói những gì mã phải làm, không phải làm thế nào . Điều này giúp dễ hiểu tại sao hầu hết các thử nghiệm xảy ra ở cấp phương thức công khai.

Thông qua các thử nghiệm, chúng tôi xác minh rằng mã thực hiện những gì nó dự kiến ​​sẽ làm , đưa ra các ngoại lệ phù hợp khi được mong đợi, v.v. Chúng tôi không thực sự quan tâm đến cách mã được nhà phát triển triển khai. Mặc dù chúng tôi không quan tâm đến việc triển khai, tức là cách mã thực hiện những gì nó làm, nhưng thật hợp lý khi tránh thử nghiệm các phương thức riêng tư.

Đối với các lớp kiểm tra không có bất kỳ phương thức công khai nào và chỉ tương tác với thế giới bên ngoài thông qua các sự kiện, bạn cũng có thể kiểm tra điều này bằng cách gửi, qua các bài kiểm tra, các sự kiện và lắng nghe phản hồi. Ví dụ: nếu một lớp phải lưu tệp nhật ký mỗi lần nhận sự kiện, kiểm tra đơn vị sẽ gửi sự kiện và xác minh rằng tệp nhật ký được viết.

Cuối cùng nhưng không kém phần quan trọng, trong một số trường hợp, việc kiểm tra các phương thức riêng tư là hoàn toàn hợp lệ. Đó là lý do tại sao trong .NET, bạn có thể kiểm tra không chỉ các lớp công khai, mà cả các lớp riêng, ngay cả khi giải pháp không đơn giản như đối với các phương thức công khai.


4
+1 Một tính năng quan trọng của TDD là nó buộc bạn phải kiểm tra rằng YÊU CẦU đã được thực hiện, thay vì kiểm tra PHƯƠNG PHÁP làm những gì họ nghĩ bạn làm. Vì vậy, câu hỏi "Tôi có thể kiểm tra một phương thức riêng tư" hơi trái ngược với tinh thần của TDD - thay vào đó, câu hỏi có thể là "Tôi có thể kiểm tra một yêu cầu có triển khai bao gồm các phương thức riêng tư không". Và câu trả lời cho câu hỏi này rõ ràng là có.
Dawood ibn Kareem

6

Theo hiểu biết của tôi thì phương pháp riêng tư là không thể đo lường được

Tôi không đồng ý với tuyên bố đó, hoặc tôi sẽ nói rằng bạn không thử trực tiếp các phương pháp riêng tư . Một phương thức công khai có thể gọi các phương thức riêng tư khác nhau. Có lẽ tác giả muốn có các phương thức "nhỏ" và trích xuất một số mã thành một phương thức riêng được đặt tên khéo léo.

Bất kể phương thức công khai được viết như thế nào, mã kiểm tra của bạn sẽ bao gồm tất cả các đường dẫn. Nếu bạn phát hiện ra sau các thử nghiệm của mình rằng một trong các câu lệnh nhánh (if / switch) trong một phương thức riêng tư chưa bao giờ được đề cập trong các thử nghiệm của bạn, thì bạn có vấn đề. Hoặc bạn đã bỏ lỡ một trường hợp và việc thực hiện là đúng HOẶC việc thực hiện là sai và thực tế đó không bao giờ tồn tại.

Đó là lý do tại sao tôi sử dụng Cobertura và NCover rất nhiều, để đảm bảo rằng thử nghiệm phương pháp công khai của tôi cũng bao gồm các phương thức riêng tư. Hãy thoải mái viết các đối tượng OO tốt bằng các phương thức riêng tư và đừng để TDD / Kiểm tra theo cách của bạn trong vấn đề như vậy.


5

Ví dụ của bạn vẫn hoàn toàn có thể kiểm tra được miễn là bạn sử dụng Dependency Injection để cung cấp các trường hợp mà CUT của bạn tương tác. Sau đó, bạn có thể sử dụng một bản giả, tạo các sự kiện quan tâm và sau đó quan sát xem CUT có thực hiện các hành động chính xác trên các phụ thuộc của nó hay không.

Mặt khác, nếu bạn có ngôn ngữ với sự hỗ trợ sự kiện tốt, bạn có thể đi một con đường hơi khác. Tôi không thích khi các đối tượng tự đăng ký các sự kiện, thay vào đó có nhà máy tạo ra các đối tượng nối các sự kiện với các phương thức công khai của đối tượng. Việc kiểm tra dễ dàng hơn và làm cho nó có thể nhìn thấy bên ngoài những loại sự kiện mà CUT cần được kiểm tra.


Đó là một ý tưởng tuyệt vời-- "... có nhà máy tạo ra các sự kiện kết nối các sự kiện với các phương thức công khai của đối tượng. Việc kiểm tra dễ dàng hơn và làm cho nó có thể nhìn thấy bên ngoài những loại sự kiện mà CUT cần được kiểm tra. "
pup

5

Bạn không cần phải từ bỏ bằng các phương pháp riêng tư. Hoàn toàn hợp lý khi sử dụng chúng, nhưng từ góc độ thử nghiệm, khó kiểm tra trực tiếp hơn mà không phá vỡ đóng gói hoặc thêm mã cụ thể kiểm tra vào các lớp của bạn. Mẹo nhỏ là giảm thiểu những thứ mà bạn biết sẽ khiến ruột của bạn bị vặn vẹo vì bạn cảm thấy như mình đã làm bẩn mã của mình.

Đây là những điều mà tôi ghi nhớ để cố gắng và đạt được sự cân bằng khả thi.

  1. Giảm thiểu số lượng các phương thức và thuộc tính riêng tư mà bạn sử dụng. Hầu hết những thứ bạn cần cho lớp học của mình có xu hướng cần được tiếp xúc công khai dù sao đi nữa, vì vậy hãy suy nghĩ xem bạn có thực sự cần phải làm cho phương thức thông minh đó thành riêng tư hay không.
  2. Giảm thiểu việc sửa đổi mã trong các phương thức riêng tư của bạn - dù sao bạn cũng thực sự nên làm điều này - và kiểm tra gián tiếp nơi bạn có thể thông qua hành vi của các phương thức khác. Bạn không bao giờ mong đợi có được phạm vi kiểm tra 100% và có lẽ bạn sẽ cần phải kiểm tra một vài giá trị thông qua trình gỡ lỗi. Sử dụng các phương pháp riêng để ném Ngoại lệ có thể dễ dàng được kiểm tra gián tiếp. Các thuộc tính riêng tư có thể cần phải được kiểm tra bằng tay hoặc thông qua một phương pháp khác.
  3. Nếu kiểm tra gián tiếp hoặc thủ công không phù hợp với bạn, hãy thêm một sự kiện được bảo vệ và truy cập qua Giao diện để hiển thị một số nội dung riêng tư. Điều này thực sự "bẻ cong" các quy tắc đóng gói, nhưng tránh sự cần thiết phải thực sự gửi mã thực hiện các thử nghiệm của bạn. Hạn chế là điều này có thể dẫn đến một chút mã nội bộ bổ sung để đảm bảo rằng sự kiện sẽ được kích hoạt khi cần thiết.
  4. Nếu bạn cảm thấy rằng một phương thức công khai không đủ "an toàn", hãy xem liệu có những cách bạn có thể thực hiện một số quy trình xác thực trong các phương thức của mình để hạn chế cách chúng được sử dụng. Rất có thể là trong khi bạn đang nghĩ về điều này thông qua việc nghĩ ra một cách tốt hơn để thực hiện các phương thức của mình, hoặc bạn sẽ thấy một lớp khác bắt đầu hình thành.
  5. Nếu bạn có nhiều phương thức riêng tư thực hiện "công cụ" cho các phương thức công khai của mình, có thể có một lớp mới đang chờ để được trích xuất. Bạn có thể kiểm tra điều này trực tiếp như một lớp riêng biệt, nhưng thực hiện như một hỗn hợp riêng trong lớp sử dụng nó.

Hãy suy nghĩ sau. Giữ các lớp học của bạn nhỏ và các phương thức của bạn nhỏ hơn, và sử dụng nhiều thành phần. Nghe có vẻ nhiều việc hơn, nhưng cuối cùng, bạn sẽ kết thúc với nhiều vật phẩm thử nghiệm riêng lẻ hơn, các thử nghiệm của bạn sẽ đơn giản hơn, bạn sẽ có nhiều tùy chọn hơn để sử dụng các giả đơn giản thay cho các vật thể thực, lớn và phức tạp, hy vọng là tốt mã được liên kết và lỏng lẻo, và quan trọng hơn là bạn sẽ cung cấp cho mình nhiều lựa chọn hơn. Giữ mọi thứ nhỏ có xu hướng giúp bạn tiết kiệm thời gian cuối cùng, bởi vì bạn giảm số lượng những thứ bạn cần kiểm tra riêng lẻ trên mỗi lớp và bạn có xu hướng giảm spaghetti mã đôi khi có thể xảy ra khi một lớp lớn và có nhiều hành vi mã phụ thuộc lẫn nhau trong nội bộ.


4

Chà, tôi có thể tạo ra một đối tượng chỉ có phương thức riêng tư và tương tác với các đối tượng khác bằng cách lắng nghe các sự kiện của họ. Điều này sẽ được gói gọn, nhưng hoàn toàn không thể kiểm chứng.

Làm thế nào để đối tượng này phản ứng với những sự kiện đó? Có lẽ, nó phải gọi các phương thức trên các đối tượng khác. Bạn có thể kiểm tra nó bằng cách kiểm tra xem các phương thức đó có được gọi không. Có nó gọi một đối tượng giả và sau đó bạn có thể dễ dàng khẳng định rằng nó làm những gì bạn mong đợi.

Vấn đề là chúng tôi chỉ muốn kiểm tra sự tương tác của đối tượng với các đối tượng khác. Chúng tôi không quan tâm những gì đang xảy ra bên trong một đối tượng. Vì vậy, không, bạn không nên có bất kỳ phương pháp công khai nào trước đó.


4

Tôi đã đấu tranh với vấn đề tương tự là tốt. Thực sự, cách để khắc phục điều này là: Làm thế nào bạn mong đợi phần còn lại của chương trình của bạn sẽ giao tiếp với lớp đó? Kiểm tra lớp học của bạn cho phù hợp. Điều này sẽ buộc bạn phải thiết kế lớp của mình dựa trên cách phần còn lại của chương trình giao tiếp với nó và trên thực tế, sẽ khuyến khích đóng gói và thiết kế tốt cho lớp của bạn.


3

Thay vì sử dụng công cụ sửa đổi mặc định. Sau đó, bạn có thể kiểm tra các phương thức đó một cách riêng lẻ, không chỉ kết hợp với các phương thức công khai. Điều này đòi hỏi các bài kiểm tra của bạn có cấu trúc gói giống như mã chính của bạn.


... giả sử đây là Java.
Dawood ibn Kareem

hoặc internaltrong .net.
CodeInChaos

2

Một vài phương pháp riêng tư thường không phải là một vấn đề. Bạn chỉ cần kiểm tra chúng thông qua API công khai như thể mã được nhập vào các phương thức công khai của bạn. Sự dư thừa của các phương pháp riêng tư có thể là một dấu hiệu của sự gắn kết kém. Lớp học của bạn nên có một trách nhiệm gắn kết và thường mọi người tạo ra các phương thức riêng tư để mang lại vẻ ngoài của sự gắn kết ở nơi không thực sự tồn tại.

Ví dụ: bạn có thể có một trình xử lý sự kiện thực hiện nhiều cuộc gọi cơ sở dữ liệu để đáp ứng với các sự kiện đó. Vì rõ ràng là thực tế tồi để khởi tạo một trình xử lý sự kiện để thực hiện các cuộc gọi cơ sở dữ liệu, nên cám dỗ là thực hiện tất cả các cuộc gọi liên quan đến cơ sở dữ liệu, khi chúng thực sự được rút ra thành một lớp riêng.


2

Điều này có nghĩa là TDD có mâu thuẫn với việc đóng gói? Sự cân bằng thích hợp là gì? Bây giờ tôi có xu hướng công khai hầu hết hoặc tất cả các phương pháp của mình.

TDD không mâu thuẫn với đóng gói. Lấy ví dụ đơn giản nhất về phương thức hoặc thuộc tính getter, tùy thuộc vào ngôn ngữ bạn chọn. Hãy nói rằng tôi có một đối tượng Khách hàng và tôi muốn nó có trường Id. Bài kiểm tra đầu tiên tôi sẽ viết là bài kiểm tra có nội dung như "customer_id_initializes_to_zero". Tôi xác định getter để ném một ngoại lệ không được thực hiện và xem thử nghiệm thất bại. Sau đó, điều đơn giản nhất tôi có thể làm để vượt qua bài kiểm tra đó là getter return zero.

Từ đó, tôi đi vào các thử nghiệm khác, có lẽ là các thử nghiệm liên quan đến ID khách hàng là một lĩnh vực chức năng thực tế. Tại một số điểm, tôi có thể phải tạo một trường riêng mà lớp khách hàng sử dụng để theo dõi những gì sẽ được trả về bởi getter. Làm thế nào chính xác để tôi theo dõi điều này? Có phải là một int sao lưu đơn giản? Tôi có theo dõi một chuỗi và sau đó chuyển đổi nó thành int không? Tôi có theo dõi 20 ints và trung bình chúng không? Thế giới bên ngoài không quan tâm - và các bài kiểm tra TDD của bạn không quan tâm. Đó là một chi tiết gói gọn .

Tôi nghĩ rằng điều này không phải lúc nào cũng rõ ràng ngay khi bắt đầu TDD - bạn không kiểm tra phương thức nào thực hiện trong nội bộ - bạn đang kiểm tra các mối quan tâm ít chi tiết hơn của lớp. Vì vậy, bạn không muốn thử nghiệm phương thức đó để DoSomethingToFoo()khởi tạo một Bar, gọi một phương thức trên nó, thêm hai vào một trong các thuộc tính của nó, v.v. Bạn đang kiểm tra rằng sau khi bạn thay đổi trạng thái của đối tượng, một số trình truy cập trạng thái đã thay đổi (hay không). Đó là mô hình chung của các bài kiểm tra của bạn: "khi tôi làm X cho lớp mình đang kiểm tra, sau đó tôi có thể quan sát Y". Làm thế nào nó đến với Y không phải là vấn đề đáng lo ngại của các bài kiểm tra, và đây là điều được gói gọn và đây là lý do tại sao TDD không mâu thuẫn với việc đóng gói.


2

Tránh sử dụng? Số
Tránh bắt đầu với ? Đúng.

Tôi nhận thấy bạn đã không hỏi về việc liệu các lớp trừu tượng với TDD có ổn không; nếu bạn hiểu làm thế nào các lớp trừu tượng xuất hiện trong TDD, thì nguyên tắc tương tự cũng áp dụng cho các phương thức riêng tư.

Bạn không thể trực tiếp kiểm tra các phương thức trong các lớp trừu tượng giống như bạn không thể trực tiếp kiểm tra các phương thức riêng tư, nhưng đó là lý do tại sao bạn không bắt đầu với các lớp trừu tượng và phương thức riêng tư; bạn bắt đầu với các lớp cụ thể và API công khai, sau đó bạn cấu trúc lại chức năng chung khi bạn đi.

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.