2009-03-18 31 views
5

Tôi hiện đang đọc hai cuốn sách tuyệt vời "Làm việc hiệu quả với Mã kế thừa" và "Mã sạch".Tái cấu trúc và kiểm tra phát triển theo hướng

Họ đang làm cho tôi suy nghĩ về cách viết và làm việc với mã theo những cách hoàn toàn mới nhưng một chủ đề phổ biến trong số đó là phát triển theo thử nghiệm và ý tưởng che giấu mọi thứ với các bài kiểm tra và kiểm tra tại chỗ trước khi bạn thực hiện thay đổi hoặc triển khai một chức năng mới.

này đã dẫn đến hai câu hỏi:

Câu hỏi 1: Nếu tôi làm việc với mã di sản. Theo những cuốn sách tôi nên đặt thử nghiệm tại chỗ để đảm bảo tôi không phá vỡ bất cứ điều gì. Hãy xem xét rằng tôi có một phương pháp 500 dòng dài. Tôi sẽ giả sử tôi sẽ có một tập hợp các phương pháp thử nghiệm tương đương để kiểm tra phương pháp đó. Khi tôi chia chức năng này lên, tôi có tạo các thử nghiệm mới cho mỗi phương thức/lớp mới có kết quả không?

Theo "Mã sạch", bất kỳ thử nghiệm nào mất nhiều hơn 1/10 giây là thử nghiệm mất quá nhiều thời gian. Đang cố gắng thử nghiệm một phương pháp kế thừa dài dòng 500 đi vào cơ sở dữ liệu và thần biết những gì khác có thể mất nhiều thời gian hơn 1/10 giây. Mặc dù tôi hiểu rằng bạn cần phải phá vỡ các phụ thuộc mà tôi gặp phải vấn đề là việc tạo thử nghiệm ban đầu.

Câu hỏi 2: Điều gì sẽ xảy ra khi mã được tái cấu trúc quá nhiều đến mức cấu trúc không còn giống với mã ban đầu (thông số mới được thêm/xóa vào phương thức, v.v.). Nó sẽ làm theo mà các xét nghiệm sẽ cần phải bao thanh toán lại cũng? Trong trường hợp đó, bạn có khả năng có thể thay đổi chức năng của hệ thống trong khi cho phép các bài kiểm tra tiếp tục đi qua? Việc kiểm tra lại có phải là một điều thích hợp để làm trong hoàn cảnh này không?

Trong khi nó ok để plod trên với giả định tôi đã tự hỏi liệu có bất kỳ suy nghĩ/đề xuất về những vấn đề như vậy từ một kinh nghiệm tập thể.

+0

tái cấu trúc là bảo quản hành vi - được thi hành bởi các thử nghiệm của bạn. Vì vậy, nếu bạn thay đổi hành vi thông qua các sửa đổi của bạn, bạn không còn tái cấu trúc nữa. Đối với mã kế thừa, bạn thêm các thử nghiệm hoạt động như một phó để giữ SUT tại chỗ trong khi bạn cải thiện thiết kế theo hướng thử nghiệm. Các xét nghiệm này có thể chậm .. hướng dẫn của 0.1 là dành cho các xét nghiệm microtests/unit. Lý do cho hướng dẫn đó là bạn có thể có hàng ngàn bài kiểm tra nhỏ như vậy .. nếu họ lấy 0.1s mỗi bài, bạn có thể chờ đợi một thời gian dài cho mỗi lần bạn chạy chúng. – Gishu

Trả lời

4
  1. Đó là thỏa thuận khi làm việc với mã cũ. Di sản có nghĩa là một hệ thống không có kiểm tra và được kết hợp chặt chẽ. Khi thêm các thử nghiệm cho mã đó, bạn đang thêm các thử nghiệm tích hợp một cách hiệu quả.Khi bạn refactor và thêm các phương pháp thử nghiệm cụ thể hơn mà tránh các cuộc gọi mạng, vv những người sẽ được thử nghiệm đơn vị của bạn. Bạn muốn giữ cả hai, chỉ cần có sau đó riêng biệt, theo cách đó hầu hết các bài kiểm tra đơn vị của bạn sẽ chạy nhanh.
  2. Bạn làm điều đó trong các bước thực sự nhỏ. Bạn thực sự chuyển đổi liên tục giữa các thử nghiệm và mã, và bạn là chính xác, nếu bạn thay đổi một chữ ký (bước nhỏ) liên quan đến các bài kiểm tra cần phải được cập nhật.

Đồng thời kiểm tra "cập nhật 2" của tôi trên How can I improve my junit tests. Nó không phải là về mã di sản và giao dịch với các khớp nối mà nó đã có, nhưng về cách bạn đi về viết logic + kiểm tra nơi hệ thống bên ngoài có liên quan tức là cơ sở dữ liệu, email, v.v.

2

Thời gian chạy thử nghiệm đơn vị 0,1 là khá ngớ ngẩn. Không có lý do đơn vị kiểm tra không nên sử dụng một ổ cắm mạng, đọc một tập tin lớn hoặc các hoạt động nhượng khác nếu họ có. Có tốt nếu thử nghiệm chạy nhanh để bạn có thể tiếp tục với công việc chính là viết ứng dụng nhưng nó đẹp hơn để kết thúc tốt nhất ở cuối và nếu điều đó có nghĩa là chạy thử nghiệm đơn vị mất 10 giây thì đó là những gì tôi 'd làm.

Nếu bạn định cấu trúc lại khóa, hãy dành nhiều thời gian khi bạn cần hiểu mã mà bạn đang tái cấu trúc. Một cách tốt để làm điều đó là viết một vài bài kiểm tra đơn vị cho nó. Khi bạn nắm được những khối mã nào đó đang làm, bạn có thể cấu trúc lại nó và sau đó thực hành tốt để viết các bài kiểm tra cho từng phương pháp mới của bạn khi bạn đi.

+0

Tôi xin lỗi, nhưng có mọi lý do trên thế giới một bài kiểm tra đơn vị không nên sử dụng ổ cắm cơ sở dữ liệu, đọc một tệp lớn hoặc bất kỳ hoạt động nhượng quyền nào khác. Mặc dù vậy, lý do chính là nếu một thử nghiệm thực sự làm điều này, nó sẽ là một thử nghiệm tích hợp và không phải là một thử nghiệm đơn vị.Bạn phải giả định các phụ thuộc của bạn để không có I/O thực sự xảy ra và logic của mã của bạn có thể được kiểm tra mà không dựa vào, cơ sở dữ liệu của bạn hoạt động chính xác. Đó là lý do tại sao một mục tiêu 0.1s là hoàn toàn hợp lý, bởi vì không có I/O thực sự xảy ra. –

1
    • Vâng, tạo thử nghiệm mới cho các phương pháp mới.

    • Tôi muốn xem 1/10 giây là mục tiêu bạn nên cố gắng. Một thử nghiệm chậm hơn vẫn tốt hơn nhiều so với không thử nghiệm.

  1. Cố gắng không thay đổi mã và thử nghiệm cùng một lúc. Luôn luôn thực hiện các bước nhỏ.

+0

Thử nghiệm chậm hơn có thể ổn nếu không chậm đến mức mọi người không chạy thường xuyên. – JeffH

0

Đây là của tôi trên đó:

  1. Không và có. Điều đầu tiên đầu tiên là có một bài kiểm tra đơn vị kiểm tra đầu ra của phương thức 500 dòng đó. Và rồi chỉ khi bạn bắt đầu nghĩ đến việc chia nhỏ nó. Lý tưởng nhất là quá trình này sẽ diễn ra như sau:

    • Viết một bài kiểm tra cho các di sản gốc 500-line khổng lồ
    • Hình ra, đánh dấu lần đầu tiên với ý kiến, những gì các khối mã bạn có thể trích xuất từ ​​phương pháp mà
    • Viết một thử nghiệm cho mỗi khối mã. Tất cả sẽ thất bại.
    • Giải nén từng khối một. Tập trung vào việc nhận được tất cả các phương pháp đi một màu xanh lá cây tại một thời điểm.
    • Rửa và lặp lại cho đến khi bạn đã hoàn tất toàn bộ điều

    Sau quá trình dài này, bạn sẽ nhận ra rằng nó có thể có ý nghĩa rằng một số phương pháp được di chuyển nơi khác, hoặc là lặp đi lặp lại và một số có thể được giảm đến một đơn chức năng; đây là cách bạn biết rằng bạn đã thành công. Chỉnh sửa các bài kiểm tra cho phù hợp.

  2. Tiếp tục và cấu trúc lại, nhưng ngay sau khi bạn cần thay đổi chữ ký, hãy thực hiện thay đổi trong kiểm tra trước khi bạn thực hiện thay đổi trong mã thực của mình. Bằng cách đó bạn đảm bảo rằng bạn vẫn đang thực hiện các xác nhận chính xác cho sự thay đổi trong chữ ký phương thức.

1

Khi bạn đã có một phương pháp di sản lâu dài mà không X (và có thể Y và Z vì kích thước của nó), lừa thực sự là không phá vỡ ứng dụng bằng cách 'sửa chữa' nó. Các bài kiểm tra trên ứng dụng cũ có điều kiện tiên quyết và postconditions và do đó bạn đã thực sự biết những người trước khi bạn đi phá vỡ nó lên. Các xét nghiệm giúp tạo thuận lợi cho điều đó. Ngay sau khi bạn phá vỡ phương pháp đó thành hai hoặc nhiều phương pháp mới, rõ ràng bạn cần phải biết trước/sau tiểu bang cho mỗi người và vì vậy kiểm tra cho những người 'giữ cho bạn trung thực' và cho phép bạn ngủ ngon hơn vào ban đêm.

Tôi không có xu hướng lo lắng quá nhiều về xác nhận thứ 1/thứ 10 của lần xác nhận thứ hai. Thay vào đó, mục tiêu khi tôi viết bài kiểm tra đơn vị là bao gồm tất cả các căn cứ của tôi. Rõ ràng, nếu một thử nghiệm mất một thời gian dài, nó có thể là bởi vì những gì đang được thử nghiệm chỉ đơn giản là cách quá nhiều mã làm cách quá nhiều.

Điểm mấu chốt là bạn chắc chắn không muốn lấy những gì có lẽ là một hệ thống làm việc và 'sửa' nó đến mức nó hoạt động đôi khi và thất bại trong những điều kiện nhất định. Đó là nơi các xét nghiệm có thể giúp ích. Mỗi người trong số họ hy vọng thế giới sẽ ở trong một trạng thái lúc bắt đầu thử nghiệm và một trạng thái mới ở cuối. Chỉ có bạn mới biết được hai trạng thái đó là chính xác. Tất cả các bài kiểm tra có thể 'vượt qua' và ứng dụng vẫn có thể sai.

Bất kỳ khi nào mã được thay đổi, các kiểm tra có thể sẽ thay đổi và những thay đổi mới có thể sẽ cần phải được thêm vào để thay đổi địa chỉ được thực hiện cho mã sản xuất. Những thử nghiệm này làm việc với mã hiện tại - không quan trọng nếu các tham số cần thay đổi, vẫn còn các điều kiện trước/sau phải được đáp ứng. Nó không phải là đủ, rõ ràng, chỉ cần chia nhỏ mã thành các phần nhỏ hơn. "Nhà phân tích" trong bạn phải có khả năng hiểu được hệ thống bạn đang xây dựng - đó là công việc.

Làm việc với mã cũ có thể là công việc thực sự tùy thuộc vào 'lộn xộn' mà bạn bắt đầu. Tôi thực sự thấy rằng biết những gì bạn đã có và những gì nó là nghĩa vụ phải làm (và cho dù nó thực sự hiện nó ở bước 0 trước khi bạn bắt đầu refactoring nó) là chìa khóa để tái cấu trúc thành công của mã. Một mục tiêu, tôi nghĩ, là tôi nên có thể tung ra những thứ cũ, gắn mã mới của tôi vào vị trí của nó và làm cho nó hoạt động như quảng cáo (hoặc tốt hơn). Tùy thuộc vào ngôn ngữ được viết, các giả định của tác giả gốc và khả năng đóng gói chức năng thành các phần có thể chứa, nó có thể là một thủ thuật thực sự.

Chúc bạn may mắn!

0

Câu hỏi 1: "Khi tôi chia chức năng này lên, tôi có tạo các thử nghiệm mới cho mỗi phương pháp/lớp mới có kết quả không?"

Như thường lệ, câu trả lời thực là tùy thuộc vào. Nếu nó là thích hợp, nó có thể đơn giản hơn khi tái cấu trúc một số phương thức nguyên khối khổng lồ thành các phương thức nhỏ hơn để xử lý các thành phần khác nhau để đặt các phương thức mới của bạn thành riêng tư/bảo vệ và để nguyên API hiện tại của bạn để tiếp tục sử dụng các kiểm thử đơn vị hiện có của bạn. Nếu bạn cần kiểm tra các phương thức mới được tách ra, đôi khi sẽ thuận lợi khi chỉ đánh dấu chúng là gói riêng để các lớp thử nghiệm đơn vị của bạn có thể nhận được chúng nhưng các lớp khác thì không.

Câu hỏi 2: "Điều gì sẽ xảy ra khi mã được xác định lại nhiều đến mức cấu trúc không còn giống mã gốc nữa?"

Lời khuyên đầu tiên của tôi ở đây là bạn cần có một IDE tốt và có kiến ​​thức tốt về các biểu thức chính quy - cố gắng thực hiện nhiều việc tái cấu trúc bằng các công cụ tự động nhất có thể. Điều này có thể giúp tiết kiệm thời gian nếu bạn thận trọng, đủ để không giới thiệu các vấn đề mới. Như bạn đã nói, bạn phải thay đổi bài kiểm tra đơn vị của bạn - nhưng nếu bạn sử dụng hiệu trưởng OOP tốt với (bạn đã làm đúng?), Sau đó nó không nên đau đớn như vậy.

Nhìn chung, điều quan trọng là bạn nên tự hỏi mình liên quan đến nhà cấu trúc lại có những lợi ích lớn hơn chi phí không? Tôi chỉ đang loay hoay xung quanh với kiến ​​trúc và thiết kế? Tôi đang làm một nhà tái cấu trúc để hiểu mã và có thực sự cần thiết không? Tôi sẽ tham khảo ý kiến ​​một đồng nghiệp đã quen thuộc với cơ sở mã cho ý kiến ​​của họ về chi phí/lợi ích của công việc hiện tại của bạn.

Cũng nên nhớ rằng lý tưởng lý thuyết bạn đọc trong sách cần phải được cân bằng với nhu cầu kinh doanh thực tế và lịch trình thời gian.

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