Является ли Guice @ImplementedBy злым? В некоторых случаях это уместно?

Я слышал утверждения, что " @ImplementedBy является злым", на том основании, что он нарушает концепции DI и информирует интерфейс о своих разработчиках.

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

Как прагматики, а не пуристы, когда, по вашему мнению, стоит использовать @ImplementedBy?

Ответ 1

У меня было то же самое, ick, yuck чувство @ImplementedBy НО, но в то же время это очень полезно. Spring должен сканировать все классы в списке пакетов, который вы ему даете. В Guice вам не нужно настраивать этот список пакетов для сканирования, а @ImplementedBy является ключом для этого (если не использовать связующее, чтобы связать это). Поскольку он спускается вниз по вашей иерархии объектов на первом Injector.getInstance и ударяет по интерфейсу, он затем использует @ImplementedBy, чтобы найти реализацию по умолчанию (пока в Binder ничего не происходит, переопределяя это значение по умолчанию).

Мы также используем @ImplementedBy. Мы считаем, что это очень приятно использовать, это немного ugh, но он просто работает и работает красиво, и поскольку он DI, он действительно не зависит от реализации, так как вы все равно можете переопределять привязки с новыми.

В то же время интерфейсы обычно используются все меньше и меньше с каркасами DI. Все интерфейсы DAO ушли в наш проект, и мы все еще можем поменять местами объекты для DAO. Классы java - это неявные интерфейсы для начала, которые можно издеваться, не требуя интерфейса. Теперь мы зарезервируем использование интерфейса для основного apis, чтобы быть очень четким и не загромождать его кодом реализации. Для DAO нам это больше не нужно.

Ответ 2

Обычно вы предпочитаете явные привязки по привязкам "точно в срок" (JIT). Явные привязки позволяют инжектору сканировать граф зависимостей во время создания инжектора. Это позволяет Guice выйти из строя, если зависимость отсутствует или недействительна. С привязками точно в срок, например @ImplementedBy, Guice не может сообщить о проблеме до тех пор, пока не будет выполнено привязку.

Связи JIT также плохо взаимодействуют с PrivateModules/child injectors. Хотя большинству приложений не нужны эти функции, когда вы делаете это менее болезненно, если каждое связывание принадлежит определенному модулю.

Ответ 3

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

Ответ 4

Я понимаю, почему Google сделал то, что сделал, но предпочтительная реализация чего-то не обязательно зла. Обратите внимание, что в документации указано, что она предназначена для реализации по умолчанию, а не только для нее.

Кстати, я нашел этот вопрос, потому что я искал Интернет для существующих реализаций концепции @ImplementedBy.

Я создал аннотацию @ImplementedBy для размещения на одном из моих интерфейсов. При использовании чистого, неиндексированного отражения это самый простой способ рассказать интерфейсу, какую реализацию использовать, особенно при работе с существующими API, которые только понимают интерфейсы. (интерфейс, а не реализация)

Аннотации позволяют мне генерировать некоторые действительно громоздкие генераторы с одной строкой аннотации и одной строкой внутри декоратора. Мне не нужно использовать структуру зависимостей для такой простой операции.

Ответ 5

для меня, да, это зло, если вы используете его для жесткой привязки и никогда не переустанавливаете привязку, потому что вы меняете смысл интерфейса. Я согласен с @thSoft, что это хорошо распространенная картина, но ее даже не ясно для меня, почему у нас нет аннотации @Implements. Также может быть раздражающим, что данная реализация по умолчанию не является той, которая используется во время выполнения.

Просто чтобы было ясно, что google ответила на это

Annotate types tell the injector what their default implementation type is. …

!! Он также отклоняет общие интерфейсы, такие как

@ImplementedBy(MyImpl.class)
public interface MyInterface<SIn,SOut> {}

public class MyImpl implements MyInterface<String, Integer> {}

которые обычно не выполняются только один раз. подробнее см. Внедрение общей реализации с использованием Guice.