Найкращі практики використання просторів імен у C ++ [закрито]


38

Я прочитав чистий код дядька Боба кілька місяців тому, і це мало глибокий вплив на спосіб написання коду. Навіть якби здавалося, що він повторює речі, які повинен знати кожен програміст, зведення їх усіх і втілення їх в життя призводить до набагато більш чіткого коду. Зокрема, я вважав, що розбиття великих функцій на багато крихітних функцій та розбиття великих класів на багато крихітних класів є надзвичайно корисними.

Тепер до питання. Приклади книги - всі на Java, тоді як я працював у С ++ останні кілька років. Як ідеї в « Чистому коді» поширюватимуться на використання просторів імен, яких у 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:: файлова система, boost :: tuples тощо - для різних бібліотек. Деякі імена "просуваються" до кореневого простору імен:

Усі визначення знаходяться у просторі імен :: boost :: tuples, але найпоширеніші імена піднімаються до простору імен :: boost з використанням декларацій. Такими назвами є: кортеж, make_tuple, прив’язати та дістати. Далі ref і cref визначаються безпосередньо у :: boost просторі імен.

Найбільша відмінність від мов із "реальними" модулями полягає в тому, наскільки поширеним є використання більш плоскої структури, що в основному відбувається, тому що так воно працює, якщо ви не докладете додаткових, конкретних зусиль для визначення вкладених імен.


+1 @Fred Nurk для повного аналізу замість одного рядка. Вам не потрібно читати книгу, щоб знати, про що йдеться. Цей потік коментарів розкриває поняття та відмінності, які можуть мати C ++ та Java-програміст у цій книзі. Коментар Clean Code в Amazon
Marlon,

8

У вас повинен бути один простір імен для всіх кодів. Це відрізняє його від зовнішнього коду щодо просторів імен.

У межах вашого основного простору імен, залежно від розміру та складності, ви можете відкривати простори під імен. Тут імена чітко означають щось у контексті, і ті ж імена можуть використовуватися в іншому контексті.

Зокрема, якщо у вас є таке загальне звучання, як FileInfo, яке означає щось конкретне в контексті, помістіть його в область імен.

Ви також можете використовувати для цього клас, хоча клас не розширюється, тому ви не можете додавати нові оголошення до класу, не змінюючи його заголовок.


3

Простори імен не є концепцією модуля, тому я використовував би їх лише там, де можуть виникнути конфлікти імен.


4
Не впевнений, що ти маєш на увазі. Чому набір пов'язаних класів, обернутих у просторі імен, не буде модулем?
Діма

У просторі імен немає обмежень. У модулі можна сказати, що до заданого класу, функції або змінної можна отримати доступ лише зсередини модуля. У просторі імен це неможливо, це лише префікс до імені.
Brainlag

3
Схоже, ми не погоджуємось з визначенням модуля . Для мене все, що об'єднує пов'язані об'єкти разом і має описову назву, - це модуль, незалежно від того, в'яне чи ні, воно забезпечує інкапсуляцію.
Діма

3
Обмеження доступу є ортогональним для модулів. Насправді у вас є успішні системи на зразок Python, які, безумовно, більше "схожі на модуль", ніж простори імен C ++, але взагалі не встановлюють обмежень доступу.
Фред Нурк

Я вважаю, що це одна з найкращих практик, перелічених у книгах Скотта Мейєра
Рафаель,

1

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

Хорошим евристикою є те, що ви використовуєте простір імен, коли виявляєте, що хочете вводити один і той же префікс для класів знову і знову. Наприклад, я нещодавно написав кілька класів під назвою OmciAttribute, OmciAlarm, OmciMe тощо, і зрозумів, що мені потрібно розбити Omci у власний простір імен.


1

Мені подобаються глибокі простори імен (що зазвичай означає три рівні).

  • Я маю назву компанії.
  • app / util / lib / тощо
  • Назва проекту / або пакет відповідно

Залежно від ситуації, я можу мати ще один рівень

  • подробиці (конкретні відомості про платформу)
  • utils (об’єкт корисності, який ще не переміщений до загальної утиліти).
  • все, що мені потрібно.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.