Inject injection

Post on 09-Jun-2015

1.235 views 2 download

Transcript of Inject injection

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

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

• Сервлеты 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!

Польза

Польза

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

Польза

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

•Работа с БД

Польза

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

•Работа с БД

• Код компактнее

Польза

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

•Работа с БД

• Код компактнее• Юнит тесты

Польза

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

•Работа с БД

• Код компактнее• Юнит тесты• Виднее избыток зависимостей

?

PROFIT?

• @surg

• http://speechat.co/injection

Спасибо!