архитектура — Пространства имен и упаковка в переполнении стека

Каков наилучший / самый чистый способ использования пространств имен в упакованном коде?

Например. в библиотеках как увеличение похоже, что управление пространствами имен очень организовано, используются некоторые методы, позволяющие устранить неоднозначность имен. Важная вещь, однако, заключается в том, что никто не увидит много кода, как

typedef namespace1::namespace2::sth_else::a_class<namespace3::namespace4::b_class> type;

как правило, между именами не так много пространства, что указывает на хорошую архитектуру, а также хорошее управление пространством имен. Вопрос в том, что такое хорошее управление пространством имен?

Скажем, у нас есть такая структура файлов:

component1/...  (depends on reusable_if)
component2/...  (depends directly on reusable_if and on component 1)
reusable/
reusable/some_part/
reusable/some_part/...
reusable/some_other_part/
reusable/some_other_part/...
reusable/SthThatUsesBothReusableParts.h   (implements reusable_if/ISth.h)
reusable/SthThatUsesBothReusableParts.cpp (implements reusable_if/ISth.h)
reusable_if/
reusable_if/ISth.h   (pure abstract class)
reusable_if/ISthElse.h (pure abstract class)
main.cpp (e.g. instantiates SthThatUsesBothReusableParts and passes to component1/2)

Причина, по которой существует папка reusable_if /, заключается в том, что и component1, и component2 хотят повторно использовать одни и те же интерфейсы (следовательно, ни один из них не «владеет» исключительно этими интерфейсами). Кроме того, предполагается, что проект действительно очень большой и нуждается в надлежащих пространствах имен для классов в каждой из папок.

Как бы вы применили пространства имен в таком проекте?
Скажем, я объявляю все классы в пространстве имен многократного использования ::reusable, Должен ли я поместить интерфейсы из reusable_if в пространство имен ::reusable или в ::reusable_if? Или, может быть, в none, так как он используется component1 и component2?

Как насчет пространств имен в component1 и component2? Есть что вспомнить?
Как насчет ключевого слова using? Допустим, я решил добавить это ::reusable_if Пространство имен. Можно поставить using reusable_if в заголовочные файлы в component1 и component2, при условии, что using ... находится внутри пространства имен ::component1 а также ::component2?

Я открыт для любых предложений, в том числе не обязательно связанных с приведенным выше примером.

5

Решение

Вот что я использую для своих проектов. Мое главное правило — каждый каталог — это пространство имен, а каждый файл — это класс, за очень немногими исключениями (иногда я группирую вспомогательные функции в подкаталогах пространства имен. detail, но без другого вложенного пространства имен).

  1. Держите весь ваш проект в едином пространстве имен верхнего уровня, названного в честь вашего проекта.

  2. Храните каждый служебный компонент в пространстве имен верхнего уровня, но в отдельном каталоге. Это единственный раз, когда я не позволяю пространствам имен перекрываться с моим деревом каталогов.

  3. Храните каждый независимо выпускаемый компонент в вашем проекте во вложенном пространстве имен, названном в честь вашего компонента. Для удобства предоставьте один заголовок, названный в честь вашего компонента и содержащий весь интерфейс компонента, либо в каталоге, соответствующем вашему пространству имен, либо непосредственно в каталоге верхнего уровня вашего проекта.

  4. Хранить реализацию каждого компонента во вложенном пространстве имен detail, В отличие от классов, пространство имен не имеет языковой поддержки для private члены, но соглашение в Boost заключается в том, что пространство имен detail не должен напрямую вызываться кодом пользователя.

Нет дальнейшего вложения, чем project::component::detail::function() или же project:::component::class.member() необходимо. Если вы предоставляете полные интерфейсы, которые облегчают ADL, вы можете повторно использовать функции компонентов внутри вашего проекта как function(x) для переменной x типа project::component::class не беспокоясь о столкновении имен.

Обратите внимание, что на языке дяди Боба: «единица повторного использования является единицей выпуска«. Каждый компонент должен обеспечивать связку взаимосвязанных и взаимозависимых классов и функций. В частности, он должен обеспечивать полный интерфейс для этого компонента. Язык C ++ будет поддерживать это через Аргумент-зависимый поиск (ADL). Смотрите эту старую колонкуПространства имен и принцип интерфейса«Хербом Саттером.

Наличие reuse_if и наличие обоих component а также reusable может быть запахом кода, если только соображения, которые вы упомянули в комментариях, на самом деле не применимы. Компонент должен быть единицей выпуска. Если бы вы могли самостоятельно использовать кусок кода, сделайте его отдельным компонентом. Если код зависит от другого куска, выпустите его вместе с этим другим кодом. См. Столбец Саттера для этих отношений зависимости.

4

Другие решения

Отказ от личного мнения. Ваш вопрос в основном требует субъективных ответов и, вероятно, будет закрыт для него, но я дам ему шанс.


Пространства имен в первую очередь полезны, чтобы избежать столкновений идентификаторов. Есть «ваше» пространство имен (mylib::) и пространства имен всех остальных (std::, boost::, icu::, …), и это примерно столько, сколько пространства имен должно быть принято.

Вы можете получить небольшую выгоду, поделив ваш проект (например, «проект вашей команды») на подпространства имен, если у вас возникает проблема со столкновением идентификаторов — в этом случае вам следует пересмотреть свою стратегию вызова ваших классов X а также Y, 😉

Вещи немного отличаются в огромный libs, как Boost. По сути, они состоят из множества различных проектов, поддерживаемых отдельными командами, поэтому существует проблема конфликтующих друг с другом идентификаторов конкретных проектов, если они все были объединены boost:: (и столкновение, возможно, не обнаруживается в случайном тестировании).

Если вы перестанете смотреть на boost::filesystem как «подпространство имен», и вместо этого посмотрите на boost:: как «обертка личности» для отдельных проектов filesystem::, thread::, program_options:: и еще много чего, так, чтобы они выглядели более «усиленно», картина становится более четкой.

4

По вопросам рекламы [email protected]