Có một nguyên tắc công nghệ phần mềm liên quan đến chi phí kiểm tra tái sử dụng và hồi quy trên một hệ thống sản xuất không?


12

Tôi đã làm việc trên một hệ thống giao dịch tài chính lớn cho một ngân hàng chăm sóc lương hưu và đầu tư. Sau 15 năm thay đổi tính năng, chi phí kiểm tra hồi quy thủ công đã tăng lên 200 nghìn đô la mỗi lần phát hành. (10 triệu LỘC, 10 triệu đô la giao dịch mỗi ngày). Hệ thống này cũng giao tiếp với 19 hệ thống khác xung quanh công ty di chuyển rất nhiều dữ liệu xung quanh. Hệ thống này đã được triển khai trong Java.

Tuy nhiên, những gì chúng tôi quan sát được là chúng tôi càng sử dụng lại nhiều hơn, chi phí kiểm tra hồi quy càng tăng. (Lý do là bạn cần "kiểm tra mã bạn chạm" - và mã được sử dụng / chia sẻ lại ảnh hưởng đến nhiều địa điểm khi chạm vào. Vì vậy, mặc dù 'DRY - Không lặp lại chính mình' - tức là không sao chép và dán mã - chúng tôi nhận thấy sự khuyến khích tài chính để sao chép và dán mã. Điều này nhằm giảm chi phí kiểm tra hồi quy, vì chúng tôi không muốn sửa đổi mã có thể được chia sẻ, vì điều đó sẽ gây ra tác động kiểm tra hồi quy lớn.)

Câu hỏi của tôi là có một nguyên tắc kỹ thuật phần mềm mô tả mối quan hệ giữa chi phí kiểm tra tái sử dụng và hồi quy?

Lý do tôi hỏi câu hỏi này là có thể cho rằng có một lợi ích chi phí trong việc phân tách hệ thống thành các phần nhỏ hơn để được kiểm tra.

Giả định:

  1. 'Kiểm tra hồi quy' có nghĩa là 'kiểm tra chấp nhận' - tức là một nhóm khác dành thời gian để viết mới và sử dụng lại các kiểm tra cũ đối với hệ thống thay mặt cho doanh nghiệp, bao gồm thiết lập môi trường và dữ liệu.

  2. Tôi biết phản ứng giật đầu gối với chi phí kiểm tra hồi quy lớn là 'kiểm tra tự động hơn'. Đây là một nguyên tắc tốt. Trong môi trường này có một vài thách thức.

    (a) Kiểm tra tự động ít hữu ích hơn trong các ranh giới hệ thống, trừ khi hệ thống đó có phạm vi kiểm tra tự động cao. (Phạm vi thách thức ảnh hưởng).

    (b) Rất khó để có được động lực về thời gian của lập trình viên hoặc đầu tư vốn vào phạm vi kiểm tra tự động cao khi hệ thống của bạn đã lớn và phức tạp.

    (c) Chi phí duy trì kiểm tra tự động được ẩn trong một dự án và do đó chúng dễ dàng bị loại bỏ ở cấp dự án.

    (d) Đây chỉ là thực tế văn hóa làm việc trong ngân hàng.

    (e) Tôi đang làm việc để giải quyết vấn đề này theo một cách khác (phân tách).


2
Bạn đưa ra tuyên bố sóng tay mà chúng tôi quan sát thấy [ Mạnh ] rằng chúng tôi càng sử dụng lại nhiều hơn, chi phí kiểm tra [chấp nhận] càng tăng lên - bạn có thể mở rộng điều đó không? Chẳng phải một thử nghiệm chấp nhận không phải là bất khả tri về các chi tiết triển khai như hệ thống phân cấp thừa kế, mà thay vào đó, hãy chơi qua các kịch bản sử dụng, chẳng hạn?
amon

2
Câu hỏi của bạn rất thú vị, nhưng nó chứa một số giả định rất thiên vị như "tái sử dụng là hậu quả của OO" hoặc phần @amon đã đề cập. Tôi khuyên bạn nên xóa hoàn toàn phần "OO" vì câu hỏi cốt lõi của bạn không phụ thuộc vào ngôn ngữ lập trình hoặc bất kỳ chương trình OO nào. Và điều khá rõ ràng là bạn đang sử dụng loại "tái sử dụng" nào - "tái sử dụng" là một thuật ngữ rộng, tái sử dụng sao chép-dán khác với tái sử dụng thành phần hoặc thư viện.
Doc Brown

Cảm ơn đó là hữu ích. Tôi đã xóa các tham chiếu đến OO - và mở rộng về ý tưởng chạm vào mã được chia sẻ, (hoặc mã sẽ trở thành mã được chia sẻ).
hawkeye

1
Ở dạng hiện tại, tôi đoán tôi sẽ trả lời là "không, tôi không nghĩ vậy" cho câu hỏi của bạn - điều mà tôi đoán sẽ không thỏa mãn cho bạn. Hay bạn quan tâm đến các nguyên tắc và thực tiễn để thực sự giảm chi phí thử nghiệm khi xây dựng một hệ thống lớn như của bạn với một số thành phần có thể tự làm lại?
Doc Brown

Câu trả lời:


11

chúng tôi không muốn sửa đổi mã có thể được chia sẻ, vì điều đó sẽ gây ra tác động thử nghiệm hồi quy lớn

Trên âm thanh về quyền của tôi. Mã càng quan trọng, nó càng được chia sẻ, yêu cầu chất lượng càng cao thì càng cần phải đảm bảo chất lượng khi thay đổi.

Vì hệ thống của bạn được triển khai bằng Java, bạn có thể thấy một ví dụ ở trên ngay tại đó, trong các thư viện tiêu chuẩn Java (JDK). Các bản phát hành chính của nó không thường xuyên, và đi kèm với thử nghiệm rất tốn công sức. Và thậm chí các bản phát hành nhỏ chạy qua bộ thử nghiệm JCK rất toàn diện để xác minh sự vắng mặt của hồi quy.

Bạn có thể nghĩ rằng điều này bằng cách nào đó kìm hãm sự phát triển của mã được chia sẻ, và ... vâng điều này đúng. Càng nhiều tác động và rủi ro liên quan đến thay đổi mã, bạn càng cẩn thận hơn khi thực hiện nó, thì càng cần phải nỗ lực nhiều hơn để thử nghiệm các bản phát hành của nó.

Lý tưởng nhất là chất lượng phát hành mã được chia sẻ rộng rãi sao cho không cần thay đổi lớn (tiết kiệm cho các cải tiến không thường xuyên). Dòng suy nghĩ này được phản ánh trong một câu nói nổi tiếng của Joshua Bloch :

API công khai, giống như kim cương, là mãi mãi. Bạn có một cơ hội để làm cho đúng, vì vậy hãy cố gắng hết sức.


Mặc dù đã nói ở trên, có vẻ như một số vấn đề bạn mô tả là do chiến lược phát triển mã chia sẻ không hiệu quả. Đặc biệt, có vẻ đặc biệt rắc rối khi đối với mã được sử dụng lại, chỉ có hai tùy chọn được xem xét: sao chép mã này hoặc đưa ngay vào thư viện chia sẻ "lõi".

Giới hạn chỉ có hai tùy chọn này là không cần thiết và, một lần nữa, bạn có thể tìm thấy các ví dụ về cách nó có thể được thực hiện tốt hơn trong chính JDK bạn sử dụng. Hãy xem java.util.concurrentcác gói ( JSR 166 ) - cho đến khi phát hành Java 5, đây là một thư viện riêng biệt, không phải là một phần của các bản phát hành JDK cốt lõi.

Hãy nghĩ về nó, đó là một lựa chọn thứ ba mà bạn bỏ qua, và một lựa chọn khá thực dụng, đó là lựa chọn bạn cần xem xét khi "khởi động" mã chia sẻ mới. Khi bạn chỉ cần tìm một số mã có thể được chia sẻ giữa 2-3 thành phần, không có gì buộc bạn phải đưa ngay vào API cốt lõi của hệ thống.

Bạn có thể đóng gói và phát hành mã chia sẻ "chưa trưởng thành" này dưới dạng thư viện riêng biệt, giống như nó đã được thực hiện cho các tiện ích đồng thời Java. Cách này giúp bạn thoát khỏi nhu cầu kiểm tra hồi quy đầy đủ, bởi vì bạn chỉ có thể sử dụng một lượng tương đối nhỏ các thành phần liên quan. Do đó, bạn có nhiều thời gian hơn để sửa đổi và cải thiện mã được chia sẻ này và để kiểm tra cách thức hoạt động của nó trong sản xuất.

Sau khi thư viện của bạn đáo hạn và ổn định đủ để bạn tự tin rằng những thay đổi tiếp theo là không thể xảy ra, bạn có thể xem xét việc đưa nó vào các thư viện cốt lõi của hệ thống, giống như các tiện ích đồng thời cuối cùng đã được đưa vào JDK.


Một ví dụ cụ thể về bao nhiêu nỗ lực (bao gồm cả thử nghiệm) có thể liên quan đến việc thay đổi mã được sử dụng lại nhiều có thể được tìm thấy, một lần nữa, trong JDK. Trong bản phát hành 7u6, họ đã thay đổi Stringđại diện nội bộ liên quan đến thay đổi substringhiệu suất. Nhận xét của nhà phát triển tính năng tại Reddit phác thảo bao nhiêu nỗ lực đã tham gia vào thay đổi này:

Phân tích ban đầu được đưa ra khỏi nhóm GC vào năm 2007 ...

Trong nội bộ, nhóm hiệu suất của Oracle duy trì một tập hợp các ứng dụng và điểm chuẩn quan trọng mà họ sử dụng để đánh giá các thay đổi về hiệu suất. Nhóm ứng dụng này rất quan trọng trong việc đánh giá sự thay đổi của chuỗi con. Chúng tôi đã xem xét kỹ cả hai thay đổi về hiệu suất và thay đổi về dấu chân. Không thể tránh khỏi, như trường hợp với bất kỳ thay đổi đáng kể nào, đã có sự hồi quy trong một số ứng dụng cũng như lợi ích ở những ứng dụng khác. Chúng tôi đã điều tra các hồi quy để xem hiệu suất có còn chấp nhận được không và tính đúng đắn được duy trì ...

Câu trả lời của tôi không nhằm mục đích toàn diện nhưng là một bản tóm tắt rất ngắn gọn về gần sáu tháng làm việc tận tụy ...


Có vẻ như cả hai chúng tôi đã làm việc song song với một câu trả lời, với rất nhiều suy nghĩ tương tự ...
Doc Brown

@DocBrown yeah, thật thú vị khi chúng tôi cũng trả lời gần như đồng thời, khoảng một giờ sau khi câu hỏi được chỉnh sửa thành hình
gnat

9

Tôi không nghĩ rằng có tồn tại bất kỳ số liệu nào để tính toán "chi phí cho các bài kiểm tra hồi quy / LỘC của mã được sử dụng lại được xây dựng". Và tôi không nghĩ có ai từng đầu tư nhiều thời gian và tiền bạc để xây dựng cùng một hệ thống "lớn" hai lần, một phiên bản với rất nhiều thành phần có thể thay đổi được, và một phiên bản không có, để thực hiện bất kỳ nghiên cứu nghiêm túc nào về điều đó.

Nhưng tôi đã thấy các vấn đề gây ra bởi việc tái sử dụng như của bạn trước đây và có thể bạn quan tâm đến một số suy nghĩ về cách xử lý việc này tốt hơn.

Đầu tiên, đó thực sự không phải là tái sử dụng , đó là vấn đề của bạn - đó là nỗ lực xây dựng các thành phần có thể tái sử dụng của riêng bạn và sử dụng chúng trong toàn hệ thống của bạn. Tôi chắc chắn rằng bạn đang sử dụng lại rất nhiều gói phần mềm lớn, nơi các vấn đề của bạn không phát sinh: nghĩ về toàn bộ ngăn xếp Java bạn đang sử dụng hoặc có thể một số thành phần bên thứ ba (giả sử bạn hài lòng với các thành phần đó). Nhưng điều gì khác biệt với phần mềm đó, ví dụ, các thư viện Java, trong khi các thành phần có thể sử dụng lại của chính bạn đang khiến bạn phải trả thêm rất nhiều chi phí kiểm tra hồi quy? Đây là một số điểm tôi đoán có thể khác nhau:

  • những thành phần này rất trưởng thành và ổn định

  • chúng được phát triển và thử nghiệm đầy đủ trong sự cô lập, bởi một tổ chức hoàn toàn khác

  • để (sử dụng lại) chúng, bạn không phải thay đổi chúng (thực tế là bạn thậm chí không thể làm như vậy, vì bạn không duy trì mã nguồn)

  • bạn không nhận được phiên bản mới hàng ngày, chỉ cập nhật nhỏ (tối đa mỗi tháng) hoặc cập nhật lớn trong khoảng thời gian mỗi năm

  • hầu hết các bản cập nhật được thiết kế để tương thích 100% trở xuống, đặc biệt là các bản cập nhật nhỏ

Vì vậy, để làm cho các thành phần có thể sử dụng lại của bạn thành công hơn, bạn nên điều chỉnh một số điều đó từ phía trên cho sự phát triển của riêng bạn:

  • đối với bất kỳ thành phần có thể tái sử dụng nào, có trách nhiệm rõ ràng là người bảo trì và đảm bảo rằng tất cả những người sử dụng lại một thành phần có thể chắc chắn nhận được một lỗi ngay lập tức nếu có vấn đề phát sinh.

  • thiết lập một chính sách phiên bản và phát hành nghiêm ngặt. Khi phát triển một thành phần có thể tái sử dụng, đừng phát hành "cho mọi người" mỗi ngày (ít nhất, không phải nếu điều đó có nghĩa là chạy thử nghiệm hồi quy đầy đủ $ 200K trên hệ thống). Thay vào đó, thỉnh thoảng hãy để các phiên bản mới được xuất bản và cung cấp các cơ chế để cho phép người dùng thành phần đó trì hoãn thay đổi đối với phiên bản mới.

  • một thành phần càng thường xuyên được tái sử dụng, điều quan trọng hơn là nó cung cấp một giao diện ổn định và hành vi tương thích hướng xuống.

  • các thành phần có thể tái sử dụng cần các bộ kiểm tra rất đầy đủ để kiểm tra chúng một cách cô lập.

Rất nhiều trong số những điều này có nghĩa là chi phí xây dựng thành phần sẽ tăng lên, nhưng nó cũng sẽ giảm chi phí thay đổi do hồi quy thất bại.


0

Mặc dù có thể có sự gia tăng chi phí "có thể quan sát" do cần nhiều thử nghiệm hơn, nhưng kiểu tái cấu trúc đó thường làm cho mã dễ duy trì hơn trong tương lai vì bạn đang giảm nợ kỹ thuật trong hệ thống.

Điều này hy vọng sẽ giảm các lỗi trong tương lai và làm cho các tính năng mới hoặc thay đổi thành các tính năng hiện có dễ thực hiện hơn.

Bằng cách dễ dàng hơn, tôi có nghĩa là họ nên mất ít thời gian hơn và do đó chi phí ít hơn.

Giảm, dễ dàng hơn và ít hơn là tất cả các thuật ngữ khá mơ hồ ở đây và bất kỳ khoản tiết kiệm nào trong tương lai (hoặc được hy vọng là tiết kiệm) là không thể tính toán vì nó chưa xảy ra.

Một cơ sở mã đơn giản hơn sẽ cho phép nhân viên mới hoặc nhân viên hiện tại di chuyển vào dự án tăng tốc nhanh hơn, đặc biệt là đối với các hệ thống lớn.

Nó cũng có thể làm giảm doanh thu nhân viên trong đó tinh thần thành viên dự án hiện tại có thể được cải thiện.

Tất nhiên không đảm bảo rằng bạn sẽ nhận được những lợi ích này, nhưng đây là những điều cần được xem xét cùng với chi phí (như thử nghiệm tăng) có thể đo lường được.

Trong thực tế, mã tốt hơn cuối cùng sẽ giảm chi phí thử nghiệm theo thời gian, ngay cả khi có sự gia tăng ban đầu do những gì bạn mô tả.

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.