Лучшие практики использования пространств имен в C ++ [закрыто]

38

Я прочитал « Чистый код» дяди Боба несколько месяцев назад, и это сильно повлияло на то, как я пишу код. Даже если бы казалось, что он повторяет вещи, которые должен знать каждый программист, объединение их всех и применение на практике приводит к гораздо более чистому коду. В частности, я обнаружил, что разделение больших функций на множество крошечных функций и разбиение больших классов на множество крошечных классов невероятно полезно.

Теперь по вопросу. Все примеры книги на Java, в то время как я работал на C ++ в течение последних нескольких лет. Как идеи Чистого кода будут распространяться на использование пространств имен, которых нет в Java? (Да, я знаю о пакетах Java, но это не совсем то же самое.)

Имеет ли смысл применять идею создания множества крошечных объектов, каждый с четко определенной ответственностью, к пространствам имен? Всегда ли небольшая группа связанных классов должна быть заключена в пространство имен? Это способ управлять сложностью наличия множества крошечных классов, или затраты на управление множеством пространств имен будут чрезмерно высокими?

Изменить: На мой вопрос ответ в этой записи Википедии о принципах пакета .

Дима
источник
7
Еще один пример хорошего и реального разработчика вопрос закрыт . Если это не сайт stackexchange, чтобы спросить о лучших разработках, то что это?
Сэм Голдберг
@SamGoldberg: становится лучше. Я нашел хороший ответ на этот вопрос здесь: en.wikipedia.org/wiki/Package_Principles . Я разместил этот ответ, а модератор удалил его, потому что я просто разместил ссылку, и у меня не было времени скопировать / вставить содержимое.
Дима
1
Я думаю, что моя единственная критика этого вопроса заключается в том, чтобы вместо того, чтобы задавать несколько вопросов в конце, попытаться обобщить его в один вопрос, например, «каковы должны быть критерии для определения того, должны ли элементы находиться в одном и том же пространстве имен или в разных пространствах имен? ».
Сэм Голдберг

Ответы:

22

(Я не читал Чистый код и не знаю много Java.)

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

Да, так же, как это происходит с рефакторингом на несколько классов и несколько функций.

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

На самом деле не отвечая: да, вы должны хотя бы использовать одно пространство имен верхнего уровня. Это может быть основано на проекте, организации или как угодно, но использование нескольких глобальных имен уменьшит конфликты имен. Единое пространство имен для группировки всего остального под ним вводит только одно глобальное имя. (Исключая внешние функции "C", но это связано с совместимостью C и влияет только на другие внешние функции "C".)

Следует ли заключить небольшую группу связанных классов в пространство имен, выделенное для них? Вероятно. Особенно если вы используете общий префикс для этих классов - FrobberThing, FrobberThang, FrobberDoohickey - вы должны рассмотреть пространство имен - frobber :: Thing и так далее. Это все еще будет в вашем корневом пространстве имен или другом пространстве имен, если они являются частью более крупного проекта.

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

Используя приведенный выше пример с префиксными именами, управлять frobber :: Thing не сложнее, чем FrobberThing. Это может быть даже проще с некоторыми инструментами, такими как документирование и завершение кода. Есть разница с ADL, но это может работать в вашу пользу: меньшее количество имен в связанных пространствах имен упрощает ADL, и вы можете использовать объявления для вставки конкретных имен в одно или другое пространство имен.

Псевдонимы пространства имен позволяют вам использовать более короткое имя для более длинного пространства имен в определенном контексте, что опять же позволяет более легкое использование:

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.
}

Рассмотрим Boost, который имеет единственное корневое пространство имен, boost, а затем множество подпространств имен - boost :: asio, boost :: io, boost :: filesystem, boost :: tuples и т. Д. - для различных библиотек. Некоторые имена «повышаются» до корневого пространства имен:

Все определения находятся в пространстве имен :: boost :: tuples, но наиболее распространенные имена поднимаются до пространства имен :: boost с помощью объявлений. Эти имена: tuple, make_tuple, tie и get. Кроме того, ref и cref определяются непосредственно в пространстве имен :: boost.

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

Фред Нурк
источник
+1 @Fred Nurk за полный анализ вместо одной строки ответов. Вам не нужно читать книгу, чтобы понять, о чем идет речь. Этот поток комментариев раскрывает понятия и различия, которые могут иметь программисты на C ++ и Java в этой книге. Чистый кодовый комментарий в Амазонке
Марлон
8

У вас должно быть одно главное пространство имен для всего вашего кода. Это отличает его от внешнего кода в отношении пространств имен.

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

В частности, если у вас есть общее звучащее имя, такое как FileInfo, которое означает что-то конкретное в контексте, поместите его в пространство имен.

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

Дойная корова
источник
3

Пространства имен не являются концепцией модуля, поэтому я буду использовать их только там, где могут возникнуть конфликты имен.

Brainlag
источник
4
Не уверен, что вы имеете в виду. Почему набор связанных классов, помещенных в пространство имен, не будет модулем?
Дима
В пространстве имен нет ограничений. В модуле вы можете сказать, что к данному классу, функции или переменной можно получить доступ только изнутри модуля. В пространстве имен это невозможно, это просто префикс к имени.
Brainlag
3
Похоже, мы не согласны с определением модуля . Для меня все, что объединяет связанные сущности вместе и имеет описательное имя, является модулем, независимо от того, обеспечивает оно инкапсуляцию или нет.
Дима
3
Ограничение доступа ортогонально модулям. На самом деле, у вас есть успешные системы, такие как Python, которые определенно более «модульны», чем пространства имен C ++, но вообще не накладывают никаких ограничений доступа.
Фред Нурк
Я считаю, что это одна из лучших практик, перечисленных в книгах Скотта Мейера
Рафаэль
1

У Java есть пространства имен, просто их так не называют. In javax.swing.* javaxявляется пространством имен и swingявляется вложенным пространством имен. Я не читал книгу, чтобы узнать, что в ней говорится о пакетах java, но те же принципы применимы в значительной степени непосредственно к пространствам имен на любом языке.

Хорошая эвристика заключается в том, что вы используете пространство имен, когда вы снова и снова хотите набирать один и тот же префикс для классов. Например, я недавно написал несколько классов под названием OmciAttribute, OmciAlarm, OmciMe и т. Д. И понял, что мне нужно разбить Omci на его собственное пространство имен.

Карл Билефельдт
источник
1

Мне нравятся глубокие пространства имен (что обычно означает три уровня).

  • У меня есть название компании.
  • приложение / Util / Lib / и т.д.
  • Название проекта / или Пакет в зависимости от ситуации

В зависимости от ситуации у меня может быть еще один уровень

  • детали (детали реализации для конкретной платформы)
  • utils (служебный объект, который еще не был перемещен в общую утилиту).
  • все что мне нужно
Мартин Йорк
источник