Một cách tốt để hiểu cấu trúc tổng thể của một cơ sở mã là gì?


8

Đôi khi nó rất hữu ích trong công việc của tôi để sửa đổi mã nguồn mở của người khác hoặc tìm ra cách phát triển những thứ cụ thể cho ứng dụng của riêng bạn. Tuy nhiên, không phải tất cả các phần mềm đều có tài liệu tốt.

Một cách tốt để hiểu cấu trúc tổng thể của một cơ sở mã là gì?

Ví dụ: thường gọi các thói quen nào, v.v. Tôi có thể sử dụng một công cụ tài liệu như Doxygen cho mục đích này, tuy nhiên, tôi đã tự hỏi liệu có chiến lược nào tốt hơn không?


5
Tôi nghĩ rằng đây là một câu hỏi hợp lý để hỏi, nhưng tôi cũng nghĩ rằng có lẽ nên hỏi về lập trình viên. Thay vào đó; nó không hoàn toàn là khoa học tính toán, mà là lập trình nhiều khái niệm hơn.
Geoff Oxberry

2
Có các kỹ thuật để làm điều này là cụ thể cho các mã khoa học?
David Ketcheson

Tôi sử dụng Doxygen vì nó dễ dàng và có thể đưa ra những bức ảnh đẹp với các biểu đồ cho thấy cách các thói quen được kết nối. Lưu ý rằng có thể cần phải tạo một thói quen chính bao gồm tất cả mọi thứ để có được một bức tranh đầy đủ như vậy.
Allan P. Engsig-Karup

@DavidKetcheson: Tôi không nghĩ có những phương pháp để thực hiện điều này cụ thể cho các mã khoa học. Với truyền thống mạnh mẽ của các mã nghiên cứu không có giấy tờ, có lẽ nên có.
Geoff Oxberry

Câu trả lời:


9

Các chủ đề sau có liên quan tiếp tuyến:

Đối với phần đầu tiên của luận án, tôi đã dành 18 tháng để sửa đổi mã Fortran không có giấy tờ và một trong những nhiệm vụ đầu tiên là thử và hiểu cấu trúc tổng thể của một cơ sở mã. Điều quan trọng nhất tôi khuyên bạn nên làm là ghi chú trong tệp văn bản bất cứ khi nào bạn phát hiện ra điều gì đó. Bạn không muốn phải học lại hoặc khám phá lại mọi thứ trong quá trình tốn thời gian và bực bội này.

Trong trường hợp của tôi, không có "API" nào để nói, trong đó các đối số của các hàm không tự ghi lại, bởi vì lập trình viên trước đó đã sử dụng kiểu giống Fortran 77, và do đó, các định danh ngắn mà không có chút gợi ý nào. ý họ là. Không có bài kiểm tra nào, và vì đó là Fortran, không có tiêu đề. Thêm nhiều niềm vui hơn vào hỗn hợp, có một vài chức năng ở đây và được viết bằng C hoặc C ++.

Những điều làm việc cho tôi (giả sử bạn làm việc trong Linux):

  • grep. Học cách yêu thương grep; bạn sẽ sử dụng nó trong trình bao để tìm nơi các hàm được khai báo và gọi và đầu ra sẽ cho bạn biết những tập tin nào cần tìm.
  • Lệnh "find" trong trình soạn thảo mã hoặc IDE yêu thích của bạn. Khi bạn biết tập tin nào cần tìm, lệnh "find" sẽ giúp bạn tiết kiệm thời gian tìm kiếm các cuộc gọi chức năng.
  • Tái cấu trúc mạnh mẽ, nếu bạn có thể thay đổi cơ sở mã. Tôi đã tự đặt tên biến thành tài liệu để không phải tốn công sức tinh thần để học lại những thứ tôi đã tìm ra. Tôi cũng sắp xếp hợp lý thiết kế mã khi tôi tìm ra nó để nó bớt khó hiểu hơn. Không có hơn 1000 dòng chương trình chính dài!
  • Bình luận tích cực. Một lần nữa, nếu bạn có thể thay đổi cơ sở mã, hãy bình luận mọi thứ để bạn biết những gì bạn đã tìm ra. Tôi đã không sử dụng Doxygen, nhưng Doxygen tốt cho việc này.
  • nm. Nó có thể hữu ích trên các thư viện nếu bạn không có mã nguồn cho chúng, nhưng muốn biết liệu một chức năng bạn gặp phải có trong thư viện đó không. Tuy nhiên, nó chỉ hoạt động nếu các biểu tượng của thư viện chưa bị tước.
  • Bước qua mã với trình gỡ lỗi. Đó là cách hiệu quả hơn so với sử dụng printbáo cáo. dddgdbrất tuyệt, và trên hầu hết mọi hệ thống Linux ngoài kia. Hãy sử dụng trình gỡ lỗi yêu thích của bạn.
  • Lỗi các nhà phát triển. Tùy chọn này thực sự tốt nhất cho các câu hỏi rất nhắm mục tiêu. Nếu bạn đến gặp họ (như tôi đã làm) và nói: "Tôi không hiểu chuyện gì đang xảy ra ở đây", họ có thể thương hại bạn và cố gắng giải thích mọi thứ một cách chi tiết, nhưng điều đó sẽ bị hạn chế sử dụng Về lâu dài. Bạn sẽ phải làm việc chân tay, bởi vì các nhà phát triển đã không làm điều đó cho bạn trong việc viết tài liệu và giải thích cấu trúc cơ sở mã của họ bằng văn bản. Các nhà phát triển thực sự tốt khi bạn thực sự bị mắc kẹt trong những điều nhỏ nhặt (nếu họ nhớ những gì họ đã làm).

Những điều tôi muốn tôi nghĩ đến sớm hơn, hoặc chỉ là những lựa chọn không phù hợp với tôi:

  • Doxygen. Nếu bạn điều chỉnh các tùy chọn Doxyfile, Doxygen sẽ tự động tạo ra rất nhiều tài liệu cho bạn, ngay cả khi không có cú pháp nhận xét Doxygen đặc biệt, có thể là một nơi tốt để bắt đầu; Tôi đã sử dụng điều này cho các dự án sau này tôi gặp phải và nó rất hữu ích.
  • Kiểm tra đơn vị. Nếu bạn có thể thay đổi cơ sở mã và bạn có một số ý tưởng về những gì nó phải làm, hãy viết các bài kiểm tra đơn vị cho các chức năng khác nhau. (Đó là một kỹ năng hữu ích để nhận bất kể.)
  • Nếu bạn đang làm việc với C / C ++, hãy xem các tiêu đề.
  • Viết chương trình ví dụ. Không phải là một lựa chọn cho tôi trong dự án Fortran đó, nhưng nó hữu ích cho tôi trong việc chọn API của bên thứ ba. Ngoài ra, nhìn vào các chương trình ví dụ của họ , nếu họ có bất kỳ.
  • Sử dụng gcovlcovđể thực hiện phân tích bảo hiểm về các lần chạy mã điển hình, nếu bạn có ví dụ hoặc thực thi để làm việc. Nếu có các ví dụ được cho là thực thi các phần lớn của cơ sở mã, hai công cụ này được kết hợp sẽ cho bạn biết số lần mỗi dòng mã được truy cập. Nó hữu ích nhất với cờ gỡ lỗi được kích hoạt. Nếu một phần của mã không được truy cập ở tất cả, có lẽ việc hiểu nó ngay lập tức ít quan trọng hơn. Nếu một phần của mã được truy cập nhiều, có lẽ bạn nên hiểu nó là gì. Có thể mã được thực thi rất nhiều vì đó là một vòng lặp không quan trọng hoặc nó có thể là một hàm chính mà rất nhiều hàm khác dựa vào. Bạn không thể chỉ nói về phân tích bảo hiểm, nhưng phân tích bảo hiểm cung cấp cho bạn một số ý tưởng về nơi tập trung thời gian của bạn.
  • Các công cụ phân tích mã tĩnh như splintcó thể cho bạn biết nếu một cái gì đó tanh đang xảy ra trong mã, như một số biến không bao giờ được sử dụng.
  • Hồ sơ. Một lần nữa, cung cấp cho bạn dữ liệu không ngay lập tức cho bạn biết điều gì là quan trọng hoặc không quan trọng, nhưng gợi ý những gì có thể quan trọng. Nếu nhiều thời gian CPU dành cho việc gọi một chức năng, bạn có thể muốn xem xét điều đó và xem nó làm gì. Bạn cũng có thể sử dụng đầu ra định hình với dotgraphvizđể tạo biểu đồ cuộc gọi và xem số lần gọi các hàm, như phân tích vùng phủ sóng. Đối với các mã phức tạp, một phân tích đồ họa có thể hữu ích hơn rất nhiều.
  • Nếu bạn đang làm việc tại C, Frama-C được cho là hữu ích trong việc phân tích mã, nhưng tôi chưa bao giờ sử dụng nó vì nó có vẻ quá phức tạp không đáng để bỏ công sức. Tôi làm một số công việc trong C thuần túy, nhưng chủ yếu là mã mà tôi viết; Tôi chưa bao giờ làm việc với mã C không có giấy tờ.

2
Cách hiểu phổ biến nhất về một ứng dụng C ++ rất lớn là gì? trên Stack Overflow là C ++ cụ thể, nhưng một câu hỏi khác hiện có về một số cổ vật.
dmckee --- ex-moderator mèo con

Danh sách tốt đẹp. Tôi đặt mọi thứ vào git và sử dụng "git grep". Và lịch sử git cho các tệp riêng lẻ, nếu có sẵn.
Ondřej Čertík

3

Tôi luôn bảo học sinh của mình đọc mã từ dưới lên: bạn bắt đầu bằng hàm main () và xem nó gọi là gì. Thông thường, đây chỉ là một số ít chức năng. Sau đó, bạn xem xét các hàm được gọi từ hàm main () thường xác định luồng tổng thể của thuật toán (vòng lặp thời gian, lắp ráp, bộ giải, đầu ra, v.v.). Đi sâu hơn hai cấp để có cái nhìn tổng quan về thuật toán từ 30.000 ft. Phần còn lại thường có thể được lượm lặt từ tài liệu doxygen, v.v.

Nhưng như tôi đã nói, thông báo là: Đọc mã từ dưới lên.


3
Lời khuyên của bạn được thực hiện tốt, nhưng không giống như đọc mã từ dưới lên. Thay vào đó, nó có vẻ như đọc từ trên xuống. Main () (hoặc Chương trình, trong Fortran) là đơn vị chương trình hàng đầu nhất trong một mã thực thi. Hơn nữa, lời khuyên của bạn yêu cầu một chút điều chỉnh khi mã được đề cập là một thư viện xác định API. Không có hàm main (), trong trường hợp đó bạn phải kết hợp chiến lược của mình để xem hàm nào gọi với quyết định hàm nào quan trọng với bạn, thường là bằng cách xem (hoặc mã hóa) các chương trình ví dụ.
Geoff Oxberry

Có thể có một số nhầm lẫn về "từ dưới lên" bởi vì các lập trình viên đã học Pascal sớm thường đặt điểm vào ở cuối (hoặc dưới cùng) của tệp --- vì Pascal chỉ thực hiện một lần và mọi thứ phải được giới thiệu trước nó được gọi là. Tuy nhiên, giống như Geoff, tôi thích logic hơn trong đó Main () nằm ở "đỉnh" nổi tiếng của một cây mọc xuống.
dmckee --- ex-moderator mèo con

Vâng, tôi có nghĩa là cách của dmckee có main () ở cuối tệp vì người ta sẽ phải tuyên bố trước mọi thứ.
Wolfgang Bangerth
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.