Подтвердить что ты не робот

Где я могу разместить все эти интерфейсы?

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

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

4b9b3361

Ответ 1

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

Хорошо, теперь я предвижу причину: насмешливость.

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

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

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

Ответ 2

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

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

Ответ 3

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

Ответ 5

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

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);

}

Другой способ, которым вы могли бы это сделать без использования интерфейсов или mocks, - это сделать:

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

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