2008-09-19 39 views
5

Gần đây tôi đã kế thừa ứng dụng giao diện điều khiển C# cần được cắt bớt và dọn dẹp. Dài câu chuyện ngắn, ứng dụng bao gồm một lớp duy nhất chứa hơn 110.000 dòng mã. Yup, hơn 110.000 dòng trong một lớp duy nhất. Và, tất nhiên, ứng dụng này là cốt lõi cho hoạt động kinh doanh của chúng tôi, chạy 'vòng đồng hồ cập nhật dữ liệu được sử dụng trên một trang web động. Mặc dù tôi đã nói với người tiền nhiệm của tôi là "một lập trình viên thực sự tốt", rõ ràng anh ta không phải là tất cả vào OOP (hoặc kiểm soát phiên bản).Làm thế nào để bạn có thể lập trình xác định số tham chiếu đến một phương thức với C#

Dù sao ... trong khi tự làm quen với mã tôi đã tìm thấy nhiều phương thức được khai báo, nhưng không bao giờ được tham chiếu. Có vẻ như sao chép/dán đã được sử dụng để phiên bản mã, ví dụ như tôi có phương thức getSomethingImportant(), có thể có một phương thức khác gọi là getSomethingImortant_July2007() (mẫu là functionName_ [datestamp] trong hầu hết các trường hợp). Có vẻ như khi lập trình viên được yêu cầu thực hiện thay đổi getSomethingImportant(), anh ta sẽ sao chép/dán rồi đổi tên thành getSomethingImortant_Date, thực hiện các thay đổi cho getSomethingImortant_Date, sau đó thay đổi bất kỳ lời gọi phương thức nào trong mã thành tên phương thức mới, để phương thức cũ trong mã nhưng không bao giờ được tham chiếu.

Tôi muốn viết một ứng dụng bảng điều khiển đơn giản thu thập thông qua một lớp rất lớn và trả về danh sách tất cả các phương pháp với số lần mỗi phương pháp được tham chiếu. Theo ước tính của tôi có hơn 1000 phương pháp, do đó, làm điều này bằng tay sẽ mất một lúc.

Có các lớp trong khuôn khổ .NET mà tôi có thể sử dụng để kiểm tra mã này không? Hoặc bất kỳ công cụ hữu ích nào khác có thể giúp xác định các phương thức được khai báo nhưng không bao giờ được tham chiếu?

(Câu hỏi phụ: Có ai khác từng thấy ứng dụng C# như thế này, một lớp học lớn không? Nhiều hay ít quy trình thủ tục rất lớn, tôi biết đây là lần đầu tiên tôi thấy, ít nhất là kích thước này.)

Trả lời

12

Bạn có thể thử sử dụng NDepend nếu bạn chỉ cần trích xuất một số số liệu thống kê về lớp học của mình. Lưu ý rằng công cụ này dựa trên Mono.Cecil nội bộ để kiểm tra các hội đồng.

0

Tôi không biết bất cứ điều gì được xây dựng để xử lý trường hợp cụ thể này, nhưng bạn có thể sử dụng Mono.Cecil. Phản ánh các hội đồng và sau đó tính tham chiếu trong IL. Không nên quá khó khăn.

1

Tôi tin rằng bạn có thể làm điều đó với NDepend, nhưng tôi chưa bao giờ sử dụng nó.

1

Cửa sổ Analyzer của nó trong Reflector có thể hiển thị cho bạn nơi một phương pháp được gọi là (sử dụng theo).
Có vẻ như sẽ mất rất nhiều thời gian để nhận thông tin theo cách đó.
Bạn có thể xem API mà Reflector cung cấp để viết bổ trợ và xem bạn có thể nhận được công việc grunt của phân tích theo cách đó hay không. Tôi hy vọng rằng mã nguồn cho code metrics add-in có thể cho bạn biết một chút về cách lấy thông tin về các phương thức từ API phản xạ.

Chỉnh sửa: Ngoài ra, bổ trợ code model viewer cho Trình phản xạ cũng có thể hữu ích. Đó là một cách hay để khám phá API phản xạ.

0

Không có công cụ dễ dàng để làm điều đó trong .NET framework. Tuy nhiên tôi không nghĩ rằng bạn thực sự cần một danh sách các phương pháp không sử dụng cùng một lúc. Như tôi thấy nó, bạn sẽ chỉ cần đi qua mã và cho mỗi phương pháp bạn sẽ kiểm tra nếu nó không sử dụng và sau đó xóa nó nếu như vậy. Tôi muốn sử dụng Visual Studio "Tìm tham khảo" lệnh để làm điều đó. Hoặc bạn có thể sử dụng Resharper với cửa sổ "Analize" của nó.Hoặc bạn chỉ có thể sử dụng công cụ phân tích mã Visual Studio để tìm tất cả các phương thức riêng không sử dụng.

+0

Đề xuất xóa cũng như ý kiến ​​đầu tiên của tôi cũng là suy nghĩ đầu tiên của tôi. Tôi sẽ sử dụng phương pháp này cộng với NDepend, như những người khác đã đề xuất, để thực hiện phân tích sâu hơn. – Duffy

0

Bạn có thể nhận tiền cho số ReSharper không? Đó là công cụ lý tưởng để tái cấu trúc.

3

Tải xuống bản dùng thử miễn phí của Resharper. Sử dụng Resharper-> Search-> Find Usages trong File (Ctrl-Shift-F7) để tất cả các tập quán được tô đậm. Ngoài ra, một số sẽ xuất hiện trong thanh trạng thái. Nếu bạn muốn tìm kiếm trên nhiều tệp, bạn cũng có thể thực hiện điều đó bằng cách sử dụng Ctrl-Alt-F7.

Nếu bạn không thích điều đó, hãy tìm kiếm văn bản cho tên hàm trong Visual Studio (Ctrl-Shift-F), điều này sẽ cho bạn biết có bao nhiêu lần xuất hiện trong giải pháp và vị trí của chúng.

0

Để trả lời "câu hỏi phụ" của bạn, chưa bao giờ thấy một câu hỏi xấu, có thể là mục nhập tốt cho The Daily WTF. Có thể gọi nó là "Sao chép cuối cùng/dán tái sử dụng".

-1

Hãy thử để trình biên dịch phát ra các tệp trình lắp ráp, như trong hướng dẫn x86, không phải các hội đồng .NET.

Tại sao? Bởi vì nó dễ dàng hơn nhiều để phân tích mã trình lắp ráp hơn là mã C# hoặc hội đồng .NET.

Ví dụ, một hàm/phương pháp kê khai trông giống như sau:

.string "w+" 
    .text 
    .type create_secure_tmpfile, @function 
create_secure_tmpfile: 
    pushl %ebp 
    movl %esp, %ebp 
    subl $24, %esp 
    movl $-1, -8(%ebp) 
    subl $4, %esp 

và chức năng/phương pháp tham khảo sẽ giống như thế này:

subl $12, %esp 
    pushl 24(%ebp) 
    call create_secure_tmpfile 
    addl $16, %esp 
    movl 20(%ebp), %edx 
    movl %eax, (%edx) 

Khi bạn thấy "create_secure_tmpfile:" bạn biết bạn có một khai báo hàm/phương thức, và khi bạn thấy "gọi create_secure_tmpfile" bạn biết bạn có tham chiếu hàm/phương thức. Điều này có thể đủ tốt cho các mục đích của bạn, nhưng nếu không chỉ là một vài bước nữa trước khi bạn có thể tạo ra một cây gọi rất dễ thương cho toàn bộ ứng dụng của bạn.

+0

Làm thế nào là nó "dễ dàng hơn nhiều" để phân tích cú pháp lắp ráp khi. Net bao gồm các thư viện phản ánh? Chưa kể đến các thư viện của bên thứ ba như Mono.Cecil. –

+0

Vì có rất nhiều công cụ để xử lý dữ liệu dựa trên dòng theo cách đặc biệt. ví dụ. grep, sed, awk, v.v. – mbac32768

1

FXCop có quy tắc sẽ xác định các phương pháp riêng tư không được sử dụng. Vì vậy, bạn có thể đánh dấu tất cả các phương thức riêng tư và để nó tạo ra một danh sách.

FxCop cũng có một ngôn ngữ nếu bạn muốn nhận được fancier http://www.binarycoder.net/fxcop/

1

Nếu bạn không muốn bao ra cho NDepend, vì nó có vẻ như đó chỉ là một lớp duy nhất trong một hội duy nhất - nhận xét ra các phương pháp và biên dịch. Nếu nó biên dịch, xóa chúng - bạn sẽ không có bất kỳ vấn đề thừa kế, phương pháp ảo hoặc bất cứ điều gì như thế. Tôi biết nó âm thanh nguyên thủy, nhưng đôi khi tái cấu trúc chỉ là công việc grunt như thế này. Đây là loại giả định bạn có các bài kiểm tra đơn vị bạn chạy sau mỗi lần xây dựng cho đến khi bạn đã làm sạch mã (Red/Green/Refactor).

4

Để hoàn thành câu trả lời Romain Verdier, hãy tìm hiểu kỹ những gì NDepend có thể mang đến cho bạn tại đây. (Tuyên bố từ chối trách nhiệm: Tôi là nhà phát triển của nhóm NDepend)

NDepend cho phép truy vấn mã .NET của bạn với một số truy vấn LINQ. Biết được phương pháp gọi và được gọi bằng mà những người khác, cũng đơn giản như viết các truy vấn LINQ sau:

from m in Application.Methods 
select new { m, m.MethodsCalled, m.MethodsCallingMe } 

Kết quả của truy vấn này được trình bày trong một cách mà làm cho dễ dàng để duyệt người gọi và callees (và 100 của mình % tích hợp vào Visual Studio).

NDepend methods callers and callees


Có rất nhiều khả năng NDepend khác có thể giúp bạn. Ví dụ, bạn có thể nhấn chuột phải một phương pháp trong Visual Studio> NDepend> Chọn phương pháp ...> đang sử dụng tôi (trực tiếp hoặc gián tiếp) ...

NDepend Visual Studio method right click

Truy vấn mã sau đây được tạo ra. ..

from m in Methods 
let depth0 = m.DepthOfIsUsing("NUnit.Framework.Constraints.ConstraintExpression.Property(String)") 
where depth0 >= 0 orderby depth0 
select new { m, depth0 } 

... khớp với người gọi trực tiếp và gián tiếp, với độ sâu cuộc gọi (1 nghĩa là người gọi trực tiếp, 2 có nghĩa là người gọi trực tiếp, v.v.).

NDepend indirect method callers

Và sau đó bằng cách nhấn vào nút Export để vẽ đồ thị, bạn sẽ có được một đồ thị cuộc gọi của phương pháp pivot của bạn (tất nhiên nó có thể là cách khác xung quanh, tức là phương pháp được gọi là trực tiếp hoặc gián tiếp bởi một đặc biệt phương pháp pivot).

NDepend call graph

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