Thực hành tốt nhất để sử dụng không gian tên trong C ++ [đã đóng]


38

Tôi đã đọc Bác Bob Mã sạch cách đây vài tháng, và nó đã có ảnh hưởng sâu sắc đến cách mã tôi viết. Ngay cả khi có vẻ như anh ta đang lặp lại những điều mà mọi lập trình viên nên biết, việc đặt tất cả chúng lại với nhau và đưa chúng vào thực tế sẽ dẫn đến mã sạch hơn nhiều. Cụ thể, tôi thấy việc chia nhỏ các hàm lớn thành nhiều hàm nhỏ và chia các lớp lớn thành nhiều lớp nhỏ trở nên vô cùng hữu ích.

Bây giờ cho câu hỏi. Các ví dụ của cuốn sách đều bằng Java, trong khi tôi đã làm việc trong C ++ trong nhiều năm qua. Làm thế nào các ý tưởng trong Clean Code sẽ mở rộng đến việc sử dụng các không gian tên không tồn tại trong Java? (Vâng, tôi biết về các gói Java, nhưng nó không thực sự giống nhau.)

Liệu nó có ý nghĩa để áp dụng ý tưởng tạo ra nhiều thực thể nhỏ, mỗi thực thể có trách nhiệm được xác định rõ ràng, cho các không gian tên? Một nhóm nhỏ các lớp liên quan có nên luôn được bọc trong một không gian tên? Đây có phải là cách để quản lý sự phức tạp của việc có nhiều lớp nhỏ, hoặc chi phí quản lý nhiều không gian tên sẽ bị cấm?

Chỉnh sửa: Câu hỏi của tôi được trả lời trong mục Wikipedia này về Nguyên tắc Gói .


7
Một ví dụ khác về một câu hỏi hay, và nhà phát triển trong thế giới thực đã đóng lại . Nếu đây không phải là trang web stackexchange để hỏi về các thực tiễn tốt nhất của nhà phát triển, thì đó là gì?
Sam Goldberg

@SamGoldberg: nó trở nên tốt hơn. Tôi tìm thấy một câu trả lời tốt cho câu hỏi này ở đây: en.wikipedia.org/wiki/Package_Principles . Tôi đã đăng câu trả lời này và một người điều hành đã xóa nó, bởi vì tôi chỉ đăng liên kết và không có thời gian để sao chép / dán nội dung.
Dima

1
Tôi nghĩ rằng bài phê bình duy nhất của tôi về câu hỏi sẽ là, thay vì hỏi nhiều câu hỏi ở cuối, hãy thử tóm tắt nó thành một câu hỏi duy nhất, ví dụ: "tiêu chí nào nên được xác định trong cùng một không gian tên hoặc không gian tên khác nhau? ".
Sam Goldberg

Câu trả lời:


22

(Tôi chưa đọc Mã sạch và không biết nhiều về Java.)

Liệu nó có ý nghĩa để áp dụng ý tưởng tạo ra nhiều thực thể nhỏ, mỗi thực thể có trách nhiệm được xác định rõ ràng, cho các không gian tên?

Vâng, giống như nó làm với tái cấu trúc thành nhiều lớp và nhiều hàm.

Một nhóm nhỏ các lớp liên quan có nên luôn được bọc trong một không gian tên?

Không thực sự trả lời: có, ít nhất bạn nên sử dụng một không gian tên cấp cao nhất. Điều này có thể dựa trên dự án, tổ chức hoặc bất cứ điều gì bạn thích, nhưng sử dụng một vài tên toàn cầu sẽ làm giảm xung đột tên. Một không gian tên duy nhất để nhóm mọi thứ khác theo nó chỉ giới thiệu một tên toàn cầu. (Ngoại trừ các chức năng "C" bên ngoài, nhưng đó là do khả năng tương tác của C và chỉ ảnh hưởng đến các chức năng "C" bên ngoài khác.)

Một nhóm nhỏ các lớp liên quan có nên được bọc trong một không gian tên dành riêng cho chúng không? Có lẽ. Đặc biệt nếu bạn thấy mình sử dụng tiền tố phổ biến trên các lớp đó - FrobberThing, FrobberThang, FrobberDoohickey - bạn nên xem xét một không gian tên - frobber :: Thing, v.v. Điều này vẫn sẽ nằm trong không gian tên gốc của bạn hoặc không gian tên khác nếu chúng là một phần của dự án lớn hơn.

Đây có phải là cách để quản lý sự phức tạp của việc có nhiều lớp nhỏ, hoặc chi phí quản lý nhiều không gian tên sẽ bị cấm?

Lấy ví dụ ở trên về các tên tiền tố, việc quản lý frobber :: Thing so với FrobberThing không khó hơn. Nó thậm chí có thể dễ dàng hơn với một số công cụ, chẳng hạn như hoàn thành tài liệu và mã. Có một sự khác biệt với ADL, nhưng điều này có thể có lợi cho bạn: ít tên hơn trong các không gian tên được liên kết làm cho ADL đơn giản hơn để tìm ra và bạn có thể sử dụng khai báo để tiêm tên cụ thể vào không gian tên này hoặc không gian tên khác.

Các bí danh không gian tên cho phép bạn sử dụng một tên ngắn hơn cho một không gian tên dài hơn trong một ngữ cảnh cụ thể, một lần nữa cho phép sử dụng dễ dàng hơn:

void f() {
  namespace CWVLN = Company_with_very_long_name;  // Example from the standard.
  // In this scope, use CWVLN::name instead of Company_with_very_long_name::name.
  namespace fs = boost::filesystem;  // Commonly used.
}

Hãy xem xét Boost, có một không gian tên gốc duy nhất, boost, và sau đó là nhiều tên con - boost :: asio, boost :: io, boost :: filesystem, boost :: tuples, v.v. - cho các thư viện khác nhau. Một số tên được "thăng cấp" vào không gian tên gốc:

Tất cả các định nghĩa đều nằm trong không gian tên :: boost :: tuples, nhưng các tên phổ biến nhất được nâng lên không gian tên :: boost bằng cách sử dụng khai báo. Những tên này là: tuple, make_tuple, tie và get. Hơn nữa, ref và cref được định nghĩa trực tiếp trong không gian tên :: boost.

Sự khác biệt lớn nhất so với các ngôn ngữ với các mô-đun "thực" là mức độ phổ biến của việc sử dụng cấu trúc phẳng hơn, điều này chủ yếu xảy ra bởi vì đó là cách nó hoạt động trừ khi bạn mất thêm nỗ lực cụ thể để xác định tên lồng nhau.


+1 @Fred Nurk để phân tích đầy đủ thay vì một câu trả lời. Bạn không cần phải đọc cuốn sách để biết câu hỏi đó là gì. Chủ đề bình luận này cho thấy các khái niệm và sự khác biệt mà một lập trình viên C ++ và Java có thể có trên cuốn sách này. Nhận xét mã sạch trong Amazon
Marlon

8

Bạn nên có một không gian tên chính cho tất cả mã của bạn. Điều này phân biệt nó với mã bên ngoài liên quan đến không gian tên.

Trong không gian tên chính của bạn, tùy thuộc vào kích thước và độ phức tạp, bạn có thể mở các không gian tên phụ. Đây là nơi tên rõ ràng có nghĩa là một cái gì đó trong một bối cảnh và các tên tương tự có thể được sử dụng trong một bối cảnh khác.

Cụ thể, nếu bạn có một tên âm chung như FileInfo có nghĩa là một cái gì đó cụ thể trong một ngữ cảnh, hãy đặt nó trong một không gian tên.

Bạn cũng có thể sử dụng một lớp cho việc này, mặc dù một lớp không thể mở rộng để bạn không thể thêm các khai báo mới vào lớp mà không sửa đổi tiêu đề của nó.


3

Không gian tên không phải là một khái niệm Mô-đun, vì vậy tôi sẽ chỉ sử dụng chúng khi có thể xảy ra xung đột tên.


4
Không chắc chắn những gì bạn có ý nghĩa. Tại sao một tập hợp các lớp liên quan được bọc trong một không gian tên sẽ không phải là một mô-đun?
Dima

Không có hạn chế trong không gian tên. Trong một mô-đun, bạn có thể nói rằng một lớp, hàm hoặc biến đã cho chỉ có thể được truy cập từ bên trong mô-đun. Trong một không gian tên, điều này là không thể, nó chỉ là tiền tố của tên.
Brainlag

3
Có vẻ như chúng tôi không đồng ý về định nghĩa của một mô-đun . Đối với tôi bất cứ điều gì mà các nhóm thực thể liên quan với nhau và có một tên mô tả là một mô-đun, bất kể khô héo hay không, nó cung cấp đóng gói.
Dima

3
Hạn chế truy cập là trực giao với các mô-đun. Trên thực tế, bạn có các hệ thống thành công như Python chắc chắn là "giống như mô-đun" hơn các không gian tên của C ++, nhưng không áp dụng bất kỳ hạn chế truy cập nào.
Fred Nurk

Tôi tin rằng đây là một trong những thực tiễn tốt nhất được liệt kê trên sách của Scott Meyer
Raphael

1

Java có các không gian tên, chúng thực sự không được gọi như vậy. Trong javax.swing.* javaxlà một không gian tên và swinglà một không gian tên phụ. Tôi chưa đọc cuốn sách để biết những gì nó nói về các gói java, nhưng các nguyên tắc tương tự sẽ áp dụng khá nhiều trực tiếp vào không gian tên trong bất kỳ ngôn ngữ nào.

Một heuristic tốt là bạn sử dụng một không gian tên khi bạn thấy mình muốn gõ cùng một tiền tố cho các lớp nhiều lần. Ví dụ, gần đây tôi đã viết một số lớp có tên OmciAttribution, OmciAlarm, OmciMe, v.v. và nhận ra rằng tôi cần phải chia Omci vào không gian tên của chính nó.


1

Tôi thích không gian tên sâu (thường có nghĩa là ba cấp độ).

  • Tôi có tên công ty.
  • ứng dụng / produc / lib / etc
  • Tên dự án / hoặc Gói phù hợp

Tùy thuộc vào tình huống tôi có thể có thêm một cấp độ

  • chi tiết (Chi tiết triển khai cụ thể nền tảng)
  • utils (đối tượng tiện ích chưa được chuyển sang tiện ích chung).
  • bất cứ điều gì tôi cần.
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.