В какое пространство имен вы должны поместить интерфейсы относительно их разработчиков? - PullRequest
12 голосов
/ 29 сентября 2008

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

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

Ответы [ 9 ]

15 голосов
/ 29 сентября 2008

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

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

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

7 голосов
/ 29 сентября 2008

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

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

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

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

6 голосов
/ 29 сентября 2008

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

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

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

3 голосов
/ 29 сентября 2008

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

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

1 голос
/ 03 сентября 2012

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

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

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

РЕДАКТИРОВАТЬ: @ Джош, я просто прочитал мое последнее предложение, это сбивает с толку! конечно, и класс зависимости, и класс, который его реализует, ссылаются на интерфейс. Для ясности приведу примеры:

Приемлемо:

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

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 МБ только для двух тупых подписчиков!

1 голос
/ 29 сентября 2008

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

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

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

0 голосов
/ 28 апреля 2016

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

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

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

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

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

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

0 голосов
/ 30 сентября 2008

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

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

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

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

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

0 голосов
/ 29 сентября 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...