Да, вы должны кодировать против интерфейсов, а не известных реализаций, и да, вы должны сначала создавать интерфейсы, а не заставлять их появляться из вашего собственного кода.
Причины обеих рекомендаций в значительной степени одинаковы: компьютерное программирование в основном связано с человеческими факторами. Многие находят это удивительным, но считают: существует почти бесконечное количество различных способов решения одной и той же вычислительной проблемы, которые работают одинаково хорошо. Почти все из них совершенно невозможно понять тем, кто их не написал (или, фактически, автору вскоре).
Из этого следует, что хорошая программная инженерия в основном заключается в том, как достичь желаемого эффекта (правильных вычислений с разумной эффективностью) таким образом, чтобы впоследствии можно было работать с исходным кодом. Интерфейсы и API являются важной частью этой дисциплины: они позволяют вам думать о проблеме на одном уровне описания одновременно. Это гораздо проще, чем думать о правилах согласованности бизнеса и о реализации связанных списков одновременно, и поэтому навязывать такое разделение интересов принудительно лучше, чем разрешать клиентскому программисту использовать ваш код так, как ему нравится.
В это трудно поверить многим ковбойским программистам, которые убеждены, что они понимают все, что пишут, гораздо лучше, чем обычные мыслители, и могут справиться со всей сложностью, которая доставляет «меньшим» проблемам программистам. Незнание собственных когнитивных ограничений является чрезвычайно распространенным явлением, поэтому лучшие практики организации кода так важны (и часто игнорируются).
Повторим, интерфейсы и API-барьеры в значительной степени хороши , даже если вы сотрудничаете только с самим собой. Что касается внешних библиотек, то, если они содержат хорошо продуманный API, я не вижу проблем в его использовании, поскольку вы не ожидаете замены этой библиотеки на другую. В противном случае, обертка или антикоррупционный слой могут быть очень хорошей идеей.