В каком пространстве имен вы должны помещать интерфейсы относительно своих разработчиков?
В частности, когда вы создаете пару интерфейса/реализации, и нет никакой главной организационной проблемы (например, интерфейс должен идти в другой сборке, то есть, как рекомендовано архитектурой s #), у вас есть способ организации по умолчанию их в вашей схеме пространства имен/имен?
Это, очевидно, более основанный на мнениях вопрос, но я думаю, что некоторые люди думали об этом больше, и мы все можем извлечь выгоду из их выводов.
Ответы
Ответ 1
Ответ зависит от ваших намерений.
- Если вы хотите, чтобы потребитель ваших пространств имен использовал интерфейсы над конкретными реализациями, я бы рекомендовал использовать ваши интерфейсы в пространстве имен верхнего уровня с реализациями в дочернем пространстве имен
- Если потребитель должен использовать оба варианта, имейте их в одном пространстве имен.
- Если интерфейс предназначен для преимущественно специализированного использования, например создания новых реализаций, рассмотрите возможность их использования в дочернем пространстве имен, например Design или ComponentModel.
Я уверен, что есть и другие варианты, но, как и в случае с большинством проблем с пространством имен, это сводится к вариантам использования проекта, а также к классам и интерфейсам, которые он содержит.
Ответ 2
Я обычно поддерживаю интерфейс в том же пространстве имен, что и конкретные типы.
Но это просто мое мнение и макет пространства имен очень субъективны.
Animals
|
| - IAnimal
| - Dog
| - Cat
Plants
|
| - IPlant
| - Cactus
На самом деле вы ничего не получаете, перемещая один или два типа из основного пространства имен, но вы добавляете требование для одного дополнительного оператора using.
Ответ 3
Что я обычно делаю, так это создать пространство имен Interfaces на высоком уровне в моей иерархии и поместить туда все интерфейсы (я не хочу встраивать туда другие пространства имен, так как в итоге я бы использовал много пространств имен, содержащих только один интерфейс).
Interfaces
|--IAnimal
|--IVegetable
|--IMineral
MineralImplementor
Organisms
|--AnimalImplementor
|--VegetableImplementor
Это именно то, как я это делал в прошлом, и у меня не было много проблем с этим, хотя, по общему признанию, это могло бы смущать других, сидящих с моими проектами. Мне очень любопытно узнать, что делают другие люди.
Ответ 4
Я предпочитаю сохранять свои интерфейсы и классы реализации в одном и том же пространстве имен. Когда это возможно, я предоставляю внутреннюю видимость классов реализации и предоставляю factory (обычно в виде статического метода factory, который делегирует класс работника, с внутренним методом, который позволяет модульным тестам в сборке друзей заменять другой рабочий, производящий заглушки). Конечно, если конкретный класс должен быть общедоступным - например, если это абстрактный базовый класс, то этот штраф; Я не вижу причин помещать ABC в собственное пространство имен.
На стороне примечания, я сильно не люблю соглашение .NET о предваряющих именах интерфейса с буквой "I." Дело в том, что интерфейсные модели (I) Foo не являются ifoo, это просто foo. Так почему я не могу просто назвать это Foo? Затем я называю классы реализации, например, AbstractFoo, MemoryOptimizedFoo, SimpleFoo, StubFoo и т.д.
Ответ 5
(. Net) Я стараюсь поддерживать интерфейсы в отдельной "общей" сборке, поэтому я могу использовать этот интерфейс в нескольких приложениях и, чаще, в компонентах сервера моих приложений.
Что касается пространств имен, я храню их в BusinessCommon.Interfaces.
Я делаю это, чтобы гарантировать, что ни я, ни мои разработчики не захотят напрямую ссылаться на реализации.
Ответ 6
Я НЕНАВИЖУ, когда я нахожу интерфейсы и реализации в одном пространстве имен/сборке. Пожалуйста, не делайте этого, если проект развивается, это боль в заднице для рефакторинга.
Когда я ссылаюсь на интерфейс, я хочу его реализовать, а не для всех его реализаций.
Что может быть допустимым, так это поместить интерфейс со своим классом зависимостей (класс , который ссылается на интерфейс).
EDIT: @Джош, я только что прочитал последнее предложение, это сбивает с толку! конечно, как класс зависимостей, так и тот, который его реализует, ссылается на интерфейс. Чтобы я убедился, я приведу примеры:
Допустимо:
Интерфейс + реализация:
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 МБ только для двух немых сигнатур!
Ответ 7
Отделить интерфейсы каким-либо образом (проекты в Eclipse и т.д.), чтобы было легко развертывать только интерфейсы. Это позволяет вам предоставить внешний API без предоставления реализаций. Это позволяет строить зависимые проекты с минимальным количеством внешних ресурсов. Очевидно, это больше относится к более крупным проектам, но концепция хороша во всех случаях.
Ответ 8
Я обычно разделяю их на две отдельные сборки. Одна из обычных причин для интерфейса состоит в том, чтобы ряд объектов выглядел одинаково для некоторой подсистемы вашего программного обеспечения. Например, у меня есть все мои отчеты, реализующие интерфейсы IReport. Используемый IReport используется не только для печати, но и для предварительного просмотра и выбора отдельных параметров для каждого отчета. Наконец, у меня есть коллекция IReport для использования в диалоговом окне, где пользователь выбирает, какие отчеты (и параметры настройки) они хотят распечатать.
Отчеты размещаются в отдельной сборке, а IReport, механизм предварительного просмотра, механизм печати, выбор отчетов находятся в их соответствующей сборке ядра и/или сборке пользовательских интерфейсов.
Если вы используете класс Factory для возврата списка доступных отчетов в сборке отчетов, то обновление программного обеспечения с новым отчетом становится просто вопросом копирования новой сборки отчета над оригиналом. Вы даже можете использовать API Reflection, чтобы просто сканировать список сборок для любых фабрик отчетов и таким образом создавать список отчетов.
Вы также можете применить эти методы к файлам. Мое собственное программное обеспечение управляет станком для резки металла, поэтому мы используем эту идею для библиотек формы и подгонки, которые мы продаем вместе с нашим программным обеспечением.
Снова классы, реализующие основной интерфейс, должны находиться в отдельной сборке, чтобы вы могли обновлять ее отдельно от остальной части программного обеспечения.
Ответ 9
Я даю свой собственный опыт, который противоречит другим ответам.
Я стараюсь поместить все свои интерфейсы в пакет, к которому они принадлежат. Это означает, что если я переведу пакет в другом проекте, у меня есть все, что нужно для запуска пакета без каких-либо изменений.
Для меня любые вспомогательные функции и функции оператора, которые являются частью функциональности класса, должны входить в одно и то же пространство имен, что и класс, потому что они являются частью общедоступного API этого пространства имен.
Если у вас есть общие реализации, которые используют один и тот же интерфейс в разных пакетах, вам, вероятно, придется реорганизовать ваш проект.
Иногда я вижу, что в проекте есть много интерфейсов, которые могут быть преобразованы в абстрактную реализацию, а не в интерфейс.
Итак, спросите себя, действительно ли вы моделируете тип или структуру.