Лучше ли передать функцию в качестве параметра* интерфейс *или* объект*?
Я пытаюсь убедить коллегу, что функция должна принимать интерфейс в качестве параметра, а не сам объект. Я думаю, что небольшие объекты могут быть прекрасны для передачи, но для больших Я бы дал им интерфейс и просто передал i/f, а не все.
Обратите внимание, что всегда будет только один из этих больших классов - i/f никогда не будет использоваться для другого объекта. Это просто для сокрытия реализации объекта.Согласитесь ли вы, что разделение большого класса на интерфейс(ы) является хорошей практикой?
Есть ли в этом какие-то недостатки?
Пример:
public interface class IVeryLargeClass
{
void DoSomething();
...
};
public ref class VeryLargeClass : public IVeryLargeClass
{
public:
virtual void DoSomething() { ... }
...
};
public ref class AnotherClass
{
public:
AnotherClass(VeryLargeClass^ vlc) { vlc->DoSomething(); }
// OR
AnotherClass(IVeryLargeClass^ vlc) { vlc->DoSomething(); }
};
5 ответов:
Один из первых принципов, которые вы узнаете при разработке ОО:
Программа для интерфейса, а не реализация.
Вы указываете, что "всегда будет только один из этих больших классов - i/f никогда не будет использоваться для другого объекта". Это может быть правдой в вашем случае, но я хотел бы иметь пять центов за каждый раз, когда такое утверждение оказывается неверным.
В дополнение к рассмотрению вопроса о том, может ли существовать несколько реализаций вашего интерфейса, вы следует также рассмотреть, экспортирует ли ваш конкретный объект (или может экспортировать) дополнительные методы,которые не имеют общего логического сходства с операциями, объявленными в интерфейсе. В таком случае можно просто объявить дополнительные операции в одном или нескольких дополнительных интерфейсах. Клиент, таким образом, должен только соединиться с интерфейсом, который экспортирует операции, в которых он заинтересован.
Проще говоря, интерфейсы обеспечивают средства управления связью между клиентами и услуги поставщиков.
Принцип инверсии зависимостейможно суммировать следующим образом: лучше зависеть от абстракций, чем от конкреций.
Почти всегда лучше передать интерфейс, чем передать конкретный класс.
Тем не менее, высокая когезивность по отношению к внутренним типам допустима в рамках конкретного модуля, но это очень субъективно в отношении того, когда и как вы должны передавать конкретные объекты.
Я бы предпочел избегать создания и интерфейса ради создания интерфейса. Если вы можете использовать этот интерфейс в нескольких местах, то у вас есть победитель - или если это публичная функция и класс, и вы специально хотите упростить.
Если вы передаете реализацию, Вы как бы теряете одно из преимуществ использования интерфейсов, то есть отделяете логику от реальной реализации.
Интерфейс программного модуля A намеренно держится отдельно от реализация этого модуля. То последний содержит фактический код процедуры и методы, описанные в интерфейс, как и другие "частные" переменные, процедуры и т. д.. Любой другой программный модуль B (который может быть упоминается как клиент К А) что взаимодействует с а вынужден это делать только через интерфейс. Один практическая польза от этого договоренность заключается в том, что замена реализация а другим что соответствует тем же спецификациям интерфейс не должен вызывать B к потерпеть неудачу-до тех пор, пока его использование соответствует с техническими характеристиками интерфейс (см. Также Лисков замена основа).
Другая проблема-это сам ваш очень большой класс. Это может быть не в рамках того, что вы делаете, но очень большой класс подразумевает, что он может делать слишком много в первую очередь. Можно ли преобразовать его в меньший classess, где информация, необходимая в вызываемой функции, инкапсулируется в ее собственном меньшем классе? Если вы создадите интерфейс для этого класса, вы можете обнаружить, что он гораздо более пригоден для повторного использования, чем для очень большого класса, который у вас в настоящее время есть.