2008-09-28 10 views
12

В частности, когда вы создаете пару интерфейса/разработчика, и нет никакой главной организационной проблемы (например, интерфейс должен идти в другой сборке, то есть, как рекомендовано архитектурой s #), у вас есть способ организации по умолчанию в вашей схеме пространства имен/имен?В каком пространстве имен вы должны помещать интерфейсы относительно своих разработчиков?

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

ответ

15

Ответ зависит от ваших намерений.

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

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

6

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

Interfaces 
|--IAnimal 
|--IVegetable 
|--IMineral 
MineralImplementor 
Organisms 
|--AnimalImplementor 
|--VegetableImplementor 

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

7

Обычно я поддерживаю интерфейс в том же пространстве имен, что и конкретные типы.

Но это только мое мнение, а макет пространства имен очень субъективен.

Animals 
| 
| - IAnimal 
| - Dog 
| - Cat 
Plants 
| 
| - IPlant 
| - Cactus 

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

+2

Что произойдет, если я хочу использовать другой класс Dog из другого пространства имен? Я считаю, что не очень хорошая практика иметь интерфейсы и реализацию в одном и том же пространстве имен. – 2012-04-26 15:35:31

1

(.Net) Я стараюсь поддерживать интерфейсы в отдельной «общей» сборке, поэтому я могу использовать этот интерфейс в нескольких приложениях и, чаще, в компонентах сервера моих приложений.

Что касается пространств имен, я храню их в BusinessCommon.Interfaces.

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

+0

Я тоже так делаю. У него есть дополнительный побочный эффект, позволяющий иметь «круговые ссылки» с использованием инъекции зависимостей: Foo зависит от Bar, Bar зависит от IFoo (который находится в общей сборке), а Foo вводится в Bar через DI. вуаля. – Manu 2008-09-28 22:12:14

0

Отделить интерфейсы в некотором роде (проекты в Eclipse и т. Д.), Так что легко развертывать только интерфейсы. Это позволяет вам предоставить внешний API без предоставления реализаций. Это позволяет строить зависимые проекты с минимальным количеством внешних ресурсов. Очевидно, что это больше относится к более крупным проектам, но концепция хороша во всех случаях.

3

Я предпочитаю сохранять свои интерфейсы и классы реализации в одном и том же пространстве имен.Когда это возможно, я предоставляю внутреннюю видимость классов реализации и предоставляю фабрику (обычно в виде статического заводского метода, который делегирует класс работника, с внутренним методом, который позволяет модульным тестам в сборке друзей заменять другого работника, который создает заглушки). Конечно, если конкретный класс должен быть общедоступным - например, если это абстрактный базовый класс, то это нормально; Я не вижу причин помещать ABC в собственное пространство имен.

На стороне примечания, я сильно не люблю соглашение .NET о предписывающих именах интерфейса с буквой «I.». Дело в том, что интерфейсные модели (I) Foo не являются ifoo, это просто foo. Так почему я не могу просто назвать это Foo? Затем я называю классы реализации, например, AbstractFoo, MemoryOptimizedFoo, SimpleFoo, StubFoo и т. Д.

+0

Тат довольно сложный, хотя я вижу, как он будет эффективен. Я также всегда задавался вопросом, почему люди ворчали о конвенции I .., что на самом деле имеет смысл. – 2008-09-29 00:35:30

+0

Это просто: ваш `foo` не` Foo`, а вообще-то просто реализация его части. Когда конкретная реализация `IFoo` просто реализует` IFoo`, и больше ничего не является просто подзадачей, поэтому зачем создавать отдельные правила для статистически незначимого подзаголовка? интерфейс похож на точку доступа к некоторой функциональности класса, реализующего интерфейс. То же самое можно сказать и о объекте `foo` - это как панель управления для какого-то конкретного объекта, а не самого объекта. – 2015-09-23 04:22:44

0

Обычно я разделяю их на две отдельные сборки. Одна из обычных причин для интерфейса состоит в том, чтобы ряд объектов выглядел одинаково для некоторой подсистемы вашего программного обеспечения. Например, у меня есть все мои отчеты, реализующие интерфейсы IReport. Используемый IReport используется не только для печати, но и для предварительного просмотра и выбора отдельных параметров для каждого отчета. Наконец, у меня есть коллекция IReport для использования в диалоговом окне, где пользователь выбирает, какие отчеты (и параметры настройки) они хотят распечатать.

Отчеты находятся в отдельной сборке, а IReport, механизм предварительного просмотра, механизм печати, выбор отчетов находятся в их соответствующей сборке ядра и/или сборке пользовательского интерфейса.

Если вы используете Factory Class для возврата списка доступных отчетов в сборке отчетов, то обновление программного обеспечения с помощью нового отчета становится просто вопросом копирования новой сборки отчета поверх оригинала. Вы даже можете использовать API Reflection, чтобы просто проверять список сборок для любых фабрик отчетов и таким образом создавать список отчетов.

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

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

1

Я НЕНАВИЖУ, когда я нахожу интерфейсы и реализации в том же пространстве имен/сборке. Пожалуйста, не делайте этого, если проект развивается, это боль в заднице для рефакторинга.

Когда я обращаюсь к интерфейсу, я хочу его реализовать, а не получить все его реализации.

Что может быть допустимым, это установить интерфейс с классом зависимостей (, который ссылается на интерфейс).

EDIT: @Josh, я только что прочитал последнее предложение, это запутанно! конечно, как класс зависимостей, так и тот, который его реализует, ссылается на интерфейс.Для того, чтобы сделать себе ясно, что я приведу примеры:

Приемлемая:

Интерфейс + реализации:

namespace A; 

    Interface IMyInterface 
    { 
     void MyMethod(); 
    } 

namespace A; 

    Interface MyDependentClass 
    { 
     private IMyInterface inject; 

     public MyDependentClass(IMyInterface inject) 
     { 
      this.inject = inject; 
     } 

     public void DoJob() 
     { 
      //Bla bla 
      inject.MyMethod(); 
     } 
    } 

Реализация класса:

namespace B; 

    Interface MyImplementing : IMyInterface 
    { 
     public void MyMethod() 
     { 
      Console.WriteLine("hello world"); 
     } 
    } 

НЕПРИЕМЛЕМО:

namespace A; 

    Interface IMyInterface 
    { 
     void MyMethod(); 
    } 

namespace A; 

    Interface MyImplementing : IMyInterface 
    { 
     public void MyMethod() 
     { 
      Console.WriteLine("hello world"); 
     } 
    } 

И НЕ СОЗДАВАЙТЕ проект/мусор для ваших интерфейсов! Пример: ShittyProject.Interfaces. Вы пропустили суть!

Представьте, что вы создали DLL, зарезервированную для ваших интерфейсов (200 МБ). Если вам нужно было добавить один интерфейс с двумя строками кодов, вашим пользователям придется обновлять 200 МБ только для двух немых сигнатур!

0

Я даю свой собственный опыт, который противоречит другим ответам.

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

Для меня любые вспомогательные функции и функции оператора, которые являются частью функциональности класса, должны находиться в том же пространстве имен, что и в классе, потому что они являются частью общедоступного API этого пространства имен.

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

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

Итак, спросите себя, действительно ли вы моделируете тип или структуру.