Модульность: использование интерфейсов или нет? - PullRequest
4 голосов
/ 27 сентября 2010

Уже через несколько лет здравый смысл подсказывает, что лучше программировать против интерфейсов, чем против реализаций. Для кода высокого уровня это действительно кажется логичным, например, если у меня есть комплексный решатель в моем приложении, кажется, лучше иметь что-то вроде этого:

ISolver *solver = solverFactory.getSolver();
solver->solve(inputdata);

Вместо

Solver solver;
solver.solve(inputdata);

В первом коде также проще смоделировать решатель и, таким образом, провести модульное тестирование.

Но мой вопрос: на каком уровне больше не имеет смысла использовать интерфейс. Например. если у меня есть класс ComplexNumber (или класс String, или что-то еще) в моем приложении, то пишу это:

IComplexNumber *complexNumber = complexNumberFactory.create(1,2);   // 1+2i

Кажется, гораздо сложнее (особенно в отношении производительности), чем написание:

ComplexNumber complexNumber(1,2);   // 1+2i

Итак, какие элементы важны при принятии решения, следует ли что-то размещать за интерфейсом, а когда - за интерфейсом?

Ответы [ 3 ]

3 голосов
/ 27 сентября 2010

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

Причины, по которым следует отказаться от интерфейса, заключаются в том, что он усложняет работу или убивает производительность (но это не обязательно). Я бы сказал, что ваш класс IComplexNumber на самом деле делает иерархию классов более сложной, если вы не вводите MockComplexNumber, но я сомневаюсь, что такой класс будет полезен ... и, вероятно, он замедлит работу, но я бы измерил .

Но не думайте, что вам нужно все делать по-одному или что ваши решения зафиксированы в камне. Это довольно легко конвертировать в / из интерфейса.

1 голос
/ 29 сентября 2010

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

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

Может быть полезно смоделировать классы обслуживания, и вам может потребоваться несколько реализаций. Ваш solverFactory может вернуть naiveSolver, lookupSolver, генетическийSolver, mockSolver и т. Д. Здесь интерфейс бесполезен.

0 голосов
/ 27 сентября 2010

С C ++ это не имеет значения, так как c ++ имеет множественное наследование, и поэтому интерфейс является абстрактным классом, к которому вы можете добавить реализацию. Где я нашел интерфейсы, наиболее часто используемые - это Java и C #, которые имеют единственное наследование, и если вы хотите, чтобы класс реализовывал несколько вещей, только одна может быть абстрактным классом, другие должны быть интерфейсами

...