TDD - Bên ngoài so với bên trong


53

Sự khác biệt giữa việc xây dựng một ứng dụng Bên ngoài so với xây dựng Inside Out bằng TDD là gì?

Đây là những cuốn sách tôi đọc về TDD và thử nghiệm đơn vị:
Phát triển dựa trên thử nghiệm: Ví dụ
Phát triển dựa trên thử nghiệm: Hướng dẫn thực tế: Hướng dẫn thực tế
Giải pháp thực tế để phát triển các khung và ứng dụng PHP chất lượng cao
Phát triển dựa trên thử nghiệm ở Microsoft. NET
xUnit Các mẫu kiểm tra: Tái cấu trúc mã kiểm tra
Nghệ thuật kiểm tra đơn vị: Với các ví dụ trong.
Phần mềm hướng đối tượng đang phát triển, được hướng dẫn bởi các bài kiểm tra ---> Điều này thực sự khó hiểu vì JAVA không phải là ngôn ngữ chính của tôi :)

Hầu hết tất cả trong số họ đã giải thích các vấn đề cơ bản về TDD và kiểm tra đơn vị nói chung, nhưng ít đề cập đến các cách khác nhau mà ứng dụng có thể được xây dựng.

Một điều tôi nhận thấy là hầu hết các cuốn sách này (nếu không phải tất cả) đều bỏ qua giai đoạn thiết kế khi viết ứng dụng. Họ tập trung nhiều hơn vào việc viết các trường hợp thử nghiệm một cách nhanh chóng và để cho thiết kế tự xuất hiện.

Tuy nhiên, tôi đã bắt gặp một đoạn trong Các mẫu thử nghiệm xUnit thảo luận về cách mọi người tiếp cận TDD. Có 2 trường ngoài đó Trongngoài Inside Out .

Đáng buồn là cuốn sách không chi tiết hơn về điểm này. Tôi muốn biết sự khác biệt chính giữa 2 trường hợp này là gì.
Khi nào tôi nên sử dụng mỗi một trong số họ?
Đối với người mới bắt đầu TDD, cái nào dễ nắm bắt hơn?
Hạn chế của từng phương pháp là gì?
Có tài liệu nào ngoài đó thảo luận về chủ đề này một cách cụ thể không?


Hai phương pháp được mô tả trên trang web Patterns XUnit Test: xunitpatterns.com/Philosophy%20Of%20Test%20Automation.html . Thật kỳ lạ khi chúng không có trong sách.
guillaume31

Câu trả lời:


45

Inside-Out và Out-In là những thuật ngữ khá hiếm, tôi thường nghe / đọc về trường Classictrường London .

  • Inside-Out (Trường học cổ điển, từ dưới lên ): bạn bắt đầu ở cấp thành phần / lớp (bên trong) và thêm các bài kiểm tra theo yêu cầu. Khi mã phát triển (do tái cấu trúc), các cộng tác viên mới, các tương tác và các thành phần khác xuất hiện. TDD hướng dẫn thiết kế hoàn toàn.

  • Inside-In (trường học London, từ trên xuống hoặc "mockist TDD" như Martin Fowler sẽ gọi nó): bạn biết về các tương tác và cộng tác viên trả trước (đặc biệt là những người ở cấp cao nhất) và bắt đầu từ đó (cấp cao nhất), chế giễu các phụ thuộc cần thiết. Với mỗi thành phần đã hoàn thành, bạn chuyển đến các cộng tác viên bị chế giễu trước đó và bắt đầu lại với TDD ở đó, tạo ra các triển khai thực tế (mặc dù đã được sử dụng nhưng không cần thiết trước khi trừu tượng hóa ). Lưu ý rằng phương pháp bên ngoài phù hợp với nguyên tắc YAGNI .

Cả hai cách tiếp cận đều là một và duy nhất ; cả hai đều có vị trí của họ tùy thuộc vào những gì bạn làm. Trong các giải pháp doanh nghiệp lớn, nơi các bộ phận của thiết kế đến từ các kiến ​​trúc sư (hoặc tồn tại trước), người ta có thể bắt đầu với phương pháp "phong cách Luân Đôn". Mặt khác, khi bạn đối mặt với một tình huống mà bạn không chắc chắn mã của mình sẽ trông như thế nào (hoặc nó sẽ phù hợp với các phần khác trong hệ thống của bạn như thế nào), có thể dễ dàng hơn để bắt đầu với một số thành phần cấp thấp và để nó phát triển khi nhiều thử nghiệm, tái cấu trúc và yêu cầu được giới thiệu.

Bất cứ điều gì bạn sử dụng, thường xuyên hơn không phải là tình huống.

Để đọc thêm, có bài đăng trên nhóm Google với cuộc thảo luận khá thú vị về cách phân biệt này (có thể có) bắt nguồn và tại sao London có thể không phải là tên thích hợp nhất.


2
Hấp dẫn. Làm thế nào bạn đạt được kết luận rằng bên ngoài trong TDD là "mockist" TDD? Tôi rất thích tư duy và thiết kế bên ngoài và do đó thử nghiệm (xem phần mềmonastring.com / 2015/01/10 / Tuy) nhưng bài báo Fowler chắc chắn đưa tôi với Fowler vào trại cổ điển. Mặc dù người nhạo báng có thể luôn sử dụng cách tiếp cận từ bên ngoài, nhưng bạn không thể quay lại và nói rằng thiết kế và thử nghiệm bên ngoài TDD nhạo báng. Bên ngoài có thể và rất nhiều được thực hành bởi TDD-ers cổ điển là tốt.
Marjan Venema

@jimmy_keen - Với bên ngoài, bạn có lúc nào thay thế các bản giả trong các bài kiểm tra cấp cao hơn bằng các triển khai thực tế được tạo sau này không? Hay bạn để chúng như những phụ thuộc bị chế giễu và sau đó thực hiện toàn bộ mã sản xuất dưới dạng thử nghiệm tích hợp?
thehowler

1
Tôi không đồng ý rằng Classic / Mockist và Inside-Out / Inside-In có liên quan. Chúng là trực giao. Bạn có thể sử dụng Inside-Out / Inside-In với một trong hai.
Daniel Kaplan

Đồng ý với Daniel. Bạn đang thích hai nguyên tắc phân loại khác nhau. Mặc dù sự phát triển Bên ngoài thường được liên kết với trường học London (mockist), nhưng không phải lúc nào cũng như vậy.
guillaume31

Tôi không nghĩ rằng đây là một mô tả chính xác của quá trình bên ngoài. Đó là về thử nghiệm từ các giao diện công cộng mà không cần ghép nối với bên trong, càng nhiều càng tốt.
mcintyre321

15

Trả lời ngắn: Như thường lệ, nó sẽ phụ thuộc vào sở thích mã hóa và cách tiếp cận nhóm của bạn.

Bên trong mã hóa là tuyệt vời bởi vì bạn luôn có một cái gì đó làm việc. Nhược điểm là nó không nhất thiết giúp bạn đến một nơi hoàn toàn khác. Nó là khó hơn để biểu đồ một khóa học theo cách này. Tương tự, viết mã bên ngoài có nhược điểm là không nhất thiết có lợi ích của sự phát triển lặp lại nhanh chóng và không nhất thiết phải nhìn thấy tất cả các cơ hội và mô hình có thể phát sinh từ sâu trong cấu trúc của mã.

Tôi đã tin rằng cả hai phong cách phát triển đều quan trọng , và trên thực tế rất hữu ích khi có sự kết hợp các phong cách trong một nhóm. Ý tưởng là từ trong ra ngoài là tuyệt vời để tạo ra các khối xây dựng, và bên ngoài trong suy nghĩ cung cấp cấu trúc và hướng của hình thức.

Một phần lý luận của tôi đến từ một trường phái tư tưởng rất phổ biến hiện đang thúc đẩy sự phát triển lặp lại, điều này thường đồng nghĩa với sự phát triển từ trong ra ngoài. Tôi tin rằng sự phát triển lặp lại là tuyệt vời khi bạn không đi quá xa. Nhưng tôi nghĩ rằng tư duy bức tranh lớn, trái ngược với một quá trình lặp đi lặp lại hoàn toàn là vô giá đối với một số loại đổi mới và để đến một nơi ít rõ ràng hơn. Quản lý đúng cách, từ trong ra ngoài và cùng nhau có thể là một sự kết hợp rất hiệu quả.


8

Bạn nên thêm Prinicples, mẫu và thực tiễn Agile trong C # vào danh sách đó. Tôi không biết lý do tại sao anh ấy đã giải quyết "trong C #" vào cuối. Các cuốn sách hoàn toàn không phải là ngôn ngữ và lý do duy nhất nó không đạt được 5 sao trên amazon là từ những người thất vọng về C # -ness của các ví dụ của anh ấy.

Tác giả, ủng hộ rằng bất cứ khi nào có thể bạn nên cố gắng viết mã bên ngoài và phụ thuộc nhiều vào thiết kế tiến hóa, và tôi đồng ý với tuyên bố của ông. Lý do của ông là khi chúng tôi thêm chức năng, thiết kế của chúng tôi sẽ luôn phát triển. Nếu chúng ta bắt đầu với các thành phần cấp thấp khi các tính năng được thêm vào, chúng ta sẽ nhận ra các thành phần đó không làm những gì chúng ta muốn chúng làm, hoặc mọi thứ cần phải được di chuyển xung quanh. Điều này có thể trở nên khá tốn kém, đặc biệt nếu mỗi khi bạn chuyển chức năng từ lớp này sang lớp khác, bạn cần thực hiện cùng một động thái trong tất cả các dự án thử nghiệm đơn vị.

Mặt khác, nếu bạn xác định ứng dụng của bạn phải làm gì ở nơi đầu tiên, bạn mã cho giao diện bên ngoài. Khi các tính năng được thêm vào và mã được kiểm tra tăng kích thước, bạn cấu trúc lại ứng dụng của mình thành nhiều lớp hơn, nhưng trong khi nỗ lực tái cấu trúc này đang diễn ra, các bài kiểm tra đơn vị ban đầu bạn đã viết vẫn hợp lệ. Vì vậy, bạn bắt đầu hoàn toàn ở bên ngoài và tiếp tục tái cấu trúc thành ngày càng nhiều lớp cấp thấp hơn, đồng thời thêm các bài kiểm tra đơn vị bổ sung cho các lớp bên trong đó, nhưng bạn hiếm khi phải di chuyển và viết lại bài kiểm tra đơn vị của mình.

Tuy nhiên, nếu bạn xác định một hệ thống con cấp thấp cụ thể mà ứng dụng của bạn sẽ cần (và có thể công ty của bạn đã có nhu cầu về hệ thống con đó trong các ứng dụng khác), thì đây sẽ là lúc bắt đầu với khối xây dựng cấp thấp xây dựng ứng dụng trên đó.


7

Như tôi thấy, khái niệm phát triển Bên ngoài thực sự lan rộng trên 2 cấp độ. Gerard Meszaros mô tả ngắn gọn chúng là " thiết kế bên ngoài" và " mã hóa bên ngoài / bên trong ".

  • Cấp độ đầu tiên là cấp độ tổ chức và quy trình. Thiết kế bên ngoài có nghĩa là trái ngược với từ trên xuống (thác nước / taylorist) và từ dưới lên. Với cách tiếp cận từ bên ngoài, chúng tôi tập trung vào viễn cảnh của người dùng cuối. Chúng tôi bắt đầu với các bài kiểm tra câu chuyện, kiểm tra ATDD hoặc BDD và đi "vào trong" suy ra các bài kiểm tra kỹ thuật và mã. Vì vậy, thiết kế bên ngoài thường là những gì bạn sẽ làm trong bối cảnh Agile. Dan North có một cuộc nói chuyện tuyệt vời về phương pháp tiếp cận BDD, từ trên xuống, từ dưới lên và từ ngoài vào trong.

  • Cấp độ thứ hai là kỹ thuật và phải làm với các lớp ứng dụng. Mã hóa bên ngoài về cơ bản có nghĩa là bắt đầu từ giao diện người dùng và đi vào lớp trung tâm (thường là lớp doanh nghiệp / miền). Nó có nghĩa là trái ngược với mã hóa từ trong ra ngoài bắt đầu từ lớp trung tâm và mã hóa các lớp bên ngoài cuối cùng.

Vì vậy, bạn có thể có thiết kế bên ngoài với mã hóa bên ngoài hoặc mã hóa từ trong ra ngoài.

Trường hợp tôi không đồng ý với Meszaros là khi anh ấy liên kết mã hóa từ trong ra ngoài với thử nghiệm tích hợp, lập luận rằng trong bối cảnh từ trong ra ngoài "chúng tôi không thực sự kiểm tra phần mềm bên ngoài để tách biệt phần mềm bên trong". Nhưng tôi tin rằng không có gì ngăn cản bạn làm như vậy. Bạn hoàn toàn có thể chọn kiểm tra các đối tượng lớp bên ngoài của mình bằng cách loại bỏ các đối tượng lớp bên trong ngay cả khi mã sản xuất cho những đối tượng đã tồn tại. Bạn chỉ cần thêm các giao diện và giả trên đầu các đối tượng cụ thể hiện có thay vì viết các giao diện, chế nhạo chúng và sau đó tạo các triển khai sau này như bạn sẽ làm với mã hóa bên ngoài.

Nói cách khác, TDD theo phong cách mockist hoặc cổ điển là IMO một mối quan tâm trực giao đối với tiền mã hóa từ trong ra ngoài. Bạn hoàn toàn có thể sử dụng một phong cách nhạo báng cùng với cách tiếp cận từ trong ra ngoài. Lý do đằng sau điều này là phong cách mockist / classicist là về sự phụ thuộc mã trong khi mã hóa từ trong ra ngoài là về các lớp ứng dụng .

Một điều quan trọng khác là sự phụ thuộc không chỉ giữa các lớp, chúng còn tồn tại giữa các đối tượng trong cùng một lớp. Chẳng hạn, bạn có thể muốn bắt đầu với một đối tượng trong lớp doanh nghiệp trung tâm của mình (cách tiếp cận từ trong ra ngoài) và sử dụng giả để cách ly đối tượng của bạn khỏi các đối tượng của lớp nghiệp vụ khác mà nó nói chuyện. Điều này xảy ra rất nhiều với IoC - sự trừu tượng mà đối tượng của bạn phụ thuộc thường được khai báo trong cùng một lớp, nhưng việc triển khai cụ thể lại ở một lớp khác.

Robert "Chú Bob" Martin đề cập ngắn gọn về mã hóa từ trong ra ngoài và làm thế nào nó không nhất thiết phải xung đột với một kiến ​​trúc tách rời trong bài " Kiến trúc sạch " của ông.

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.