Лучше ли передать функцию в качестве параметра* интерфейс *или* объект*?


Я пытаюсь убедить коллегу, что функция должна принимать интерфейс в качестве параметра, а не сам объект. Я думаю, что небольшие объекты могут быть прекрасны для передачи, но для больших Я бы дал им интерфейс и просто передал 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 4

5 ответов:

Один из первых принципов, которые вы узнаете при разработке ОО:

Программа для интерфейса, а не реализация.

Вы указываете, что "всегда будет только один из этих больших классов - i/f никогда не будет использоваться для другого объекта". Это может быть правдой в вашем случае, но я хотел бы иметь пять центов за каждый раз, когда такое утверждение оказывается неверным.

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

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

Принцип инверсии зависимостейможно суммировать следующим образом: лучше зависеть от абстракций, чем от конкреций.

Почти всегда лучше передать интерфейс, чем передать конкретный класс.

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

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

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

Интерфейс программного модуля A намеренно держится отдельно от реализация этого модуля. То последний содержит фактический код процедуры и методы, описанные в интерфейс, как и другие "частные" переменные, процедуры и т. д.. Любой другой программный модуль B (который может быть упоминается как клиент К А) что взаимодействует с а вынужден это делать только через интерфейс. Один практическая польза от этого договоренность заключается в том, что замена реализация а другим что соответствует тем же спецификациям интерфейс не должен вызывать B к потерпеть неудачу-до тех пор, пока его использование соответствует с техническими характеристиками интерфейс (см. Также Лисков замена основа).

Http://en.wikipedia.org/wiki/Interface_ (computer_science)

Другая проблема-это сам ваш очень большой класс. Это может быть не в рамках того, что вы делаете, но очень большой класс подразумевает, что он может делать слишком много в первую очередь. Можно ли преобразовать его в меньший classess, где информация, необходимая в вызываемой функции, инкапсулируется в ее собственном меньшем классе? Если вы создадите интерфейс для этого класса, вы можете обнаружить, что он гораздо более пригоден для повторного использования, чем для очень большого класса, который у вас в настоящее время есть.