Injector.inject() рано или поздно прийдется сделать, потому что для кого-то TwitterApi будет полем, а при FieldInjection необходимо добавлять себя в контейнер.
Нет, не придётся. Нужно просто не делать TwitterApi внедряемым полем, и всё. Вы же контролируете ваш код, не так ли? :)
Опыта с DI у меня немного, поэтому на подобные грабли не наступал (пока :) )
Всё ещё впереди) я начинал со спринга, и очень долго не мог понять, что такое DI вообще и зачем нужен спринг в частности. Потом щёлкнуло, и сразу всё стало понятно)
Да, в спринге по умолчанию все бины — синглтоны. Ну это в некотором роде соответствует ментальной модели спринговой XML-конфигурации, когда вы описываете компоненты-бины. В Guice нет понятия бинов, там привязки реализаций к интерфейсам, и там создание новых копий объектов при внедрении более логично.
Без проблем. Внедрите не сам объект, а его провайдер (в терминологии Guice, в Spring, кажется, это называется Factory):
public class TwitterApi {
private final Provider<HttpClient> clientProvider;
@Inject
public TwitterApi(Provider<HttpClient> clientProvider) {
this.clientProvider = clientProvider;
}
...
}
и теперь можно использовать этот провайдер, чтобы насоздавать столько объектов, сколько нужно:
List<HttpClient> httpClients = new ArrayList<>();
for (int i = 0; i < 10; ++i) {
httpClients.add(clientProvider.get());
}
Все зависимости при этом будут разрешены автоматически. Тут ещё от scope'а привязки зависит. Если HttpClient помечен как singleton, то контейнер сам позаботится, чтобы существовал только один экземпляр объекта, и провайдер всегда будет возвращать его. Если scope не указан, объекты будут создаваться на каждый вызов get().
Есть и другие паттерны создания и внедрения объектов. Например, Guice позволяет создавать объекты таким образом, чтобы часть зависимостей объекта внедрялась, а часть передавалась из кода бизнес-логики (расширение AssistedInject). Можно делать провайдеры, которые могут выбрасывать исключения, чтобы затем обрабатывать эти исключения в коде бизнес-логики (расширение ThrowingProviders). Можно сделать привязки на множество реализаций одного интерфейса и внедрить их все сразу как Set или Map, что бывает полезно для плагинной архитектуры (расширение Multibindings). Не знаю, как с этим у Dagger, но Guice умеет всё вышеперечисленное, и это очень удобно.
public TwitterApi()
{
//Добавляем класс в граф зависимостей
Injector.inject(this);
//На этом этапе "магическим" образом client проинициализирован Dagger'ом
}
очень нехорошо. Убирая зависимость на классы бизнес-логики, вы добавляете зависимость на класс инжектора. TwitterApi невозможно будет использовать отдельно от контейнера DI.
Самым правильным способом, имхо, является использование внедрения через конструктор. Guice умеет так (да и Dagger, я думаю, тоже):
public class TwitterApi {
private final HttpClient client;
@Inject
public TwitterApi(HttpClient client) {
this.client = client;
}
...
}
и пусть теперь этот класс создаётся контейнером, когда потребуется его использование внутри проекта. Если же его нужно протестировать, в модульном тесте вы делаете просто new TwitterApi(mockClient), без всяких контейнеров. Использование контейнеров в модульных тестах, кстати, есть плохой тон.
Да, можно. Собственно, 3al привёл код, судя по всему, из какой-то стандартной сишной библиотеки. А QString внутри юникодовая, содержит 16-битные символы с суррогатными парами.
Но обучать на основе Qt… Почему бы тогда сразу не взять что-то более высокоуровневое, чем C++?
Да, learning Scalaz это один из наиболее полезных ресурсов, что я находил. Но тем не менее, это не полноценная документация по библиотеке, оно достаточно бесструктурно.
Ну я как бы и не спорю насчёт великолепности) действительно, очень здорово, что на скалу можно портировать множество замечательных идей из чистых FP-языков вроде хаскелла — показатель мощи и выразительности языка)
Возможно. С макросами мне пока не сильно приходилось играться (хотя есть задумки), а вот scalaz мне очень не понравился тем, что на него нет нормальной документации. Я, конечно, понимаю, что это довольно сложная библиотека, и документацию к ней писать тоже сложно, но тем не менее. Я ещё где-то видел очень пренебрежительное замечание то ли от одного из авторов scalaz, то ли от одного из его пользователей, что-то вроде «документация нужна только идиотам, есть же примеры». До shapeless вообще пока руки не доходили, не сталкивался ещё с его областью применения.
Ну и вообще, конечно, Scala довольно сложна для анализа, если не пользоваться уже готовым компилятором, но в идее так не прокатит из-за её внутренного устройства. Так что неудивительно, что есть куча ложноположительных срабатываний.
Если человека напрягает временная необходимость работать в эклипсе
Проблема в том, что это не необходимость. Мне не нужно изучать Ceylon, чтобы, например, устроиться на работу, это чисто изучение для себя и, может быть, для своих проектов. А потому, как мне кажется, персональный комфорт важнее.
принципиальная невозможность охватить плагином всю мощь языка его приведет в полнейшее уныние
Не приведёт. Как я уже сказал, для среднего по используемым возможностям кода идея отлично работает. Да, на чём-то сложном вроде упомянутых path-dependent types, или, из того с чем я столкнулся — введением новых типов в паттернматчинге:
x match {
case xs: List[a] =>
y match {
case ys: List[`a`] => xs ++ ys
}
}
Плагин идеи ломается, но такой код, имхо, всё-таки редок.
Kotlin очень сырой. Плюс его интероперабельность с джавой унылая, потому что требует описания того, какие методы в java-библиотеках могут возвращать null, а какие не могут. Для этого нужно писать внешние конфиги. Может я чего-то недопонял, но мне это очень не понравилось. Плюс из котлина выкинули reified generics.
На Scala я сейчас и пишу (почти только для себя, к сожалению, на работе Java). Язык мне очень нравится, и в целом он гораздо красивее и удобнее цейлона. Просто цейлон — это что-то свежее и интересное. Плагин для Scala, кстати, очень удобен. Я уже давно не сталкивался в нём с серьёзными проблемами с анализом кода.
Ceylon — это очень классный язык. В нём есть много интересных фич, отличающих его от других языков на JVM. Но вот то, что среда к нему в виде плагина к Eclipse, а не к IDEA, хоть и понятно, но ужасно плохо. После идеи эклипсом пользоваться невозможно совершенно, и поэтому я не могу писать на цейлоне вообще :(
Это микроядерная архитектура ОС. Ну плюс, возможно, юникс-вей при написании пользовательских программ. Уже давно есть такие операционные системы. У них есть свои проблемы, например, сложность разработки производительных систем на основе такой модели.
Нет, не придётся. Нужно просто не делать
TwitterApi
внедряемым полем, и всё. Вы же контролируете ваш код, не так ли? :)Всё ещё впереди) я начинал со спринга, и очень долго не мог понять, что такое DI вообще и зачем нужен спринг в частности. Потом щёлкнуло, и сразу всё стало понятно)
и теперь можно использовать этот провайдер, чтобы насоздавать столько объектов, сколько нужно:
Все зависимости при этом будут разрешены автоматически. Тут ещё от scope'а привязки зависит. Если
HttpClient
помечен как singleton, то контейнер сам позаботится, чтобы существовал только один экземпляр объекта, и провайдер всегда будет возвращать его. Если scope не указан, объекты будут создаваться на каждый вызовget()
.Есть и другие паттерны создания и внедрения объектов. Например, Guice позволяет создавать объекты таким образом, чтобы часть зависимостей объекта внедрялась, а часть передавалась из кода бизнес-логики (расширение AssistedInject). Можно делать провайдеры, которые могут выбрасывать исключения, чтобы затем обрабатывать эти исключения в коде бизнес-логики (расширение ThrowingProviders). Можно сделать привязки на множество реализаций одного интерфейса и внедрить их все сразу как
Set
илиMap
, что бывает полезно для плагинной архитектуры (расширение Multibindings). Не знаю, как с этим у Dagger, но Guice умеет всё вышеперечисленное, и это очень удобно.очень нехорошо. Убирая зависимость на классы бизнес-логики, вы добавляете зависимость на класс инжектора.
TwitterApi
невозможно будет использовать отдельно от контейнера DI.Самым правильным способом, имхо, является использование внедрения через конструктор. Guice умеет так (да и Dagger, я думаю, тоже):
и пусть теперь этот класс создаётся контейнером, когда потребуется его использование внутри проекта. Если же его нужно протестировать, в модульном тесте вы делаете просто
new TwitterApi(mockClient)
, без всяких контейнеров. Использование контейнеров в модульных тестах, кстати, есть плохой тон.QString
внутри юникодовая, содержит 16-битные символы с суррогатными парами.Но обучать на основе Qt… Почему бы тогда сразу не взять что-то более высокоуровневое, чем C++?
Выводит
даже если заменить литерал на u8.
s
это строка в UTF-8?Ну я как бы и не спорю насчёт великолепности) действительно, очень здорово, что на скалу можно портировать множество замечательных идей из чистых FP-языков вроде хаскелла — показатель мощи и выразительности языка)
Ну и вообще, конечно, Scala довольно сложна для анализа, если не пользоваться уже готовым компилятором, но в идее так не прокатит из-за её внутренного устройства. Так что неудивительно, что есть куча ложноположительных срабатываний.
Проблема в том, что это не необходимость. Мне не нужно изучать Ceylon, чтобы, например, устроиться на работу, это чисто изучение для себя и, может быть, для своих проектов. А потому, как мне кажется, персональный комфорт важнее.
Не приведёт. Как я уже сказал, для среднего по используемым возможностям кода идея отлично работает. Да, на чём-то сложном вроде упомянутых path-dependent types, или, из того с чем я столкнулся — введением новых типов в паттернматчинге:
Плагин идеи ломается, но такой код, имхо, всё-таки редок.
На Scala я сейчас и пишу (почти только для себя, к сожалению, на работе Java). Язык мне очень нравится, и в целом он гораздо красивее и удобнее цейлона. Просто цейлон — это что-то свежее и интересное. Плагин для Scala, кстати, очень удобен. Я уже давно не сталкивался в нём с серьёзными проблемами с анализом кода.
насколько я в курсе, в этом вся суть микроядра и есть — возможность замены сервисов когда необходимо.
я и сейчас это могу сделать — под линукс есть миллион графических оболочек, которые вполне реально менять, не перезагружая ОС.