Являются ли взаимозависимые дочерние / родительские пространства имен запахом кода? - PullRequest
4 голосов
/ 15 июня 2009

Недавно я просматривал некоторые графы зависимостей для своего основного личного проекта и заметил, что у меня есть взаимозависимость между объектами во вложенных пространствах имен. Например, у меня в MyNamespace.Foo был объект, который реализовал универсальный интерфейс в MyNamespace.Foo.Interfaces с этим объектом в качестве универсального параметра в интерфейсе.

namespace MyNamespace.Foo
{
    internal class Foo : MyNamespace.Foo.Interfaces.IFoo<Foo>
    { }
}

В этом случае. инструмент анализа зависимостей (бета-версия VS2010) обоснованно рассматривает универсальное «создание экземпляров» (для обсуждения я знаю, что это не c ++) интерфейса как члена пространства имен Interfaces, которое затем зависит от его родительского пространства имен.

После некоторых размышлений с моей стороны я более или менее пришел к выводу, что мой существующий дизайн, в моем конкретном случае, является запахом кода. Я должен объединить пространство имен Interfaces с родительским пространством имен Foo. (Глупо требовать от клиентов развертывания дополнительного слоя в пространстве имен интерфейсов, если я хочу, чтобы они использовали Foo через IFoo.) Однако верно ли это в общем случае?

Как должны управляться зависимости между пространствами имен? Должны ли «более широкие» пространства имен (например, MyNamespace.Foo обычно зависеть от «более узких» пространств имен (например, MyNamespace.Foo.Interfaces), или более узкие пространства имен зависят от более широких?

Ответы [ 2 ]

2 голосов
/ 15 июня 2009

Если вы хотите отделить интерфейс от реализации, возможны параллельные пространства имен MyNamespace.Foo.Interfaces и MyNamespace.Foo.Implementation.

По умолчанию кажется, что пространство имен эквивалентно пакету или сборке: поэтому Foo и Bar будут пространствами имен для foo.dll и bar.dll соответственно.

Я добавлю префиксы в пространство имен, если я хочу высокоуровневые группировки: например, MyCorp.Server.Foo - это пространство имен для серверной стороны foo.dll, созданное MyCorp.

Обратите внимание, что я добавляю префиксы, а не суффиксы: так что MyCorp.Server.Foo вместо Foo.Server.MyCorp. Эти структурированные пространства имен соответствуют структурам папок / каталогов, в которых содержатся исходный код и проекты.

По умолчанию все файлы в пакете будут иметь одинаковое пространство имен (например, весь код в foo.dll принадлежит пространству имен MyCorp.Server.Foo). Если я когда-либо добавлю суффикс, это приведет к тому, что этот код будет скрыт от остальной части сборки. Например, код в пространстве имен MyCorp.Server.Foo.EditorTransactions существует в foo.dll, но не виден большинством других кодов в foo.dll (кроме кода, который явно использует MyCorp.Server.Foo.EditorTransactions).

2 голосов
/ 15 июня 2009

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

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

Следует также отметить, что я не думаю, что эти правила обязательно применяются к сторонним зависимостям. Например, зависимость от кода из узкого пространства имен в Spring.NET в вашем коде не является запахом кода.

...