2010-11-17 4 views
6

У меня лично нет объектов, реализующих интерфейсы. Для класса Task у меня не было бы ITask, у которого были только те же свойства, что и на нем.Должны ли объекты реализовывать интерфейсы?

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

Если вы используете ORM, аргумент, который говорит «Я могу изменить доступ к данным», не имеет значения, так зачем же это делать?

UPDATE:
Хороший момент был сделан в комментариях о INotifyPropertyChanged. Это была не моя точка зрения, хотя - я говорю о том, что-то вроде этого:

public interface ITask 
{ 
    int Id { get; set; } 
    string Description { get; set; } 
} 

public class Task : ITask 
{ 
    public int Id { get; set; } 
    public string Description { get; set; } 
} 
+0

Одно слово: INotifyPropertyChanged – slugster

+0

Для этого необходимы некоторые другие теги. – bmargulies

+0

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

ответ

3

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

Mocking: Это объекты ценности. Нечего насмехаться. Плюс насмешка заканчивается большой болью, чем написание строителя (на Java) или использование именованных аргументов в C#.

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

Скрытая функциональность: В целом область охватила это для меня.

+0

Не забывайте также, что XmlSerializer отказывается сериализовать интерфейсы или десериализовать интерфейс. –

+0

Как вы делаете второй пункт (Readonly views) без использования интерфейса? –

+0

Обычно я делаю вещи неизменными по умолчанию. Else clone перед тем, как передать что-то «небезопасное» или предоставить интерфейс только для чтения. –

1

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

1

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

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

var myTask = MyIoCProvider.Get<Task>(); 
var taskType = typeof(myTask); 

Непредсказуем. Принимая во внимание, что:

var myTask = MyIoCProvider.Get<ITask>(); 
var taskType = typeof(myTask); 

Дает вам задание типа, которое определенно получено из ITask.

Так интерфейсы просто дают нам способ сделать нашу систему более макетируемой.

+0

Я вижу. Однако зачем вам возвращать объекты из контейнера IoC? Мы говорим об модульном тестировании полных объектов домена данных и поведения, которые имеют зависимости от других объектов домена, и вы хотите издеваться над этими зависимостями? –

+0

В нашем случае мы имеем различие между объектами данных, такими как «Задача» и объекты бизнес-логики, такие как «TaskAssignmentManager». Чистые объекты данных не имеют в них логики, поэтому не нужно насмехаться, IoC или интерфейсы. Если бы у нас были объекты домена, которые имели как логику, но и данные, я думаю, что мы получим интерфейсы на них. – d4nt

0

Если вы думаете с точки зрения использования DomainEvents чем структур данных, таких как задача действительно нужно реализовать интерфейс

public interface IDomainEvent 
{ 
    Guid EventId { get; } 
    Guid TriggeredByEvent { get; } 
    DateTime Created { get; } 
} 

public class OrderCancelledEvent : IDomainEvent 
{ 
    Guid EventId { get; set; } 
    Guid TriggeredByEvent { get; set; } 
    DateTime Created { get; set; } 
    // And now for the specific bit 
    int OrderId { get; set; } 
} 

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

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

Смежные вопросы