Где я могу разместить все эти интерфейсы? - PullRequest
24 голосов
/ 16 июня 2011

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

Учитывая, что я собираюсь перейти от всего лишь нескольких интерфейсов к, возможно, сотням, первое, что пришло мне в голову, было: куда мне поместить все эти интерфейсы? Должен ли я просто смешать их со всеми конкретными реализациями или поместить их в подпапку. Например, должны ли интерфейсы контроллера входить в root / Controllers / Interfaces, root / Controllers или что-то еще целиком? Что вы посоветуете?

Ответы [ 5 ]

18 голосов
/ 16 июня 2011

Прежде чем обсуждать организацию:

Что ж, теперь я предвижу причину: издеваться.

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

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

При этом я обычно организую свои интерфейсы вместе со своими классами, поскольку группировка связанных типов в одних и тех же пространствах имен, как правило, имеет смысл.Основное исключение - внутренние реализации интерфейсов - они могут быть где угодно, но я иногда создаю «внутреннюю» папку + внутреннее пространство имен, которое я использую специально для «частных» реализаций интерфейса (а также другие классы, которые являются чисто внутренней реализацией).Это помогает мне не загромождать главное пространство имен, поэтому единственными типами являются основные типы, относящиеся к самому API.

8 голосов
/ 16 июня 2011

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

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

1 голос
/ 16 июня 2011

Это зависит. Я делаю так: если вам нужно добавить зависимую стороннюю сборку, переместите конкретные версии в другую библиотеку классов. Если нет, они могут оставаться рядом в том же каталоге и пространстве имен.

0 голосов
/ 16 июня 2011

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

public interface IDataPersistor
{
    void PersistData(Data data);
}

public class Foo
{
    private IDataPersistor Persistor { get; set; }
    public Foo(IDataPersistor persistor)
    {
        Persistor = persistor;
    }

    // somewhere in the implementation we call Persistor.PersistData(data);

}

Еще один способ сделать это без использования интерфейсов или макетов - это сделать:

public class Foo
{
    public event EventHandler<PersistDataEventArgs> OnPersistData;

    // somewhere in the implementation we call OnPersistData(this, new PersistDataEventArgs(data))
}

ЗатемВ нашем тесте вы можете вместо создания макета сделать следующее:

Foo foo = new Foo();
foo.OnPersistData += (sender, e) => { // do what your mock would do here };

// finish your test

Я считаю, что это чище, чем чрезмерное использование макетов.

0 голосов
/ 16 июня 2011

Вот кое-что, с чего можно начать

http://aspalliance.com/2064_Creating_a_SOLID_Visual_Studio_Solution.all

...