2008-09-17 29 views
24

Tôi có cảm giác lẫn lộn về TDD. Trong khi tôi tin vào thử nghiệm, tôi có một vấn đề với ý tưởng thử nghiệm thúc đẩy nỗ lực phát triển của tôi.Phát triển theo hướng thử nghiệm có tập trung vào thiết kế không?

Khi bạn mã hóa để đáp ứng một số thử nghiệm được viết cho giao diện cho các yêu cầu bạn có ngay bây giờ, bạn có thể chuyển trọng tâm của mình từ xây dựng mã có thể duy trì, từ thiết kế rõ ràng và từ kiến ​​trúc âm thanh.

Tôi gặp vấn đề với việc lái xe không phải với thử nghiệm. Có suy nghĩ gì không?

Trả lời

1

Luôn là số dư:
- quá nhiều TDD và bạn kết thúc bằng mã hoạt động nhưng đó là một nỗi đau cần phải thực hiện.
- quá nhiều 'mã có thể duy trì, thiết kế rõ ràng và kiến ​​trúc âm thanh' và bạn kết thúc với Architecture Astronauts đã tự nói lên sự tê liệt mã hóa

Kiểm duyệt trong tất cả mọi thứ.

43

No.

Nếu được thực hiện đúng, Kiểm tra phát triển là công cụ thiết kế của bạn.

Tôi hy vọng bạn tha thứ cho tôi vì liên kết đến my own blog entry, wherein I discuss the pitfalls of Test Driven Development that went wrong đơn giản chỉ vì các nhà phát triển đã xử lý các thử nghiệm của họ như, chỉ đơn thuần là kiểm tra.

Trong một dự án trước đó, các nhà phát triển sử dụng một mô hình singleton hại cao mà được thực thi phụ thuộc trong suốt dự án, mà chỉ phá vỡ toàn bộ điều khi yêu cầu đã được thay đổi:

TDD được coi là một nhiệm vụ, khi nó nên được coi là phương pháp . [...]

Đã xảy ra lỗi khi nhận dạng rằng TDD không phải về thử nghiệm, đó là về thiết kế. Các trường hợp tràn lan của lạm dụng singleton trong các bài kiểm tra đơn vị thực hiện điều này rõ ràng: thay vì kiểm tra nhà văn nghĩ rằng "WTF là những singleton = giá trị; báo cáo thực hiện trong các bài kiểm tra của tôi? ”, các nhà văn kiểm tra chỉ tuyên truyền các singleton vào các bài kiểm tra . 330 lần.

Hậu quả không may là kiểm tra xây dựng được thi hành bởi máy chủ là được thực hiện để vượt qua, bất kể việc gì.

Test Driven Development, thực hiện ngay, nên các nhà phát triển đánh giá cao ý thức về những cạm bẫy thiết kế như khớp nối chặt chẽ, vi phạm DRY (không lặp lại chính mình), vi phạm SRP (Single Trách nhiệm Nguyên tắc) vv

Nếu bạn viết mã vượt qua cho các bài kiểm tra của bạn để vượt qua các bài kiểm tra của bạn, bạn đã thất bại: bạn nên xử lý khó khăn để viết kiểm tra như biển chỉ dẫn mà làm cho bạn hỏi: tại sao điều này được thực hiện theo cách này? Tại sao tôi không thể kiểm tra mã này mà không phụ thuộc vào một số mã khác? Tại sao tôi không thể sử dụng lại mã này? Tại sao mã này bị phá vỡ khi được sử dụng bởi chính nó?

Bên cạnh đó nếu thiết kế của bạn là thực sự sạch, và mã của bạn thực sự duy trì tại sao nó không tầm thường để viết một bài kiểm tra cho nó?

+0

Điều gì tùy thuộc vào khuôn khổ không được thiết kế để được kiểm tra thân thiện? Tôi thích TDD và tự mình luyện tập nhưng tôi thường thấy sự cần thiết cho một sơ đồ nhanh ở góc bàn để chắc chắn rằng tôi đã nhận được tất cả các quyền – Jean

+1

Đối với mã cũ, đó là một câu chuyện hoàn toàn khác nhau hoàn toàn. : D –

+1

Có một nhu cầu tiềm ẩn để có một số thiết kế cơ bản ... bạn cần điều đó để có thể viết các bài kiểm tra đầu tiên của bạn. Mối quan tâm không phải là chống lại thiết kế lên phía trước, đó là về thiết kế BIG lên phía trước trước khi thiết kế tốt nhất cho các tính năng/nhiệm vụ cụ thể được đến. –

2

Có ba bước để hoàn thành phần mềm:

  1. Làm cho nó làm việc
  2. Làm cho nó đúng
  3. Làm cho nó nhanh

Các xét nghiệm giúp bạn có đượC# 1. Mã của bạn không được thực hiện chỉ vì các thử nghiệm đã trôi qua. Tốt hơn là bạn có một số khái niệm về cấu trúc dự án (Các tiện ích, các đối tượng thường được truy cập, các lớp, khung công tác) trước khi bạn bắt đầu viết các bài kiểm tra/mã của mình. Sau khi bạn đã viết mã của bạn để làm cho các bài kiểm tra vượt qua, bạn cần phải đánh giá lại nó để xem phần nào có thể được tái cấu trúc ra các khía cạnh khác nhau của ứng dụng của bạn. Yuo có thể làm điều này một cách tự tin, bởi vì bạn biết rằng miễn là các bài kiểm tra của bạn vẫn đang trôi qua, mã của bạn vẫn hoạt động (hoặc ít nhất là đáp ứng các yêu cầu).

Khi bắt đầu dự án, hãy suy nghĩ về cấu trúc. Khi dự án tiếp tục đánh giá và đánh giá lại mã của bạn để giữ thiết kế tại chỗ hoặc thay đổi thiết kế nếu nó ngừng hoạt động. Tất cả các mục này phải được tính đến khi bạn ước tính, hoặc bạn sẽ kết thúc với mã spagetti, TDD hay không.

+0

Chỉ cần một nit: Công thức ban đầu của bộ ba này tôi tin rằng nợ Kent Beck, và nó hơi khác một chút. Bước một chỉ đơn giản là "làm cho nó chạy" mà là khác nhau từ "làm cho nó hoạt động." Tôi có thể đoán đó là ý định của bạn. – Cope

3

Tôi hoàn toàn đồng ý với pjz. Không có cách nào đúng để thiết kế phần mềm. Nếu bạn sử dụng TDD đến mức cực đoan, mà không có bất kỳ sự suy đoán nào ngoại trừ bài kiểm tra đơn vị tiếp theo, bạn có thể làm cho mọi thứ trở nên khó khăn hơn. Ditto cho người đưa ra một dự án phần mềm lớn bằng cách chi tiêu hàng tháng trên sơ đồ và tài liệu, nhưng không có mã.

Trung bình. Nếu cảm thấy sự thôi thúc để vẽ lên một sơ đồ nhanh chóng giúp bạn hình dung cấu trúc mã của bạn, hãy thực hiện nó. Nếu bạn cần hai trang, có thể đã đến lúc bắt đầu viết một số mã. Và nếu bạn muốn làm điều đó trước khi bạn viết các bài kiểm tra của bạn, vì vậy những gì. Mục tiêu là làm việc, phần mềm chất lượng, không phù hợp tuyệt đối với bất kỳ học thuyết phát triển phần mềm cụ thể nào. Làm những gì phù hợp với bạn và nhóm của bạn. Tìm các khu vực có thể thực hiện các cải tiến. Lặp lại.

+0

Không thể tranh luận với thực tế là mục tiêu đang làm việc, phần mềm chất lượng. –

1

Tôi tương đối mới đối với TDD và thử nghiệm đơn vị, nhưng trong hai dự án mà tôi đã sử dụng, tôi đã tìm thấy nó là thiết kế aide thay vì thiết kế thay thế. Các tội phạm để kiểm tra và xác minh các thành phần/tiểu thành phần độc lập đã làm cho nó dễ dàng hơn cho tôi để thực hiện thay đổi nhanh chóng và thử những ý tưởng thiết kế mới.

Sự khác biệt mà tôi đã trải qua với TDD là độ tin cậy. Quá trình làm việc ra thành phần giao tiếp trên các cấp độ nhỏ hơn của thành phần lúc bắt đầu của quá trình thiết kế, hơn là sau đó, là tôi đã có các thành phần tôi có thể tin tưởng sẽ làm việc trước đó, vì vậy tôi có thể ngừng lo lắng về các phần nhỏ và thay vì làm việc trên những vấn đề khó khăn.

Và khi tôi chắc chắn cần phải quay lại và duy trì các phần nhỏ, tôi có thể dành ít hơn thời gian để làm như vậy, để tôi có thể quay lại công việc tôi muốn làm.

1

Đối với hầu hết các phần, tôi đồng ý rằng TDD cung cấp một loại công cụ thiết kế. Phần quan trọng nhất đối với tôi là cách mà nó xây dựng trong khả năng tạo ra nhiều thay đổi hơn (bạn biết đấy, khi bạn có khoảnh khắc sáng suốt trong đó bạn có thể thêm chức năng bằng cách xóa mã) với nguy cơ giảm đáng kể.

Điều đó nói rằng, một số công việc thuật toán hơn mà tôi đã ký hợp đồng gần đây đã phải chịu một chút dưới TDD mà không cần cân nhắc cẩn thận về ý tưởng thiết kế.Tuyên bố trên về tái cấu trúc an toàn hơn vẫn là một lợi ích lớn, nhưng đối với một số thuật toán TDD là (mặc dù vẫn hữu ích) không đủ để đưa bạn đến một giải pháp lý tưởng. Hãy phân loại như một ví dụ đơn giản. TDD có thể dễ dàng dẫn bạn đến một thuật toán tối ưu (N^2) (và các phép kiểm tra đi qua cho phép bạn cấu trúc lại để sắp xếp nhanh) như kiểu bong bóng. TDD là một công cụ, một công cụ rất tốt, nhưng giống như nhiều thứ cần phải được sử dụng một cách thích hợp cho bối cảnh của vấn đề đang được giải quyết.

+0

Bạn không thể chỉ cần thêm một thử nghiệm đo thời gian (trong CPU tick) cần thiết để sắp xếp N mục, so sánh nó với một khoảng thời gian dự kiến ​​(mô phỏng một vấn đề phức tạp N), và thì đấy! Bạn đang kiểm tra sự phức tạp. –

3

Tôi hoàn toàn đồng ý với bạn về chủ đề đó. Tôi nghĩ TDD thường có một số hiệu ứng rất tiêu cực trên cơ sở mã (thiết kế crappy, mã thủ tục, không đóng gói, mã sản xuất rải rác với mã kiểm tra, giao diện ở khắp mọi nơi, mã sản xuất tái cấu trúc khó bởi vì mọi thứ được kết hợp chặt chẽ với nhiều kiểm tra v.v.)

Jim Coplien đã đưa ra đàm phán về chính xác những chủ đề này trong một thời gian bây giờ là:

nghiên cứu

gần đây (Siniaalto và Abrahamsson) của TDD cho thấy rằng nó có thể không có lợi ích hơn truyền thống phát triển thử nghiệm cuối cùng và đó trong một số trường hợp đã làm hỏng mã và rằng các trường hợp này có các báo động khác (hiệu ứng từ) của chúng. Người lo lắng cho tôi nhiều nhất là nó làm hỏng cấu trúc . - Jim's blog

Ngoài ra còn có một discussion over on InfoQ giữa Robert C. Martin và James Coplien nơi họ chạm về chủ đề này.

+0

Nếu mã thoái hóa thành thủ tục, không có đóng gói, thì TDD không phải là vấn đề. Đó là OOP. Xem câu trả lời của tôi –

13

Luôn có nguy cơ lạm dụng thiết kế TDD hoặc thiết kế trả trước. Vì vậy, câu trả lời là nó phụ thuộc. Tôi thích bắt đầu với một bài kiểm tra câu chuyện/chấp nhận người dùng là cơ sở của yêu cầu mà các bài kiểm tra của tôi sẽ hỗ trợ trong quá trình sản xuất. Chỉ sau khi tôi đã thiết lập được điều đó, tôi bắt đầu viết các bài kiểm tra đơn vị chi tiết theo kiểu TDD. Nếu thiết kế duy nhất và suy nghĩ bạn làm là thông qua TDD, thì bạn có nguy cơ quá nhiều cách tiếp cận từ dưới lên, điều này có thể cung cấp cho bạn các đơn vị và lớp học tuyệt vời trong sự cô lập, nhưng khi bạn cố gắng tích hợp chúng vào câu chuyện của người dùng có thể ngạc nhiên vì đã làm tất cả sai. Để có thêm cảm hứng về điều này, hãy xem att BDD.

A great "debate" about this has been recorded giữa Robert C. Martin và James Coplien, nơi trước đây là người ủng hộ TDD và người thứ hai đã tuyên bố rằng nó phá hỏng thiết kế của hệ thống. Đây là những gì Robert nói về TDD và thiết kế:

"Hiện đã có một cảm giác trong cộng đồng Agile từ khoảng '99 rằng kiến ​​trúc là không thích hợp, chúng tôi không cần làm kiến ​​trúc, tất cả chúng ta cần phải làm là viết một lô kiểm tra và làm rất nhiều câu chuyện và làm nhanh lặp và mã sẽ lắp ráp bản thân một cách kỳ diệu, và điều này đã luôn được ngựa shit. tôi thậm chí còn nghĩ rằng hầu hết những người ủng hộ Agile gốc sẽ đồng ý rằng đó là một sự silliness."

James Coplien khẳng định rằng chỉ đơn thuần là lái xe thiết kế của bạn từ TDD có một nguy cơ rất lớn:

" Một trong những điều chúng ta thấy rất nhiều, trong rất nhiều của dự án, được rằng các dự án đi về phía nam về lần chạy nước rút thứ 3 của họ và chúng bị hỏng và ghi vì chúng không thể tiến xa hơn nữa, bởi vì chúng đã tự dồn vào chân tường về mặt kiến ​​trúc. Và bạn không thể cấu trúc lại theo cách của bạn ra khỏi điều này bởi vì refactoring có được qua lớp loại, qua phân cấp lớp, và bạn không còn có thể có bất kỳ sự bảo đảm về việc có cùng chức năng."

Ngoài ra ông đưa ra một ví dụ tuyệt vời của một tài khoản ngân hàng có lẽ sẽ trông như thế nào nếu bạn kiểm tra lái xe nó so với sử dụng kiến ​​thức trả trước của bạn để lái xe các kiến ​​trúc:

"tôi nhớ khi tôi đang nói chuyện với Kent o nce, về trong những ngày đầu tiên khi ông đề xuất TDD, và điều này là theo ý nghĩa của YAGNI và làm điều đơn giản nhất có thể có thể làm việc và ông nói: 'Ok. Hãy tạo một tài khoản ngân hàng , một tài khoản tiết kiệm. ' Tài khoản tiết kiệm là gì? Đó là số và bạn có thể thêm vào số và bạn có thể trừ số đó. Vì vậy, tài khoản tiết kiệm là gì, là một máy tính . Hãy tạo một máy tính, và chúng tôi có thể cho thấy rằng bạn có thể thêm vào số số dư và trừ khỏi số dư . Đó là điều đơn giản nhất có thể có thể hoạt động, mọi thứ khác là một sự tiến hóa của điều đó.

Nếu bạn làm một hệ thống ngân hàng thực tế, một tài khoản tiết kiệm không phải là thậm chí một đối tượng và bạn sẽ không refactor theo cách của bạn đến kiến ​​trúc ngay từ rằng một. Tài khoản tiết kiệm là gì, là một quá trình thực hiện lặp lại qua đường dẫn kiểm tra của cơ sở dữ liệu giao dịch, tiền gửi và lãi các cuộc tụ họp và các thay đổi khác của tiền. Nó không giống như tài khoản tiết kiệm là một số tiền ngồi trên một giá đỡ ở một nơi nào đó, mặc dù đó là góc nhìn người dùng và bạn chỉ cần biết rằng có cấu trúc tương đối phức tạp này trong cơ sở của hệ thống ngân hàng để hỗ trợ người thuế và chuyên gia truyền thông và tất cả những người khác này, mà bạn không thể truy cập theo cách gia tăng . Vâng, bạn có thể, vì tất nhiên ngành ngân hàng đã đến sau 40 năm. Bạn muốn cho mình 40 năm? Đó là không nhanh nhẹn. "

Điều thú vị ở đây là cả người đề xuất TDD và đối thủ TDD đều nói rằng bạn cần thiết kế trước.

Nếu bạn có thời gian, hãy xem video. Đó là một cuộc thảo luận tuyệt vời giữa hai chuyên gia có ảnh hưởng lớn và chỉ dài 22 phút.

+0

Cảm ơn Microserf :) Tôi đã xem video. Cảm giác của tôi là như nhau. Nếu bạn đặt trọng tâm chính vào kiểm tra mã và thực hiện các kiểm tra bắt buộc thì bằng cách nào đó chúng sẽ bắt đầu thay thế cho thiết kế và kiến ​​trúc tốt. – Daniel

+1

Cách nào sai để tiếp cận TDD - tập trung vào kiểm thử mỗi lần là thực hành kém phát triển theo hướng thử nghiệm. –

3

Cách của tôi để suy nghĩ về nó là, viết những gì bạn muốn mã của bạn trông giống như trước tiên. Một khi bạn có một mẫu mã đích của bạn (mà bây giờ không làm gì cả) xem bạn có thể đặt giàn giáo thử nghiệm lên nó hay không. Nếu bạn không thể làm điều đó, hãy tìm ra lý do tại sao bạn không thể. Phần lớn thời gian đó là vì bạn đã thực hiện một quyết định thiết kế nghèo (99%), tuy nhiên nếu đó không phải là trường hợp (1%) hãy thử như sau:

  • xác định các yêu cầu điên được rằng bạn cần phải tuân thủ để điều đó sẽ không cho phép bạn kiểm tra mã của mình. Bạn hiểu vấn đề thiết kế lại API của mình.
  • nếu người khác đã quyết định yêu cầu này thảo luận về điều đó. Họ có thể có một lý do chính đáng cho yêu cầu và một khi bạn biết lý do của họ, bạn sẽ có thể hoàn thiện thiết kế của bạn và làm cho nó có thể kiểm chứng. Nếu không phải bây giờ bạn có thể làm lại cả hai yêu cầu và cả hai sẽ tốt hơn cho nó.

Sau khi bạn có mã đích và giàn giáo thử nghiệm. Triển khai mã. Bây giờ bạn thậm chí còn có lợi thế là biết bạn tiến bộ như thế nào khi bạn vượt qua bài kiểm tra của riêng bạn (Đó là một động lực tuyệt vời!)

Trường hợp duy nhất mà thử nghiệm có thể thừa, từ kinh nghiệm cá nhân, là khi bạn tạo mẫu thử nghiệm ban đầu bởi vì tại thời điểm đó bạn vẫn không hiểu vấn đề đủ tốt để thiết kế hoặc kiểm tra mã của bạn một cách chính xác.

0

Có nhiều ý kiến ​​không chính thức ở đây, bao gồm cả ý kiến ​​phổ biến (từ Jon Limjap) rằng kết quả xấu đến từ việc làm sai và tuyên bố dường như không được hỗ trợ nhiều hơn kinh nghiệm cá nhân. Các bằng chứng thực nghiệm ưu thế và kết quả được công bố điểm theo một hướng ngược lại từ kinh nghiệm đó.

Lý thuyết là phương pháp yêu cầu bạn viết các bài kiểm tra trước khi mã sẽ dẫn đến suy nghĩ về thiết kế ở cấp các đoạn mã riêng lẻ - tức là lập trình theo từng nhỏ. Vì các thủ tục là tất cả những gì bạn có thể kiểm tra (bạn vẫn kiểm tra một đối tượng cùng một lúc và bạn không thể kiểm tra các lớp bằng hầu hết các ngôn ngữ), trọng tâm thiết kế của bạn đi đến các phương thức riêng lẻ và cách chúng tạo. Điều đó dẫn đến, theo lý thuyết, đến một thiết kế thủ tục từ dưới lên và, đến lượt nó, để kết nối và gắn kết kém giữa các đối tượng.

Dữ liệu thực nghiệm rộng rãi chứng minh lý thuyết. Siniaalto và Abrahamsson, (Nghiên cứu điển hình so sánh về ảnh hưởng của phát triển thử nghiệm trên thiết kế chương trình và phạm vi kiểm tra), ESEM 2007, thấy rằng "Kết quả của chúng tôi cho thấy sự gắn kết có thể tồi tệ hơn (mặc dù Beck tuyên bố rằng TDD sản xuất cao Trong nghiên cứu thứ hai của chúng tôi, chúng tôi nhận thấy rằng các biện pháp phức tạp tốt hơn với TDD, nhưng các số liệu quản lý phụ thuộc rõ ràng tệ hơn. " Janzen và Saledian (Phát triển theo hướng thử nghiệm có thực sự cải thiện chất lượng thiết kế phần mềm không? Phần mềm IEEE 25 (2), March/April 2008, tr. 77 - 84) nhận thấy rằng “[T] ghép nối và tăng sự gắn kết với TDD ”.

Bài đánh giá tài liệu sẽ phát hiện ra các ấn phẩm khác làm tăng thêm các trường hợp này. Ngay cả người bạn thân yêu của tôi, Bác Bob viết: "Một trong những huyền thoại dai dẳng và dai dẳng của phát triển nhanh là kiến ​​trúc và thiết kế phía trước là xấu, bạn không bao giờ dành thời gian lên phía trước để đưa ra quyết định kiến ​​trúc.Điều đó thay vào đó bạn nên phát triển kiến ​​trúc và thiết kế của bạn từ không có gì, một trường hợp thử nghiệm tại một thời điểm. Tha thứ cho tôi, nhưng đó là ngựa Chết tiệt."('The Scatology của Agile Kiến trúc,' http://blog.objectmentor.com/articles/2009/04/25/the-scatology-of-agile-architecture)

Tuy nhiên, đó là đáng chú ý là sự thất bại lớn hơn là mọi người nghĩ đó là một kỹ thuật xét nghiệm chứ không phải là một kỹ thuật thiết kế. Osherov chỉ ra một loạt các phương pháp tiếp cận thường được tương đương với TDD.Tôi không thể chắc chắn những gì có nghĩa là bởi các áp phích ở đây.Xem: http://weblogs.asp.net/rosherove/archive/2007/10/08/the-various-meanings-of-tdd.aspx

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