2013-07-31 3 views
0

У меня есть интерфейс под названием IRepository. Этот интерфейс определяет набор таких общих методов, как:Liskov Замена Принцип и избыточные методы

IQueryable<T> Get<T>() where T : class; 
void Add<T>(T obj) where T : class; 
void Update<T>(T obj) where T : class; 
void SaveChanges(); 

У меня тогда есть класс, который реализует этот интерфейс. Этот класс фактически использует Entity Framework для реализации этих методов. Однако обновление метода избыточно, поскольку Entity Framework отслеживает изменения, сделанные для получаемых объектов, поэтому я просто получаю объект, который я хочу, обновляю, а затем вызываю SaveChanges. Однако в будущем я, возможно, захочу заменить эту конкретную реализацию IRepository чем-то другим. Который, вероятно, не будет отслеживать изменения, такие как инфраструктура Entity. Поэтому я думаю, что хочу оставить метод обновления в интерфейсе, но в моей конкретной реализации этого интерфейса просто оставьте метод, но ничего не делайте. например

public void Update<T>(T obj) where T : class 
{ 
} 

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

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

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

+0

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

+2

Приятно читать: http://blog.ploeh.dk/2012/03/26/IQueryableTisTightCoupling/ и это: http://www.cuttingedge.it/blogs/steven/pivot/ entry.php? id = 92 – Fendy

+0

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

ответ

2

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

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

Это не может быть именно то, что вы ищете, но вы получите точку ...

+0

Хорошая точка в области интерфейса. Мне нравится ваше предложение. –

+0

Учитывая ограничения многих систем типов систем, оптимальный уровень разделения интерфейсов часто отличается от того, что было бы без таких ограничений. Если разные объекты используют разные комбинации X, Y и Z, даже если некоторые из них делают все, используя интерфейс «кухонный раковина», а также свойство, которое подробно сообщает * о том, какие функции поддерживает экземпляр, может быть чище, чем необходимо определить другой тип интерфейса для каждой * комбинации * функций, которые могут быть реализованы, использовать проверки типа во время выполнения и downcasts повсюду, или и то, и другое. – supercat

1

Если я вас правильно понимаю, у вас есть одна реализация которой вы завернутые в интерфейсе. LSP - это не единственное, о чем можно беспокоиться в дизайне: я бы сказал, что KISS и YAGNI являются более фундаментальными, тогда как LSP - это всего лишь способ сохранить вещи простыми и предсказуемыми в объектно-ориентированном дизайне. Попытка разработать для любые Возможные будущие изменения в вашей системе на самом деле будут делать вашу систему сложнее изменить из-за повышенной сложности. Возможно, вы замените репозиторий альтернативной реализацией, которая нуждается в методе обновления? Тогда непременно сохраните его. Если это только возможность, отключите его прямо сейчас (и, возможно, подумайте об использовании EF напрямую).

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

+0

Я полностью согласен с тем, что KISS и YAGNI являются фундаментальными. Однако я беспокоюсь о вызове EF directy. Элемент EF системы легко развязан путем абстрагирования этого. Затем, если что-то изменится в этой области, изменения кода будут ограничены одной областью не по всему приложению. Я не вижу в этом сложностей для такого выигрыша? Также, что касается модульного тестирования, мне нужно отвлечь этот компонент доступа к данным, чтобы я мог изолировать свой код? –

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