inject injection
Embed Size (px)
TRANSCRIPT

INJECT
INJECTION

Юра Литвиненко
• Джавист• http://linkd.in/lytvynenko
• @surg

speechat.co

План

План
•Проблема

План
•Проблема• Внедрение DI

План
•Проблема• Внедрение DI
• Трудности

План
•Проблема• Внедрение DI
• Трудности •Польза

План
•Проблема• Внедрение DI
• Трудности •Польза• ??????????

План
•Проблема• Внедрение DI
• Трудности •Польза• ??????????
• PROFIT!

Проблема

Проблема: Проект

Проблема: Проект
• С 2005 года

Проблема: Проект
• С 2005 года
• До черта кода

Проблема: Проект
• С 2005 года
• До черта кода• Много технического долга

Проблема: Проект
• С 2005 года
• До черта кода• Много технического долга•Монолитный

Проблема: Монолит

Проблема: Монолит

Проблема: Монолит

Проблема: Монолит

Проблема: Монолит

Проблема: Монолит

Проблема: Монолит

Проблема: Монолит

Проблема: Монолит

Проблема: Монолит

А душа просит...

Модульность!

Модульность

Модульность

Модульность

Модульность

Модульность

А еще...

Работа с базой

Проблема: БД
void updateSmth() {
}

Проблема: БД
void updateSmth() {
IDbConnection con = getConnection();
}

Проблема: БД
void updateSmth() {
IDbConnection con = getConnection();
try {
}
}

Проблема: БД
void updateSmth() {
IDbConnection con = getConnection();
try {
// do stuff with con
}
}

Проблема: БД
void updateSmth() {
IDbConnection con = getConnection();
try {
// do stuff with con
} finally {
con.close();
}}

Проблема: БД
void updateSmth() {
// do stuff with con
}

Проблема: БД@Transactionalvoid updateSmth() {
// do stuff with con
}

План
•Проблема•Внедрение DI
• Трудности • Польза• ??????????
• PROFIT!

Что надеть?

Что надеть?выбрать

Внедрение: Выбор
• Spring
• Guice
• Pico-, nano- container
• Apache Avalon
• Apache HiveMind

Внедрение: Выбор
•Spring
•Guice
• Pico-, nano- container
• Apache Avalon
• Apache HiveMind

Внедрение: Выбор
vs

Внедрение: Выбор
vs

Внедрение: Guice
• Легковесность

Внедрение: Guice
• Легковесность• Конфигурация в коде

Внедрение: Guice
• Легковесность• Конфигурация в коде• Мультибиндинг

Внедрение: Guice
• Легковесность• Конфигурация в коде• Мультибиндинг• Упрощенное AOP

Внедрение: Guice
• Легковесность• Конфигурация в коде• Мультибиндинг• Упрощенное AOP
• RI JSR-330

Guice

Guice: Знакомство

Guice: Знакомство

Guice: Знакомство

Guice: Знакомство
•Биндинг

Guice: Знакомство
•Биндинг (binding)

Guice: Знакомство
• Биндинг (binding) – привязка интерфейса к реализации. Конфигурация зависимостей

Guice: Знакомство
• Биндинг (binding) – привязка интерфейса к реализации. Конфигурация зависимостей
•Модуль

Guice: Знакомство
• Биндинг (binding) – привязка интерфейса к реализации. Конфигурация зависимостей
• Модуль – класс, в котором происходит биндинг. Строительный элемент Guice

Guice: Биндинг в коде

Guice: Биндинг в коде
• Вовлечен компилятор

Guice: Биндинг в коде
• Вовлечен компилятор• Java

Guice: Биндинг в коде
• Вовлечен компилятор• Java
• Выразительный DSL

Guice: Биндинг в коде
• Вовлечен компилятор• Java
• Выразительный DSL
• Появился в Spring 3.1

Guice: Биндинг в коде

Guice: Биндинг в кодеbind(FlightFactory.class)

Guice: Биндинг в кодеbind(FlightFactory.class) .to(StubFlightFactory.class)

Guice: Биндинг в кодеbind(FlightFactory.class) .to(StubFlightFactory.class)
...
bind(FlightFactory.class)

Guice: Биндинг в кодеbind(FlightFactory.class) .to(StubFlightFactory.class)
...
bind(FlightFactory.class) .toInstance( )

Guice: Биндинг в кодеbind(FlightFactory.class) .to(StubFlightFactory.class)
...
bind(FlightFactory.class) .toInstance(flightFactoryMock)

Guice: Биндинг в кодеclass Foo {
...
}

Guice: Биндинг в кодеclass Foo {
@Inject FlightFactory flightFactory;
...
}

Guice: Multibinding

Guice: Multibinding
• Коллекция в качестве зависимости

Guice: Multibinding
• Коллекция в качестве зависимости• Определяется в разных модулях

Guice: Multibinding
• Коллекция в качестве зависимости• Определяется в разных модулях• По сути - поддержка плагинов

Guice: Multibinding

Guice: MultibindingMultibinder<Service> binder =

Guice: MultibindingMultibinder<Service> binder = Multibinder.newSetBinder( binder(), Service.class);

Guice: MultibindingMultibinder<Service> binder = Multibinder.newSetBinder( binder(), Service.class);
binder.addBinding()

Guice: MultibindingMultibinder<Service> binder = Multibinder.newSetBinder( binder(), Service.class);
binder.addBinding() .to(DocumentService.class);

Guice: MultibindingMultibinder<Service> binder = Multibinder.newSetBinder( binder(), Service.class);
binder.addBinding() .to(DocumentService.class);...

Guice: MultibindingMultibinder<Service> binder = Multibinder.newSetBinder( binder(), Service.class);
binder.addBinding() .to(DocumentService.class);...binder.addBinding()

Guice: MultibindingMultibinder<Service> binder = Multibinder.newSetBinder( binder(), Service.class);
binder.addBinding() .to(DocumentService.class);...binder.addBinding() .toInstance(userService);

Guice: Multibindingpublic class ServiceRegistry {
...
}

Guice: Multibindingpublic class ServiceRegistry {
@Inject private Set<Service> services;
...
}

Guice: Ошибки

Guice: Ошибки
• Ошибки сложно отследить

Guice: Ошибки
• Ошибки сложно отследить• Guice подробно разъясняет

Guice: Ошибки
• Ошибки сложно отследить• Guice подробно разъясняет
• ...в чем ошибка

Guice: Ошибки
• Ошибки сложно отследить• Guice подробно разъясняет
• ...в чем ошибка
• ...и главное - где

Например

НапримерЗабыли забиндить интерфейс UserService

Guice: Ошибкиpublic class UserManager {
}

Guice: Ошибкиpublic class UserManager {
@Inject private UserService service;
...
}

Guice: Ошибкиpublic class UserManager {
@Inject private UserService service;
...
}
inj.getInstance(UserManager.class);

Guice: ОшибкиGuice configuration errors:

Guice: ОшибкиGuice configuration errors:
1) No implementation for com.UserService was bound.

Guice: ОшибкиGuice configuration errors:
1) No implementation for com.UserService was bound. while locating com.UserService

Guice: ОшибкиGuice configuration errors:
1) No implementation for com.UserService was bound. while locating com.UserService for field at com.UserManager.service(UserManager.java:17)

Guice: ОшибкиGuice configuration errors:
1) No implementation for com.UserService was bound. while locating com.UserService for field at com.UserManager.service(UserManager.java:17) while locating com.UserManager

Guice: ОшибкиGuice configuration errors:
1) No implementation for com.UserService was bound. while locating com.UserService for field at com.UserManager.service(UserManager.java:17) while locating com.UserManager
1 error at ...

Guice: ОшибкиGuice configuration errors:
1) No implementation for com.UserService was bound. while locating com.UserService for field at com.UserManager.service(UserManager.java:17) while locating com.UserManager
1 error at ...

Guice: Ошибки...
com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1004)

Guice: Ошибки...
com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1004)
at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:961)

Guice: Ошибки...
com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1004)
at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:961)
at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1013)

Guice: Ошибки...
com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1004)
at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:961)
at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1013)
at com.jeeconf.Main.main(Main.java:21)

Guice: И еще...

Guice: А также
• Поддержка GWT (GIN)

Guice: А также
• Поддержка GWT (GIN)
• Assisted Inject

Guice: А также
• Поддержка GWT (GIN)
• Assisted Inject
• Поддержка TestNG

Guice: А также
• Поддержка GWT (GIN)
• Assisted Inject
• Поддержка TestNG
• etc...

С чего начать?

ВнедрениеServlet

ВнедрениеServlet
Struts Remoting

ВнедрениеServlet
Struts Remoting
Managers (BO)

План
• Проблема• Внедрение DI
•Трудности
•Польза• ??????????
• PROFIT!

Трудности: Struts

Трудности: Struts
• Action’ы и Controller’ы - синглтоны

Трудности: Struts
• Action’ы и Controller’ы - синглтоны
• Hardcoded

Решение: Struts

Решение: Struts
• Один базовый класс

Решение: Struts
• Один базовый класс• Явная инъекция в конструкторе

Решение: Struts
• Один базовый класс• Явная инъекция в конструкторе• Field injection

Решение: Struts
• Один базовый класс• Явная инъекция в конструкторе• Field injection
• Провайдеры

Решение: Strutsinterface Provider {
}

Решение: Strutsinterface Provider<T> {
}

Решение: Strutsinterface Provider<T> {
T get();
}

Решение: Strutsclass BaseAction extends Action {
}

Решение: Strutsclass BaseAction extends Action {
public BaseAction() {
}
}

Решение: Strutsclass BaseAction extends Action {
public BaseAction() {
Injector injector = ...;
}
}

Решение: Strutsclass BaseAction extends Action {
public BaseAction() {
Injector injector = ...;
injector.injectMembers(this);
}
}

Решение: Strutsclass MyAction extends BaseAction {
}

Решение: Strutsclass MyAction extends BaseAction {
Provider<MyManager> myManager;
}

Решение: Strutsclass MyAction extends BaseAction {
@Inject Provider<MyManager> myManager;
}

Решение: Strutsclass MyAction extends BaseAction {
@Inject Provider<MyManager> myManager;
... execute(Context context) {
}
}

Решение: Strutsclass MyAction extends BaseAction {
@Inject Provider<MyManager> myManager;
... execute(Context context) {
myManager.get().doSmth();
}
}

Трудности: Сервлет

Трудности: Сервлет
• Сервлеты 2.0 - только в web.xml
• Хак: Guice servlet

Трудности: Сервлет
• Сервлеты 2.0 - только в web.xml
• Хак: Guice servlet
• Stack overflow в некоторых случаях

Решение: Сервлет

Решение: Сервлет
• Servlet 3.0

Решение: Сервлет
• Servlet 3.0
• Программная регистрация фильтров и сервлетов

Решение: Сервлет
• Servlet 3.0
• Программная регистрация фильтров и сервлетов
• Свой API (близкий к Guice-Servlet)

Трудности: Статика

Трудности: Статика
• Большинство методов в менеджерах - статические

Трудности: Статика
• Большинство методов в менеджерах - статические
• Очень плохо тестируется

Трудности: Статика
• Большинство методов в менеджерах - статические
• Очень плохо тестируется• Некоторые лучше не трогать

Трудности: Статика
• Большинство методов в менеджерах - статические
• Очень плохо тестируется• Некоторые лучше не трогать• Вирусность

Решение: Статика

Решение: Статика
• Фасады

Решение: Статика
• Фасады (Да, кэп!)

Решение: Статика
• Фасады• Расширение - по необходимости
(Да, кэп!)

Решение: Статика
• Фасады• Расширение - по необходимости
• Более удобный API
(Да, кэп!)

Решение: Статика
• Фасады• Расширение - по необходимости
• Более удобный API
• Спрятать “checked” исключения
(Да, кэп!)

Решение: Статикаclass UserManager {
}

Решение: Статикаclass UserManager {
static User getUser(String login)
}

Решение: Статикаclass UserManager {
static User getUser(String login) throws SQLException, RetrieveFailedException { ... }}

Решение: Статикаclass UserManager {
static User getUser(String login) throws SQLException, RetrieveFailedException { ... }}
interface UserManagerFacade {
}

Решение: Статикаclass UserManager {
static User getUser(String login) throws SQLException, RetrieveFailedException { ... }}
interface UserManagerFacade {
User getUser(String userLogin);
}

Решение: Статикаclass UserManagerFacadeImpl
}

Решение: Статикаclass UserManagerFacadeImpl implements UserManagerFacade {
}

Решение: Статикаclass UserManagerFacadeImpl implements UserManagerFacade {
User getUser(String login) {
}}

Решение: Статикаclass UserManagerFacadeImpl implements UserManagerFacade {
User getUser(String login) { try {
}
}}

Решение: Статикаclass UserManagerFacadeImpl implements UserManagerFacade {
User getUser(String login) { try { return UserManager.getUser(login) }
}}

Решение: Статикаclass UserManagerFacadeImpl implements UserManagerFacade {
User getUser(String login) { try { return UserManager.getUser(login) } catch(Exception e) { }
}}

Решение: Статикаclass UserManagerFacadeImpl implements UserManagerFacade {
User getUser(String login) { try { return UserManager.getUser(login) } catch(Exception e) { // rethrow unchecked exception }
}}

не все так плохо

План• Проблема
• Внедрение DI
• Трудности •Польза
• ??????????
• PROFIT!

Польза

Польза
•Первый шаг к модульности

Польза
•Первый шаг к модульности
•Работа с БД

Польза
•Первый шаг к модульности
•Работа с БД
• Код компактнее

Польза
•Первый шаг к модульности
•Работа с БД
• Код компактнее• Юнит тесты

Польза
•Первый шаг к модульности
•Работа с БД
• Код компактнее• Юнит тесты• Виднее избыток зависимостей

?

Спасибо!