Các quy ước đặt tên được sử dụng cho các biến và hàm trong C [đã đóng]


12

Trong khi mã hóa một dự án lớn ở CI đã gặp phải một vấn đề. Nếu tôi tiếp tục viết thêm mã thì sẽ có lúc tôi gặp khó khăn trong việc tổ chức mã. Tôi có nghĩa là việc đặt tên cho các hàm và biến cho các phần khác nhau của chương trình có thể bị lẫn lộn.

Vì vậy, tôi đã suy nghĩ liệu có những quy ước đặt tên hữu ích mà tôi có thể sử dụng cho các biến và hàm C không?

Hầu hết các ngôn ngữ đề nghị một quy ước đặt tên. Nhưng đối với C, điều duy nhất tôi đã đọc cho đến nay là các tên nên được mô tả cho khả năng đọc mã.

BIÊN TẬP:

Ví dụ về một số ví dụ về các quy ước đặt tên được đề xuất:

Tôi đọc thêm một số quy ước đặt tên cho java ở đâu đó nhưng không thể nhớ ở đâu.


Trích dẫn một số ví dụ về các ngôn ngữ với các quy ước đặt tên được đề xuất. Và nơi chúng ta có thể tìm thấy những quy ước đặt tên.
Philip

@Philip Đã thêm ví dụ
Aseem Bansal

1
Không nên có vấn đề với các biến khi bạn không sử dụng toàn cầu. Và đối với tên hàm: nếu tên của mô-đun là order.c, bạn có thể đặt tên cho các hàmorder_add() , order_del()v.v. Có thể có các hệ thống cũ cho bạn biết rằng tên phải là duy nhất trong 8 ký tự đầu tiên. Khi bạn chuyển sang c ++ sau một cách tình cờ, bạn sẽ thích viết order::add()order::del()sau đó.
ott--

Câu trả lời:


17

Nếu tôi tiếp tục viết thêm mã thì sẽ có lúc tôi gặp khó khăn trong việc tổ chức mã.

Đây là vấn đề của bạn: làm cho tổ chức phù hợp và phong cách sẽ dễ dàng trôi chảy hơn.

Đừng chờ đợi để tổ chức mã của bạn: giữ cho mã của bạn được tổ chức khi bạn đi. Mặc dù ngôn ngữ không làm điều đó cho bạn, mã vẫn nên được tổ chức thành các mô-đun với độ khớp thấp và độ gắn kết cao.

Các mô-đun sau đó tự nhiên cung cấp một không gian tên. Viết tắt tên mô-đun (nếu dài) và tên hàm tiền tố với mô-đun của chúng để tránh va chạm.

Ở cấp độ định danh cá nhân, đây là khoảng thứ tự tăng tính chủ quan:

  1. chọn một quy ước và gắn bó với nó
    • ví dụ, function_like_this(struct TypeLikeThis variable)là phổ biến
  2. chắc chắn tránh ký hiệu Hungary (xin lỗi JNL)

    • trừ khi bạn sẵn sàng sử dụng nó như dự định ban đầu, điều đó có nghĩa là ký hiệu ứng dụng của Simony thay vì phiên bản hệ thống khủng khiếp

      Tại sao? Tôi có thể viết một bài luận về điều này, nhưng thay vào đó tôi sẽ đề nghị bạn đọc bài viết này của Joel Spolsky, và sau đó săn lùng thêm một số nếu bạn quan tâm. Có một liên kết đến giấy gốc của Simonyi ở phía dưới.

  3. tránh con trỏ typedefs trừ khi chúng thực sự là loại cookie mờ - chúng chỉ gây nhầm lẫn mọi thứ

    struct Type *ok;
    typedef struct Type *TypePtr;
    TypePtr yuck;

    Ý tôi là gì bởi một loại cookie mờ ? Ý tôi là một cái gì đó được sử dụng bên trong một mô-đun (hoặc thư viện hoặc bất cứ thứ gì) phải được chuyển cho mã máy khách, nhưng mã máy khách đó không thể sử dụng trực tiếp. Nó chỉ cần chuyển nó trở lại thư viện.

    Ví dụ: thư viện cơ sở dữ liệu có thể hiển thị giao diện như

    /* Lots of buffering, IPC and metadata magic held in here.
       No, you don't get to look inside. */
    struct DBContextT;
    /* In fact, you only ever get a pointer, so let's give it a nice name */
    typedef struct DBContexT *DBContext;
    
    DBContext db_allocate_context(/*maybe some optional flags?*/);
    void db_release_context(DBContext);
    int db_connect(DBContext, const char *connect);
    int db_disconnect(DBContext);
    int db_execute(DBContext, const char *sql);

    Bây giờ, bối cảnh mờ đục đối với mã máy khách, vì bạn không thể nhìn vào bên trong. Bạn chỉ cần chuyển nó trở lại thư viện. Một cái gì đó giống như FILElà mờ đục, và một mô tả tập tin số nguyên cũng là một cookie , nhưng không phải là mờ.


Một lưu ý về thiết kế

Tôi đã sử dụng cụm từ khớp nối thấp và độ gắn kết cao ở trên mà không có lời giải thích, và tôi cảm thấy một chút xấu về điều đó. Bạn có thể tìm kiếm nó và có thể tìm thấy một số kết quả tốt, nhưng tôi sẽ cố gắng giải quyết ngắn gọn (một lần nữa, tôi có thể viết một bài luận nhưng sẽ cố gắng không).

Thư viện DB được phác thảo ở trên cho thấy khả năng ghép thấp vì nó phơi bày một giao diện nhỏ với thế giới bên ngoài. Bằng cách ẩn các chi tiết triển khai của nó (một phần với thủ thuật cookie mờ), nó ngăn chặn mã máy khách đến phụ thuộc vào các chi tiết đó.

Hãy tưởng tượng thay vì cookie mờ, chúng tôi khai báo cấu trúc bối cảnh để nội dung của nó hiển thị và bao gồm một mô tả tệp ổ cắm cho kết nối TCP đến cơ sở dữ liệu. Nếu sau đó chúng tôi thay đổi việc triển khai để hỗ trợ sử dụng phân đoạn bộ nhớ dùng chung khi DB đang chạy trên cùng một máy, máy khách cần được biên dịch lại thay vì chỉ được liên kết lại. Thậm chí tệ hơn, máy khách có thể đã bắt đầu sử dụng bộ mô tả tệp, ví dụ như gọi setsockoptđể thay đổi kích thước bộ đệm mặc định và bây giờ nó cũng cần thay đổi mã. Tất cả các chi tiết này nên được ẩn bên trong mô-đun của chúng tôi, nơi thực tế và điều này mang lại sự khớp nối thấp giữa các mô-đun.

Ví dụ này cũng cho thấy sự gắn kết cao , trong đó tất cả các phương thức trong mô-đun đều liên quan đến cùng một tác vụ (truy cập DB). Điều này có nghĩa là chỉ có mã cần biết về các chi tiết triển khai (nghĩa là nội dung của cookie của chúng tôi) thực sự có quyền truy cập vào chúng, giúp đơn giản hóa việc gỡ lỗi.

Bạn cũng có thể thấy rằng có một mối quan tâm duy nhất giúp bạn dễ dàng chọn tiền tố để nhóm các chức năng này lại với nhau.

Bây giờ, nói ví dụ này là tốt là dễ dàng (đặc biệt là vì nó thậm chí chưa hoàn thành), nhưng ngay lập tức không giúp bạn. Mẹo nhỏ là hãy xem, khi bạn viết và mở rộng mã của mình, cho các hàm làm những việc tương tự hoặc hoạt động trên cùng loại (có thể là ứng cử viên cho mô-đun của riêng chúng) và cũng cho các hàm thực hiện nhiều điều riêng biệt phát sinh ' t thực sự liên quan, và có thể là ứng cử viên để chia tách.


Bạn có thể giúp tôi hiểu tại sao Hungary tránh? Chỉ tò mò muốn biết thêm về nó. :)
JNL

@JNL: Một nhận xét quá ngắn để giải thích chính xác. Tôi đề nghị bạn đăng nó như một câu hỏi mới.
Bart van Ingen Schenau

with low coupling and high cohesion. Điều đó nghĩa là gì? Và hãy giải thích về các loại cookie mờ. Tôi không có ý tưởng gì đó có nghĩa.
Aseem Bansal

Tôi đã cố gắng giải quyết ngắn gọn cả hai, và thẳng thắn thất bại. Hy vọng nó sẽ giúp bạn bắt đầu mặc dù.
Vô dụng

Tôi đang trả lời sau vài ngày. Xin lỗi vì điều đó. Tôi đọc mô tả của bạn về low coupling and high cohesion. Vì vậy, về cơ bản nó có nghĩa là gói gọn mọi thứ khi tôi có thể và nó nên được thực hiện theo cách mà các chức năng thực sự cần phải có quyền truy cập. Một số điều đã đi qua đầu tôi nhưng tôi vẫn nghĩ rằng tôi đã nhận được điểm của bạn.
Aseem Bansal

5

Theo tôi, 90% vấn đề đặt tên được giải quyết nếu bạn ghi nhớ ba điều sau: a) làm cho tên biến và tên hàm của bạn càng mô tả càng tốt, b) nhất quán trong toàn bộ mã của bạn (nghĩa là, nếu một hàm được đặt tên là addNumbers, a Hàm thứ hai nên được đặt tên là bội số và không phải là sốMul) và c) cố gắng đặt tên ngắn nếu có thể, vì chúng ta cần nhập chúng.

Điều đó đang được nói nếu bạn muốn xem xét các khía cạnh khác về chủ đề này, trang Wikipedia về Quy ước đặt tên có một danh sách tốt về những điều bạn nên ghi nhớ. Nó cũng có một phần trên C và C ++:

Trong C và C ++, từ khóa và định danh thư viện chuẩn chủ yếu là chữ thường. Trong thư viện chuẩn C, tên viết tắt là phổ biến nhất (ví dụ: isalnum để kiểm tra chức năng cho dù một ký tự là chữ và số), trong khi thư viện chuẩn C ++ thường sử dụng dấu gạch dưới làm dấu tách từ (ví dụ: out_of_range). Các định danh đại diện cho các macro, theo quy ước, được viết chỉ sử dụng chữ in hoa và dấu gạch dưới (điều này có liên quan đến quy ước trong nhiều ngôn ngữ lập trình sử dụng định danh toàn chữ hoa cho các hằng số). Các tên chứa dấu gạch dưới kép hoặc bắt đầu bằng dấu gạch dưới và chữ in hoa được dành riêng để thực hiện (trình biên dịch, thư viện chuẩn) và không nên được sử dụng (ví dụ: reserved__ hoặc _Reserved). [5] [6] Điều này bề ngoài tương tự như vuốt, nhưng ngữ nghĩa khác nhau:


3
"Cố gắng rút ngắn tên nếu có thể" Sử dụng IDE có tự động hoàn thành, sau đó tên hàm của bạn có thể dài và mô tả khi chúng cần chỉ cần gõ một lần.
Joel

1
@Joel lời khuyên khủng khiếp. Không phải ai cũng sẽ sử dụng IDE giống như bạn.
James

6
@James Họ không cần, họ chỉ có thể sử dụng bất kỳ IDE phong nha nào. Sau đó, bạn không phải hy sinh sự rõ ràng cho năng suất.
Joel

Thuật ngữ IDE được kéo dài một chút mỏng bây giờ một ngày. Về mặt kỹ thuật Notepad ++ là một IDE vì bạn có thể cấu hình nó để biên dịch và chạy dự án của bạn, nhưng chủ yếu nó là một trình soạn thảo văn bản. Và nó tự động hoàn thành.
Philip

5

Hạn chế cứng duy nhất trong C là không có không gian tên. Do đó, bạn phải tìm cách làm cho rename()chức năng của thư viện hệ thống tập tin của bạn khác với rename()chức năng của thư viện phương tiện . Giải pháp thông thường là tiền tố, chẳng hạn như: filesystem_rename()media_rename().

Lời khuyên chung khác là: hãy kiên định trong một dự án hoặc một nhóm. Khả năng đọc sẽ được cải thiện.


+1: Điều đó đặc biệt đúng đối với các biểu tượng được xuất trong thư viện. "Tôi xin lỗi, nhưng thư viện hệ thống tập tin đó không đi cùng với thư viện phương tiện đó, vì cả hai đều có chức năng đổi tên.
Residuum

2

NẾU BẠN ĐANG TÌM KIẾM MỘT HÌNH THỨC ĐƯỢC CHẤP NHẬN TOÀN CẦU

MISRA / JSF / AUTOSAR bao gồm gần 100% bất kỳ và mọi tiêu chuẩn ngành để đặt tên và tổ chức mã C / C ++. Vấn đề là họ sẽ không được miễn phí để nắm giữ, tức là mỗi cuốn sách hướng dẫn đều tiêu tốn một số tiền. Tôi biết rằng cuốn sách tiêu chuẩn mã hóa MISRA 2008 C / C ++ có thể có giá khoảng 50 USD.

Bạn có thể nghĩ về những điều này như Tài liệu tham khảo của Harvard cho thư mục và đọc thêm khi bạn viết một tạp chí. Tôi đã sử dụng MISRA và đó là một cách hay để đặt tên cho các hàm và biến của bạn và sắp xếp chúng để sử dụng đúng cách.

NẾU BẠN ĐANG TÌM KIẾM TẠM THỜI

Các tài liệu tham khảo bạn cung cấp cho Python và Java đều ổn, tôi đoán vậy. Tôi đã thấy mọi người chấp nhận bình luận theo kiểu javadoc, đặt tên và tổ chức mã. Như một vấn đề thực tế, trong dự án cuối cùng của tôi, tôi đã phải viết mã C ++ bằng các hàm / tên biến giống như Java. Hai lý do đằng sau điều này:

1) Rõ ràng là dễ theo dõi hơn.

2) Các yêu cầu về mã sản xuất không chạm đến các tiêu chuẩn hệ thống phần mềm quan trọng an toàn.

3) Mã kế thừa (bằng cách nào đó) ở định dạng đó.

4) Doxygen cho phép bình luận tinh tế Javadoc. Vào lúc đó, chúng tôi đang sử dụng doxygen để tạo tài liệu cho những người sản xuất.

Nhiều lập trình viên sẽ là đối thủ của điều này, nhưng cá nhân tôi cho rằng không có gì sai khi áp dụng hàm kiểu javadoc / đặt tên biến trong C / C ++. CÓ KHÓA HỌC, các phương thức tổ chức kiểm soát dòng chảy, an toàn luồng, v.v ... cần được giải quyết bất kể. Tuy nhiên, tôi không phải là người nộp đơn ở đây. Tôi cũng không biết các yêu cầu định dạng mã sản xuất của bạn nghiêm ngặt đến mức nào. Không chuyển hướng nó sang một khu vực ngoài chủ đề, tôi khuyên bạn nên xem lại các yêu cầu của mình, tìm hiểu xem bạn phụ thuộc vào một quy ước đặt tên cụ thể như thế nào và đi đến một giải pháp được đề cập trong câu trả lời của tôi và của người khác

Hy vọng điều này sẽ giúp!?


Trên thực tế tôi đã yêu cầu điều này cho mã C cá nhân. Nhưng tôi sẽ nhớ đề nghị của bạn.
Aseem Bansal

@AseemBansal Cá ​​nhân hoặc chuyên nghiệp, những người tốt để học và cũng tốt để đưa vào CV của bạn :) .... Tùy bạn.
hagubear

0

Vài điều quan trọng cần được xem xét trong khi đặt tên sẽ là;

  1. Nhìn vào loại actionObject hoặc ObjectAction. (Đối tượng không dành cho C. Nhưng nói chung khi bạn đi đến các ngôn ngữ hướng đối tượng khác) Điều này sẽ giúp

  2. Phần còn lại sẽ là SỰ TIN TƯỞNG, ngắn gọn và mô tả cho chắc chắn.

  3. Ngoài ra, có một mục đích duy nhất của mọi biến và hàm được xác định, Ví dụ: Nếu tạm thời lưu trữ một giá trị, hãy đặt tên là nTempVal cho int
  4. Các biến nên là danh từ và Phương thức nên là động từ.

6
Ký hiệu Hungary (tiền tố một biến với các chữ cái biểu thị loại) dẫn đến không có kết thúc đau đớn. Nó đã may mắn đi ra khỏi thời trang.
Gort Robot

@StevenBurnap Chỉ tò mò tại sao tránh định dạng Hungary? Tôi tin rằng đó là những gì họ dạy chúng tôi ở trường và tôi cũng đã thấy mã như vậy ở một số nơi làm việc. Mà bạn muốn giới thiệu nếu không phải Hungary. Cảm ơn
JNL

1
Quy ước đặt tên tốt nhất chỉ là một quy tắc được sử dụng nhất quán, với các tên mô tả rõ ràng, lý tưởng được giữ tương đối ngắn mà không viết tắt quá nhiều và tránh các tiền tố dư thừa. Ký hiệu Hungary có ít tiện ích thực tế, làm cho mã khó đọc hơn và làm cho việc thay đổi loại khó hơn.
Gort Robot

2
Dưới đây là một mô tả về ý định ban đầu và sự ghê tởm mà ký hiệu Hungary đã trở thành: joelonsoftware.com/articles/Wrong.html
Residuum

@Residuum Đó là một liên kết tốt. Giúp rất nhiều. Cảm kích điều đó.
JNL

0

Hầu hết các câu trả lời đều tốt, nhưng tôi muốn nói một số điều về cách đặt tên cho các quy tắc và các tệp được bao gồm, tương tự như sử dụng không gian tên trong các ngôn ngữ khác như C ++ hoặc Java:

Nếu bạn xây dựng một thư viện, hãy tìm một tiền tố chung cho các ký hiệu được xuất của bạn, tức là các hàm toàn cục, typedefs và các biến. Điều này sẽ ngăn xung đột với các thư viện khác và xác định các chức năng đến từ bạn. Đây là một chút các ứng dụng ký hiệu Hungary.

Có thể đi xa hơn và nhóm các biểu tượng đã xuất của bạn: libcurl sử dụng curl_ * cho các biểu tượng toàn cầu, curl_easy_ *, curl_multi_ * và curl_share_ * cho các giao diện khác nhau. Vì vậy, ngoài việc sử dụng curl_ * cho tất cả các hàm, họ đã thêm một cấp độ "không gian tên" khác cho các giao diện khác nhau: gọi hàm curl_easy_ * trên hàm curl_multi_ * hiện có vẻ sai, xem tên hàm tại http: // curl. haxx.se/libcurl/c/

Giữ quy tắc cho các ký hiệu được xuất, bạn nên sử dụng các quy tắc cho các hàm tĩnh trong #includetệp ed: Cố gắng tìm tiền tố chung cho các hàm này. Có lẽ bạn có các hàm tiện ích chuỗi tĩnh trong một tệp có tên "my_opes"? Tiền tố tất cả các chức năng với my_opes_ *.


Bằng các ký hiệu được xuất, bạn có nghĩa là các biến toàn cục, hàm, typedefs, v.v. nếu tôi đúng. Bạn có thể giải thích một chút về việc nhóm các biểu tượng được xuất không? Tôi nghĩ bạn đã giải thích rằng trong đoạn trước. Bạn đã thêm gì vào đoạn 3?
Aseem Bansal
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.