2008-10-10 68 views
66

Chúng tôi có một cơ sở mã khá lớn, 400K LOC của C++, và sao chép mã là một vấn đề. Có bất kỳ công cụ nào có hiệu quả có thể phát hiện các khối mã trùng lặp không?Làm thế nào để phát hiện trùng lặp mã trong quá trình phát triển?

Lý tưởng nhất đây sẽ là điều mà các nhà phát triển có thể sử dụng trong quá trình phát triển thay vì chỉ chạy thỉnh thoảng để xem vấn đề ở đâu. Nó cũng sẽ tốt đẹp nếu chúng ta có thể tích hợp một công cụ như vậy với CruiseControl để đưa ra một báo cáo sau mỗi lần kiểm tra.

Tôi đã xem Duploc một số thời gian trước đây, yêu cầu một môi trường nhỏ để sử dụng nó , điều này làm cho việc chạy nó tự động khá khó khăn.

Công cụ miễn phí sẽ đẹp, nhưng nếu có một số công cụ thương mại tốt, tôi cũng sẽ quan tâm.

+3

Bất cứ khi nào ai đó sử dụng nút dán: -} –

+0

Câu hỏi liên quan - http://stackoverflow.com/questions/2490884/why-is-copy-and-paste-of-code-dangerous – Oded

Trả lời

33

Simian phát hiện mã trùng lặp trong các dự án C++.

Cập nhật: Cũng làm việc với Java, C#, C, COBOL, Ruby, JSP, ASP, HTML, XML, Visual Basic, mã nguồn Groovy và các tập tin văn bản ngay cả đồng bằng

+0

sẽ simian kiểm tra liên tục. Mm Các tệp, AKA ObjectiveC++ – rraallvv

+1

@rraallvv Simian có thể thực hiện kiểm tra văn bản thuần tuý, do đó, nó có thể phát hiện sự sao chép mã bằng bất kỳ ngôn ngữ nào. – Catharz

+2

Lưu ý rằng nó không miễn phí cho mục đích thương mại. – Zitrax

5

Nhìn vào PMD project.

Tôi chưa bao giờ sử dụng, nhưng luôn muốn.

+0

Tôi nghĩ rằng PMD chỉ dành cho Java, nhưng bây giờ tôi thấy rằng CPD (một phần của PMD) cũng có thể được sử dụng cho C++. –

1

CCFinderX là trình phát hiện mã nhân bản miễn phí (để sử dụng trong nhà) hỗ trợ nhiều ngôn ngữ lập trình (Java, C, C++, COBOL, VB, C#).

+0

Cảm ơn bạn đã liên kết này. Tôi chắc chắn sẽ nhìn vào nó. Thậm chí tốt hơn là có một phiên bản tiếng Nhật (tất cả các nhà phát triển khác trong dự án ngoài tôi là người Nhật) –

-3

TeamCity có công cụ sao chép mã mạnh mẽ cho .NET và java, có thể dễ dàng chạy như một phần của hệ thống xây dựng của bạn.

+0

Không có .Net hoặc Java là C++, vì vậy trong khi điều này có thể dễ dàng chạy, nó cũng không có kết quả. – Tom

18

Tôi đã sử dụng PMD's Copy-and-Paste-Detector và tích hợp nó vào CruiseControl bằng cách sử dụng tập lệnh trình bao bọc sau (hãy chắc chắn có dấu ngoặc vuông trong đường dẫn lớp).

Séc của chúng tôi chạy hàng đêm. Nếu bạn muốn giới hạn đầu ra để chỉ liệt kê các tệp từ bộ thay đổi hiện tại, bạn có thể cần một số chương trình tùy chỉnh (ý tưởng: kiểm tra tất cả và chỉ liệt kê các bản sao mà một trong các tệp đã thay đổi có liên quan. một số mã từ một tập tin không thay đổi). Nên có thể thực hiện được bằng cách sử dụng đầu ra XML và phân tích cú pháp kết quả. Đừng quên gửi kịch bản đó khi hoàn thành;)

Để bắt đầu, đầu ra "Văn bản" phải ổn, nhưng bạn sẽ muốn hiển thị kết quả theo cách thân thiện với người dùng, tôi sử dụng tập lệnh perl để tạo tệp HTML từ đầu ra "xml" của CPD. Những người có thể truy cập bằng cách đăng chúng vào tomcat nơi jsp báo cáo của hành trình cư trú. Các nhà phát triển có thể xem chúng từ đó và xem kết quả của sự tấn công bẩn của chúng :)

Nó chạy khá nhanh, ít hơn 2 giây trên 150 mã KLoc (dòng trống và chú thích không được tính trong số đó).

duplicatecheck.xml:

<project name="duplicatecheck" default="cpd"> 

<property name="files.dir" value="dir containing your sources"/> 
<property name="output.dir" value="dir containing results for publishing"/> 

<target name="cpd"> 
    <taskdef name="cpd" classname="net.sourceforge.pmd.cpd.CPDTask"/> 
    <cpd minimumTokenCount="100" 
     language="cpp" 
     outputFile="${output.dir}/duplicates.txt" 
     ignoreLiterals="false" 
     ignoreIdentifiers="false" 
     format="text"> 
     <fileset dir="${files.dir}/"> 
      <include name="**/*.h"/> 
      <include name="**/*.cpp"/> 
       <!-- exclude third-party stuff --> 
      <exclude name="boost/"/> 
      <exclude name="cppunit/"/> 
     </fileset> 
    </cpd> 
</target> 

+0

Đảm bảo sử dụng phiên bản mới nhất từ ​​trang sourgeforge! Trang tài liệu của họ cho thấy một phiên bản từ năm 2011, trong khi có sự phát triển tích cực. Trong trường hợp của tôi phiên bản 5.5 hoạt động tốt hơn nhiều so với phiên bản 4.2 họ liên kết trên trang chủ của họ. – FourtyTwo

1

tìm "giống hệt" đoạn mã là tương đối dễ dàng, có những công cụ hiện có mà đã làm điều này (xem câu trả lời khác).

Đôi khi đó là điều tốt, đôi khi không phải; nó có thể làm giảm thời gian phát triển nếu được thực hiện ở mức "quá" tốt; I E.cố gắng để tái cấu trúc mã quá nhiều, bạn mất mục tiêu của bạn (và có thể phá vỡ sự kiện quan trọng và lịch trình của bạn).

Điều khó hơn là tìm nhiều hàm/phương thức thực hiện tương tự nhưng với các đầu vào và/hoặc thuật toán khác (nhưng tương tự) không có tài liệu thích hợp.

Nếu bạn có hai hoặc các phương pháp khác nhau để làm điều tương tự và lập trình cố gắng sửa một thể hiện nhưng quên (hoặc không biết chúng tồn tại) để sửa lỗi khác, bạn sẽ tăng rủi ro cho phần mềm của mình.

+3

... và là một vấn đề thực tế, bạn sẽ không thể phát hiện hai đoạn mã * làm * điều tương tự nếu chúng được thực hiện khác nhau. Có một máy Turing đứng theo cách của bạn. –

+1

"Điều khó hơn là tìm nhiều chức năng/phương pháp làm cùng một điều nhưng với các đầu vào và/hoặc thuật toán khác nhau (nhưng tương tự) mà không có tài liệu thích hợp." Phải. Và nếu họ làm điều tương tự, họ nên được đặt tên giống nhau, vì tên nên mô tả lý do tại sao mã đó tồn tại ở nơi đầu tiên. Vì vậy, bước một có thể là để đảm bảo rằng tất cả các chức năng/phương pháp được đặt tên và tài liệu chính xác. Nếu tên thật sự mô tả những gì nó làm, những điểm tương đồng và danh tính sẽ nhanh chóng trở nên rõ ràng. – mickeyf

+0

Rắc rối là, ngay cả một "cùng một điều" oracle (mà tôi tin là mạnh hơn đáng kể so với một oracle tạm dừng?) Sẽ không giúp bạn tìm ra nếu hai tên thể hiện (hoặc được dự định để thể hiện) cùng một ý tưởng. (Bên cạnh đó, sẽ có xu hướng có nhiều sai sót tích cực.) – SamB

6

duplo dường như là triển khai C của thuật toán được sử dụng trong Duploc. Nó rất đơn giản để biên dịch và cài đặt, và trong khi các tùy chọn bị hạn chế, nó dường như làm việc nhiều hơn hoặc ít hơn.

+0

Tôi vừa thử nó trên một tệp mã khá thừa kế với rất nhiều tấn-gần-dupes, và so sánh với một tệp mã gần đây với ít hoàn hảo- dupes.Tệp cũ được xếp hạng hoàn hảo. Tệp mới được xếp hạng không tốt. –

2

Vâng, bạn có thể chạy trình phát hiện bản sao trên nguồn của mình mã cơ sở mỗi đêm.

Nhiều trình dò ​​bản sao hoạt động bằng cách so sánh các dòng nguồn, và chỉ có thể tìm mã trùng lặp chính xác.

CCFinder, ở trên, hoạt động bằng cách so sánh ngôn ngữ mã thông báo, do đó không nhạy cảm với không gian trắng thay đổi. Nó có thể phát hiện nhân bản là các biến thể của mã gốc nếu chỉ có một mã thông báo thay đổi (ví dụ: thay đổi biến X thành Y trong bản sao).

Lý tưởng nhất là những gì bạn muốn là ở trên, nhưng khả năng để tìm nhái nơi các biến thể được phép là tương đối tùy ý, ví dụ như , thay thế một biến bởi một biểu thức, một tuyên bố bởi một khối vv

Trình tạo bản sao CloneDR của chúng tôi thực hiện điều này cho Java, C#, C++, COBOL, VB.net, VB6, Fortran và nhiều ngôn ngữ khác . Có thể xem tại: http://www.semdesigns.com/Products/Clone/index.html

Cũng như có thể xử lý nhiều ngôn ngữ, công cụ CloneDR có khả năng xử lý nhiều kiểu mã hóa đầu vào khác nhau, bao gồm ASCII, ISO-8859-1, UTF8, UTF16, EBCDIC, một số mã hóa của Microsoft, và (tiếng Nhật) Shift-JIS.

Trang web có một số báo cáo ví dụ chạy phát hiện bản sao, bao gồm một cho C++.

EDIT tháng 2 năm 2014: Hiện đang xử lý tất cả C++ 14.

1

Tương tự (http://sourceforge.net/projects/same/) cực kỳ đơn giản, nhưng nó hoạt động trên dòng văn bản thay vì mã thông báo, rất hữu ích nếu bạn đang sử dụng ngôn ngữ không được hỗ trợ bởi một trong những công cụ tìm kiếm nhân bản.

0

Ngoài ra còn có Simian mà hỗ trợ Java, C#, C++, C, Objective-C, JavaScript ...

Nó được hỗ trợ bởi Hudson (như CPD).

Trừ khi bạn là một dự án nguồn mở, bạn phải thanh toán cho Simian.

2

Để tham khảo trong tương lai của riêng tôi, những gói Debian dường như làm một cái gì đó cùng những dòng này:

Tôi có thể thề rằng tôi đã có một số gói khác được cài đặt tại có thể thậm chí còn phù hợp hơn, nhưng tôi không thể tìm thấy chúng vào lúc này. (Đó là lý do tại sao tôi liệt kê những phát hiện của tôi ở đây lần này: để cho bản thân mình cơ hội được tìm lại chúng!)

P.S. Nó thực sự có vẻ như có phải là một thẻ debtags cho tất cả các công cụ liên quan cho việc tìm kiếm [gần] trùng lặp. (Nhưng nó sẽ được gọi là gì?)

1

ConQAT là một công cụ tuyệt vời hỗ trợ phân tích mã C++. Có thể tìm thấy bản sao bỏ qua khoảng trắng. Có giao diện gui và console tiện dụng. Vì tính linh hoạt của nó không dễ cài đặt. Tôi đã tìm thấy this blog post very useful for setting up c++ project.

1

Bạn có thể sử dụng công cụ SourceMeter để phát hiện trùng lặp mã. Nó là một công cụ dòng lệnh (rất giống với các trình biên dịch), vì vậy bạn có thể dễ dàng tích hợp vào các công cụ tích hợp liên tục, như CruiseControl mà bạn đã đề cập, hoặc Jenkins.

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