При рассмотрении (сформировавшейся) кодовой базы в моем новом задании существует интерфейс, и только один класс реализует его (насколько я могу сказать). Могут/должны я избавляюсь от интерфейса?
Сегодня нет. Через полгода после того, как проект станет в десять раз сложнее? Кто знает. На ваш взгляд, если это унаследованный код, мало что значит для интерфейса, реализованного один раз, но также нет смысла проводить рефакторинг, связанный с его удалением. «Если сработает, не чините».
Даже если люди не совсем согласны с количеством ошибок на 1000 строк кода, эти два кажутся коррелированными ( https://stackoverflow.com/questions/862277/what -это-отраслевой стандарт-для-ошибок-на-1000-строк-кода ). Меньше строк == меньше ошибок.
Кроме того, все, что здесь нужно сделать, это изменить имя реализации на имя интерфейса.
Если усилия по рефакторингу минимальны и сокращают код, я предпочитаю подавление интерфейса.
В дополнение к уже предоставленным хорошим ответам - если в какой-то момент в будущем этот один класс потребуется имитировать для целей тестирования, это будет намного проще сделать, когда уже есть доступный интерфейс !
Поскольку вы упомянули зрелую базу, я хотел бы привести еще один пример из реальной жизни: сеанс Hibernate.
Сеанс - это интерфейс, реализованный только одним классом: SessionImpl . Однако, если вы использовали спящий режим в прошлом или читали его исходный код, вы, вероятно, заметили, что Session используется везде, а не SessionImpl.
Это неправильный дизайн? Определенно нет. Это называется «Принцип подстановки» или «программирование на интерфейсы». Это означает, что, используя интерфейс вместо реализации, вы можете без каких-либо усилий расширять свой код, просто создавая экземпляры ваших новых классов соответственно, но всегда используя интерфейс. Будет ли все равно неправильно, если никто не создаст новый класс, реализующий Session? Нет, все равно не ошибаюсь.
Мои два цента.
Помимо причин, указанных в других ответах, только реализация интерфейса позволяет перехватывать методы путем создания прокси без использования инструментов. Это используется для ведения журнала, инкапсуляции операций в транзакции и т. Д. Он используется несколькими фреймворками.
Ни за что! У него нет вредных эффектов, и однажды кто-нибудь сможет поменять реализацию без рефакторинга тонны кода.
Я бы сказал, это зависит от обстоятельств, но в большинстве случаев интерфейс является хорошей идеей для определенных классов. Мокинг упрощается с помощью интерфейсов, и когда вы используете контейнер IoC, интерфейсы начинают иметь большой смысл, особенно когда вы начинаете реализовывать службы, совместно используемые в контейнере. После этого вы сможете отделить реализацию сервиса от класса, нуждающегося в сервисе.
Да, есть смысл в интерфейсах, поскольку в будущем может быть несколько реализаций. Вы, конечно, можете переборщить и создать интерфейсы для всего, так что нужно найти баланс.